Forum: Ruby on Rails n:m relationship, joining table record creation issue

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
36d14958934ec98b2f84669bb60d78d3?d=identicon&s=25 Ahad L. Amdani (Guest)
on 2009-05-01 09:42
(Received via mailing list)
Hey all,

I have an n:m relationship between lpl_short_form_apps and
practice_areas. The joining table is called practices. The definitions
are as follows (minus validation/business logic):

LPLSFAs Model:
class LPLShortFormApp < ActiveRecord::Base
  has_many :practices
  has_many :practice_areas, :through => :practices
  has_many :attorneys
end
Table:
class CreateLplShortFormApps < ActiveRecord::Migration
  def self.up
    create_table :lpl_short_form_apps do |t|
      t.string :applicant_name, :null => false
      t.string :principal_business_address
      ...
      t.string :email_address, :null => false
      t.datetime :effective_date_requested
      ...
      t.timestamps
    end
  end

  def self.down
    drop_table :lpl_short_form_apps
  end
end

Practice Areas Model:
class PracticeArea < ActiveRecord::Base
  has_many :practices
  has_many :lpl_short_form_apps, :through => :practices
end
Table:
class CreatePracticeAreas < ActiveRecord::Migration
  def self.up
    create_table :practice_areas do |t|
      t.string :area
      t.integer :specialty

      t.timestamps
    end
  end

  def self.down
    drop_table :practice_areas
  end
end



Model:
class Practice < ActiveRecord::Base
  belongs_to :lpl_short_form_app, :class_name => "LPLShortFormApp"
  belongs_to :practice_areas
end
Table:
class Practices < ActiveRecord::Migration
  def self.up
    create_table :practices, :id => false do |t|
      t.integer :lplsfa_id, :null => false, :options => "CONSTRAINT
fk_practices_lplsfas REFERENCES lpl_short_form_apps(id)"
      t.integer :practice_area_id, :null => false, :options =>
"CONSTRAINT fk_practices_areas_of_practice REFERENCES practice_area
(id)"

      t.decimal :percentage, :null => false
    end
  end

  def self.down
    drop_table :practices
  end
end

I think that's the proper way to setup the relationships. If it isn't,
can someone guide me along the right method?

What I want to do, what I'm having an issue doing, is generating the
new records in the n:m relationship. By business rules, we have 30
Practice Areas set up. Each LPLSFA can have a percentage of those
areas up to 100%; so, I have a practices_controller defined with an
index that generates a form with all of the areas of practice and a
percentage field.

This is the controller code:
  def index
    @lpl_short_form_app             = LPLShortFormApp.find(session
[:lplsfa_id])
    @practice                       = Practice.new
    @practice_areas                 = PracticeArea.all
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @practice }
    end
  end


This is the index page:
<div class = "demo-long-form">
  <% form_for(@practice) do |f| %>
  <%= f.error_messages %>
  <fieldset>
    <legend>Listing all Areas of Practice for <%=
@lpl_short_form_app.applicant_name %></legend>
    <% @practice_areas.each do |practice_area| %>
    <div>
      <%= f.label practice_area.area %>
      <%= f.text_field :percentage, :id => practice_area.area %>
    </div>
    <% end %>
    <div>
      <%= f.submit 'Set' %>
    </div>
  </fieldset>
  <% end %>
</div>

So, my questions are as follows:
1. How do I have the submit button go to the "Set" action defined in
the practices_controller?
2. How do I collect/scrape each of the individual percentages from the
form so that I can validate them against a total of 100%?
3. How do I take that collection and generate a new record in the
practices table such that it joins the LPLSFA with the Practice Area?
Each LPLSFA will have all 30 practice areas, so 30 practices records,
most of which will probably be at a 0 percentage. I'm imagining
something like this:

  def set
    @practice_areas = PracticeArea.all
    @lpl_short_form_app = LPLShortFormApp.find(session[:lplsfa_id])
    @practice_areas.each do |practice_area|
      @practice_areas.lpl_short_form_apps << @lpl_short_form_app
    end
  end

I know this is a long message, but I hope it gets a fair evaluation.
It breaks down to my lack of understanding of many to many
relationships in Ruby, my lack of understanding of the form_for in
Rails, and my lack of understanding of both ruby/rails general syntax.
I have the Ruby 1.9 Pickaxe book as well as the Agile Web Dev with
Rail, 3rd ed. but having read through the beginning sections of both
books hasn't cleared this up for me.
81b61875e41eaa58887543635d556fca?d=identicon&s=25 Frederick Cheung (Guest)
on 2009-05-01 12:54
(Received via mailing list)
On Apr 30, 10:24 pm, "Ahad L. Amdani" <ahad.amd...@gmail.com> wrote:

