$50 to anyone - 1 form - multiple models, HMT w/check_boxes

Hi Guys,

Firstly apologies for posting again.

I have been through a load of headache and days deep in google trying to
find an example/solution to my problem.
A lot of good people have been helping out a lot but I still haven’t
managed to knock it over yet.

So, I am offering $50USD (via paypal) to anyone who can get this working
for me. Or I can send you something cool from Thailand (where I live)

I have the following models in a has_many :through relationship.
Job, Division, JobDivisions.

Each job can involve any number of divisions.

The 3 things I need to do:

  1. When I create a new Job I want to be able to select the appropriate
    divisions using checkboxes.
  2. I guess I will probably need to edit a job later - add/remove
    divisions
  3. The other step in ‘setting up a job’ is I have a script that builds
    a bunch of different directories depending on the divisions the job has.
    This, hopefully, will get information from the JobDivisions JOIN table -
    basically ‘how many directories for each division to build’.

Most importantly I need to work out point (1).

Maybe the only problem is that I have no idea how to use the checkbox’s
output to create new JobDivisions.

NOTES:
I am using form_for, but am wondering if I should be using form_for_tag
My tables seem to be ok - the JobDivision table has job_id:integer,
division_id:integer & one called shotamount:integer - for point (3)
above.

Please help!

Very Sincerely!, Adam

As for errors I currently get:


NoMethodError in JobsController#create

undefined method `values’ for “true”:String
RAILS_ROOT: /Users/ateale/frameworx

Application Trace | Framework Trace | Full Trace
app/controllers/jobs_controller.rb:72:in create' app/controllers/jobs_controller.rb:71:ineach_value’
app/controllers/jobs_controller.rb:71:in `create’
Request

Parameters:

{“commit”=>“Create”,
“authenticity_token”=>“c37334c050f07baa76c1daa9fcf08f0416902ce3”,
“job”=>{“job_title”=>“green”},
“divisions”=>{“1”=>“true”,
“3”=>“true”}}
Show session dump

Response

Headers:

{“cookie”=>[],
“Cache-Control”=>“no-cache”}

Here are my files so far:

##############
MODELS
##############


job.rb

class Job < ActiveRecord::Base
has_many :job_divisions
has_many :divisions, :through => :job_divisions
end


division.rb

class Division < ActiveRecord::Base
has_many :job_divisions
has_many :jobs, :through => :job_divisions
end


job_division.rb

class JobDivision < ActiveRecord::Base
belongs_to :job
belongs_to :division
end

##############
VIEWS
##############


new.html.erb

New job

<%= error_messages_for :job %>

<% form_for(@job) do |f| %>

Job Title
<%= f.text_field :job_title %>

<% Division.find(:all).each do |division| %>

<%= check_box_tag “divisions[#{division.id}]”, true,
@job.divisions.include?(division.id) %> <%= division.name %>


<% end %>

<%= f.submit "Create" %>

<% end %>

##############
CONTROLLERS
##############


jobs_controller.rb

def new
@job = Job.new

Division.find(:all).each do |c|
@job.job_divisions.build(:id => c)
end

respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @job }
end
end

def create
@job = Job.new(params[:job])
@job.user_id = session[:user_id]

params[:divisions].each_value do |k|
@job.job_divisions.build(k)
end

respond_to do |format|
if @job.save
flash[:notice] = ‘Job was successfully created.’
format.html { redirect_to(@job) }
format.xml { render :xml => @job, :status => :created, :location
=> @job }
else
format.html { render :action => “new” }
format.xml { render :xml => @job.errors, :status =>
:unprocessable_entity }
end
end
end

def update

params[:post][:tag_ids] ||= []
@job = Job.find(params[:id])

if @job.update_attributes(params[:job])
flash[:notice] = ‘Post was successfully updated.’
else
end

respond_to do |format|
if @job.update_attributes(params[:job])
flash[:notice] = ‘Job was successfully updated.’
format.html { redirect_to(@job) }
format.xml { head :ok }
else
format.html { render :action => “edit” }
format.xml { render :xml => @job.errors, :status =>
:unprocessable_entity }
end
end
end

Adam –

Is it feasible to use something like active scaffold?

If so, that’s the easiest way I know to solve this. If not, I’d still
be happy to help.

Matt

hey Matt thanks for reading my post

I’ll check that out. I was hoping to try build most of the app - from
what I had seen on the web most of this seemed built into rails.

Thanks for the link!

Adam

I was trying to do something similar and found a much better approach
than using checkboxes, which was ugly in code and UI. Check out these
Railscasts, just following these through gave me a good start:

On Jul 7, 7:47 pm, Adam T. [email protected]

Adam –

In your controller’s create, you have:

@job = Job.new(params[:job])
@job.user_id = session[:user_id]

params[:divisions].each_value do |k|
@job.job_divisions.build(k)
end

The problem is that it hasn’t created an id for the job yet, so it can’t
define the relationship between the job and the division.

You need to save the job prior to adding the divisions.

@job.save!

Hope this helps,
Matt

I think i might be getting closer!

But I am getting this error (does it mean it is trying to save the Join
table before it has created a Job? and therefore can’t reference a
job_id?) :

THE ERROR:

“You cannot call create unless the parent is saved”

Any ideas how to save the parent?

my updated Job.rb model:

class Job < ActiveRecord::Base
has_many :job_divisions
has_many :divisions, :through => :job_divisions

def self.options_for_select
self.find(:all).collect{|job| [job.job_title]}
end

def division_ids=(division_ids)
job_divisions.each do |job_divi|
# destroying the item you are enumerating over usually isn’t a
good idea.
# So this may not work:
job_divi.destroy unless division_ids.include? job_divi.division_id
end

division_ids.each do |division_id|
  self.job_divisions.create(:division_id => division_id) unless 

job_divisions.any? { |d| d.division_id == division_id }
end
end

end

updated new.html.erb view:

New job

<%= error_messages_for :job %>

<% form_for(@job) do |f| %>

Job Title
<%= text_field :job, :job_title %>

<b>Division</b><br />

<% for division in Division.find(:all) %>

<%= check_box_tag "job[division_ids][]", division.id, @job.job_divisions.include?(division) %><%= division.name%>
<% end %>

<%= f.submit "Create" %>

<% end %>

<%= link_to ‘Back’, jobs_path %>