How can I serialize and swap ActiveRecord instances in the same Rails application?

The main idea is that I have several working instances of a Rails application, and then the main aggregate

I want to do something similar with the following pseudo pseudo-code

posts = Post.all.to_json( :include => { :comments => { :include => :blah } }) # send data to another, identical, exactly the same Rails app # ... # Fast forward to the separate but identical Rails app: # ... # remote_posts is the posts results from the first Rails app posts = JSON.parse(remote_posts) posts.each do |post| p = Post.new p = post p.save end 

I shy away from Active Resource because I have thousands of records to create, which will mean thousands of queries for each record. If there is a way to make all this a single request with an active resource, it's simple, I would like to avoid it.

  • The format does not matter. Whatever it is convenient.
  • Identifiers do not need to be sent because another application will simply create entries and assign new identifiers in the “aggregate” system.
  • The hierarchy must be preserved (for example, "Hello, another Rails application, I have genres, and each genre has an artist, and each artist has an album, and each album has songs", etc.).
+4
source share
4 answers

There are several options you could implement to make this work:

Active resource

Like others, you can use ActiveResource . After reading your comments, this seems like a solution that you want to avoid because of the multi-query aspect.

Receiving controller

You may have a controller in your second rails application that receives data and creates records from it.

 class RecordReceiver < ActiveRecord::Base def create params[:data][:posts].each do |p| Post.create(p) end end end 

You can skip this controller in the API namespace, which is a pretty clean solution if it runs correctly.

Share Database

You can share one database in two applications. This means that you will not need to send data from one model to another, it will already be there. This is the least work for you as a developer, but it may not be possible depending on your system architecture.

Two databases in each application

In each application, you can implement several databases, for example:

 #Add to database.yml other_development: adapter: mysql database: otherdb_development username: root password: host: localhost other_production: adapter: mysql database: otherdb_production username: root password: host: localhost 

Then define your models as follows:

 class Post < ActiveRecord::Base end class PostClone < ActiveRecord::Base establish_connection "other_#{RAILS_ENV}" end 

Now your Clone model will point to the current database, and the PostClone model will point to another database. Having access to both, you can copy data when you need using the basic methods of the model.

Conclusion

Since you do not want to use ActiveResource, I would recommend that you simply split the database between applications. If this is not possible, try to have two models, each of which is collected in a different database. Finally, the host controller is a valid, albeit slower option (since it must execute an HTTP request over database queries)

+3
source

Use an active resource to directly create your messages in a remote application.

http://railscasts.com/tags/19

+3
source

Not quite the answer, but a couple of ideas:

  • Instead of to_json you can call Marshal.dump with your posts.
  • You can create a controller that will receive such serialized data via HTTP on a remote rail, Marshal.load and save it (possibly with some code to solve all kinds of conflicts).

I’m not sure how marshaling will process the included data and how much work it will take on the remote side to ensure clean imports (as for records that may violate some uniqueness, etc.), but I am experimenting a bit and see.

By the way, since you asked the question in the first place, I believe that standard database replication solutions do not work for you?

+1
source

I have a similar use case and I am using ActiveResource . If you want to keep the contained objects, this is a good choice. ActiveResource provides you with a choice of JSON or XML as the wire format.

You can pack all your notes on one request. On the receiving side, you can process the request in one transaction.

Source application

  class PostsController < ApplicationController def synch @posts = Post.all(:conditions => {...}) # # Multiple posts and their child objects uploaded in one HTTP call. # Remote::Post.upload(@posts) end end # ActiveResource model for remote Post module Remote class Post < ActiveResource::Base self.site = "http://host:3000/" def self.upload posts # pass :include option to to_xml to select # hierarchy. body = posts.to_xml(:root => 'posts', :except => [:id] :include => { :genres =>{ :except => [:id], :artists => { :except => [:id], :albums => { :except => [:id], :songs => {:except => [:id] } } } } } ) post(:upload, {}, body) end end end 

Application Purpose

  class PostsController < ApplicationController def upload # # Multiple posts and their child objects are saved in one call. # Posts.create(params[:posts]) end end class Post < ActiveRecord::Base has_many :genres accepts_nested_attributes_for ::genres end class Genre < ActiveRecord::Base has_many :artists accepts_nested_attributes_for :artists end class Artist < ActiveRecord::Base has_many :songs accepts_nested_attributes_for :songs end class Album < ActiveRecord::Base has_many :albums accepts_nested_attributes_for :albums end class Songs < ActiveRecord::Base end 

Other expedited processing options at destination ARExtensions . This gem supports volumetric inserts.

Destination route

 map.resources :posts, :collection => { :upload => :post } 
+1
source

Source: https://habr.com/ru/post/1301921/


All Articles