>
> So, my questions are as follows:
> 1. How do I have the submit button go to the "Set" action defined in
> the practices_controller?

by default this form would submit to the update (if the record
existed) or create (if it didn't) url for that practice - which
doesn;t sound quite right - the model you are editing
is LPLShortFormApp as I understand it (since the list of areas is a
fixed list). if what you are doing feels like an update/edit/create i
would stick with the default set of actions rather than create a set
action

> 2. How do I collect/scrape each of the individual percentages from the
> form so that I can validate them against a total of 100%?

you're going to have to plough through the params hash. right now it
will be bust since all of your form inputs have the same name (and so
will overwrite each other). The form helpers guide (on
guides.rubyonrails.org) has information on dealing with that sort of
thing.

> 3. How do I take that collection and generate a new record in the
> practices table such that it joins the LPLSFA with the Practice Area?
> Each LPLSFA will have all 30 practice areas, so 30 practices records,
> most of which will probably be at a 0 percentage. I'm imagining
> something like this:

you're starting to get into the complex forms arena (ie a form that
does not edit/update a single row in the database). one way of going
it would be to have a method on LPLShortFormApp that took as an
argument the info from the params and created the rows in the join
table.

Fred
36d14958934ec98b2f84669bb60d78d3?d=identicon&s=25 Ahad Amdani (ahad)
on 2009-05-04 08:49
Frederick Cheung wrote:
> On Apr 30, 10:24�pm, "Ahad L. Amdani" <ahad.amd...@gmail.com> wrote:
>
>>
>> So, my questions are as follows:
>> 1. How do I have the submit button go to the "Set" action defined in
>> the practices_controller?
>
> by default this form would submit to the update (if the record
> existed) or create (if it didn't) url for that practice - which
> doesn;t sound quite right - the model you are editing
> is LPLShortFormApp as I understand it (since the list of areas is a
> fixed list). if what you are doing feels like an update/edit/create i
> would stick with the default set of actions rather than create a set
> action
>
>> 2. How do I collect/scrape each of the individual percentages from the
>> form so that I can validate them against a total of 100%?
>
> you're going to have to plough through the params hash. right now it
> will be bust since all of your form inputs have the same name (and so
> will overwrite each other). The form helpers guide (on
> guides.rubyonrails.org) has information on dealing with that sort of
> thing.
>
>> 3. How do I take that collection and generate a new record in the
>> practices table such that it joins the LPLSFA with the Practice Area?
>> Each LPLSFA will have all 30 practice areas, so 30 practices records,
>> most of which will probably be at a 0 percentage. I'm imagining
>> something like this:
>
> you're starting to get into the complex forms arena (ie a form that
> does not edit/update a single row in the database). one way of going
> it would be to have a method on LPLShortFormApp that took as an
> argument the info from the params and created the rows in the join
> table.
>
> Fred

Thanks for the assistance. I've been looking at the guides, and I found
this in 7.3 of the forms guide:

<% form_for @person do |person_form| %>
  <%= person_form.text_field :name %>
  <% for address in @person.addresses %>
  <% person_form.fields_for address, :index => address do
|address_form|%>
  <%= address_form.text_field :city %>
  <% end %>
  <% end %>
 <% end %>

I believe I can do something similar with @lpl_short_form_app.practices
:)

I'll try it out and report my results, for people who may be searching
for similar results.
36d14958934ec98b2f84669bb60d78d3?d=identicon&s=25 Ahad Amdani (ahad)
on 2009-05-06 23:13
Ahad Amdani wrote:
>
> Thanks for the assistance. I've been looking at the guides, and I found
> this in 7.3 of the forms guide:
>
> <% form_for @person do |person_form| %>
>   <%= person_form.text_field :name %>
>   <% for address in @person.addresses %>
>   <% person_form.fields_for address, :index => address do
> |address_form|%>
>   <%= address_form.text_field :city %>
>   <% end %>
>   <% end %>
>  <% end %>
>
> I believe I can do something similar with @lpl_short_form_app.practices
> :)
>
> I'll try it out and report my results, for people who may be searching
> for similar results.

My resulting solution didn't actually have much to do with this -
however, it doesn't take away any merits from this solution!

Good luck, and happy coding.
This topic is locked and can not be replied to.