ngw
ngw

Reputation: 1282

Empty link_to_add_association for cocoon nested attributes

I'm using simple_form with cocoon (https://github.com/nathanvda/cocoon) and everything works pretty well.

The only thing I really really dislike is the fact that I have to initialize empty instances to make it work:

def new
  @facility = Facility.friendly.find(params[:facility_slug])
  @pet = @facility.pets.build(animal: Dog.new)
  @pet.pet_pictures.build
  @pet.animal.mixtures.build
end

The last 2 lines are for making cocoon and link_to_add_association work, if I remove them link_to_add_association is completely empty.

Does anybody know how to make this a little bit more idiomatic and avoid explicitly call the build method? How can I improve this code?

Upvotes: 1

Views: 970

Answers (1)

Richard Peck
Richard Peck

Reputation: 76774

How can I improve this code?

By putting the code in the model:

#app/models/facility.rb
class Facility < ActiveRecord::Base
   def construct_pet animal
      model = animal.to_s.constantize
      pet = pets.build animal: model.send(:new)
      pet.pet_pictures.build
      pet.animal_mixtures.build
      pet
   end
end

#app/controllers/facilities_controller.rb
class FacilitiesController < ApplicationController
   def new
      @facility = Facility.find(params[:facility_slug]).construct_pet(:dog)
   end
end

The problem you have is not with cocoon, it's Rails.

Let me explain:


fields_for

You must remember that rails is object orientated, in every sense of the term.

This means that if you want to create dependent data (IE nested fields), you'll have to build the relevant associated model instances.

There is no getting around this; if you don't build the models, Rails will simply not know how to construct the fields_for methods.

When you create an associated model (IE pass data with accepts_nested_attributes_for), Rails has to have instances of the related models to pass.

If you don't build the dependent models, you don't get any related fields, and thus it won't work.

Cocoon uses fields_for in exactly the same way as you would if you "manually" did it:

enter image description here

You can see from this RailsCast and this answer I literally just wrote.

--

avoid explicitly call the build method

N'est pas possible, mon ami.

The build method creates instances of the instances associative models. If you don't want them to show (which is required to get fields_for working), you won't be able to use them.

Upvotes: 1

Related Questions