1

I am sending a JSON from app1 to app2 whenever a model is created in app1. I need to create a similar model in app2 along with the nested attributes. I am able to create the model but not able to figure out how to create the nested attributes model for the same in app2. How can I do that in the same controller?

models in app1

class Author
  has_many :books, dependent: :destroy
  accepts_nested_attributes_for :books
end

class Book
  belongs_to :author
end

books_controller.rb in app1

def new
  @author = Author.new
  @books = @author.books.build
  end

def create
  @author = Author.new(author_params)

  if @author.save
    redirect_to author_path(@author), notice: 'Author was successfully created.'
  else
    render :new
  end
end

def author_params
  params.require(:author).permit(:name, books_attributes: [:id, :book_name, :publisher]) if params[:author]
end

api in app1

def self.create_or_update_author_in_app2(auth)
  app2_author = {}
  app2_author[:author_id_in_app1] = auth.id
  app2_author[:name] = auth.name
  app2_author[:app2_books_attributes] = auth.books.as_json(except: 'app1_author_id')
  response = API.post( 'create_or_update_author', body: { request: { author_data: author_data, authenticate: {auth_key: key} } } )
end

models in app2

class App2Author
  has_many :app2_books
end

class App2Book
  belongs_to :app2_author
end

controller in app2

def create_or_update_author
  response = params['request']['app2_author']
  app2_author = App2Author.find_or_create_by(author_id_in_app1: response['author_id_in_app1'])
  author.update!(name: response['name'])
  app2_author.update_attributes(response['app2_books_attributes']) unless app2_author  
end

At present, App2Author instances are being created in app2 but how can I create the associated books from the same json?

response received by controller in app2

    Parameters: {"request"=>{"app2_author"=>{"author_id_in_app1"=>"16", "name"=>"Author 1", "app2_books_attributes"=>[{"id"=>"43", "book_name"=>"Book 1", "publisher"=>"Publisher 1", "created_at"=>"2019-07-25 15:26:57 +0530", "updated_at"=>"2019-07-25 15:26:57 +0530"}, 
{"id"=>"43", "book_name"=>"Book 1", "publisher"=>"Publisher 1", "created_at"=>"2019-07-25 15:26:57 +0530", "updated_at"=>"2019-07-25 15:26:57 +0530"}, 
{"id"=>"43", "book_name"=>"Book 1", "publisher"=>"Publisher 1", "created_at"=>"2019-07-25 15:26:57 +0530", "updated_at"=>"2019-07-25 15:26:57 +0530"}, 
{"id"=>"43", "book_name"=>"Book 1", "publisher"=>"Publisher 1", "created_at"=>"2019-07-25 15:26:57 +0530", "updated_at"=>"2019-07-25 15:26:57 +0530"}]}, "authenticate"=>{"auth_key"=>"my_key"}}}
4
  • Can you share the sample response from app1? Commented Jul 25, 2019 at 5:56
  • I have added the response received by app2. Commented Jul 25, 2019 at 6:34
  • can a book belong to multiple authors? Commented Jul 25, 2019 at 6:45
  • No. In my case it is one to many relationship only. Commented Jul 25, 2019 at 7:01

1 Answer 1

1

The code bellow is just an idea how you can handle this.

models in app2

class App2Author
  has_many :app2_books

  # it's better to keep business logic in models.
  def update_info(data)
    name = data['name']
    data['author_books'].each do |book|
      books << Book.new(book)
    end
    save!
  end
end

class App2Book
  belongs_to :app2_author
end

controller in app2

def create_or_update_author
  request = params['request']['author_data']
  author = App2Author.find_or_create_by(author_id_in_app1: request['author_id_in_app1'])
  author.update_info(request)
end

Anyway to be hones with you it's not a good approach. Rails has default mechanism to create associated objects. TO make it work in the right way you need:

1) add accepts_nested_attributes_for :app2_books to App2Author model.

class App2Author
  has_many :app2_books
end

2) in the first app build valid hash with parameters and send to the second app . Something like:

app2_author: { id: 1, name: 'Author name', app2_books_attributes: [:app2_author_id, :book_name, :publisher]}

3) In the second app in controller do something like this:

author = App2Author.find_or_create_by(id: params[:id])
author.update(params) #in case the params hash is valid

that will create associations automatically.

Sign up to request clarification or add additional context in comments.

4 Comments

Ok. Got it! I have one query. How can I delete author_id from each nested attribute in json?
you can specify keys while using :to_json method. apidock.com/rails/Hash/to_json Another option is to use custome method where you prepare hash with valid structure. if you find the answer helpful - please mark as a solution.
I made the changes you said but I still not able to create or update the associations. Is it because I am just trying to update_attributes and not create?
@user001 my bad. I updated 3) point. instead of using update_attributes you can use :update method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.