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:

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.