I am trying to created a nested form with a HABTM association and I am
unable to find an approach that works for all cases.
What I am trying to achieve is a Project form that can:
- Create a new project and create new company to associate with it
- This works perfectly
- Create a new project with an existing company via autocomplete.
- This fails because it’s looking for an existing record in the HABTM
join table before there is a project id.
Here is the SQL that comes out of this failed case:
SELECT “companies”.* FROM “companies” INNER JOIN “companies_projects” ON
“companies”.id = “companies_projects”.company_id WHERE (“companies”.“id”
IN (‘6’)) AND (“companies_projects”.project_id = NULL )
In my Project model I am using:
accepts_nested_attributes_for :companies
Is this the wrong approach to tackling this use case? I’ve read that
this is only good for 1-1 or 1-n relationships. What is the preferred
method for doing something like this?
project.rb
class Project < ActiveRecord::Base
has_and_belongs_to_many :companies
has_and_belongs_to_many :people
has_and_belongs_to_many :services
has_many :hours
accepts_nested_attributes_for :companies, :allow_destroy => true,
:reject_if => :reject_companies
def reject_companies(attributed)
attributed[‘name’].blank?
end
end
company.rb
class Company < ActiveRecord::Base
has_and_belongs_to_many :projects
has_many :people
belongs_to :account
end
#projects_controller.rb
…
POST /projects
POST /projects.xml
def create
@project = Project.new(params[:project])
@project.account_id = @current_account.id
respond_to do |format|
if @project.save
flash[:notice] = 'Project was successfully created.'
format.html { redirect_to(@project) }
format.xml { render :xml => @project, :status => :created,
:location => @project }
else
format.html { render :action => “new” }
format.xml { render :xml => @project.errors, :status =>
:unprocessable_entity }
end
end
end
…
New project form: rendered HTML
…
<!-- Here we call fields_for on the project_form builder
instance.
The block is called for each member of the tasks
collection. -->
<p>
<label
for=“project_companies_attributes_0_name”>Company
<input id="project_companies_attributes_0_name"
name=“project[companies_attributes][0][name]” size=“30”
type=“text” />
<p>
<label for="project_name">Name</label><br />
<input id="project_name" name="project[name]" size="30"
type=“text” />
<p>
<label for="project_estimate">Estimate ($)</label><br />
<input id="project_estimate" name="project[estimate]"
size=“30” type=“text” />
<p>
<label for="project_notes">Notes</label><br />
<textarea cols="28" id="project_notes" name="project[notes]"
rows=“10”>
</p>
<p>
<input id="project_submit" name="commit" type="submit"
value=“Create” />
…
Thanks in advance,
David