Welcome to Working With Rails

 

Discussion Forums

Discuss all things Ruby on Rails with perhaps the web's most vibrant group of Ruby on Rails enthusiasts.
Set the extra attribute in a join model with an association of has_many :through without creating two records for the joinmodel?
2 Posts
Set the extra attribute in a join model with an association of has_many :through without creating two records for the joinmodel?

Suppose you have something like this:-

class User < ActiveRecord::Base (user model)

has_many :event_users
has_many :events, :through => :event_users

end

class Event < ActiveRecord::Base (event model)

has_many :event_users
has_many :users, :through => :event_users

end

class EventUser < ActiveRecord::Base (join model)

belongs_to :event
belongs_to :user

end

Normally EventUser will have event_id and user_id column, but suppose it has one extra attribute. i.e. boolean column as "active". Now to set that active column, which is an extra attribute, we can do something like this:-

In user model

class User < ActiveRecord::Base (user model)

has_many  :event_users
has_many  :active_events, :through => :event_users,  (this we can pass as hash)
          :class_name => "Event", 
          :source => :event, 
          :conditions => ['event_users.active = ?',true]
has_many  :events, :through => :event_users

end

In the above lines you can use the code

:conditions => {'event_users.active' =>"true"}

instead of

:conditions => ['event_users.active = ?',true]

to explicitly set the attribute.

Now you can get active_events for user.

You can use something like:-

User.first.active_events(i.e- this will find the events with active = true,without generating extra records)

I tried out some code in my console and I am having difficulty translating it for my view and controller so that it gives me the same result. My console:

    @contract = Contract.new(authnum: "900700", st_date:"2012-01-01", end_date: "2012-30-06")

    @contract.save

    @code = Code.new(code_name: "S-5463", status: "Active",  description: "This and That")

    @code.save

    @codeline = @code.codelines.build(:units_alloc => "80.00", :contract => @contract)

    @codeline.save

    @codeline
    => #

Using pgadmin3 I check my codelines table and I get the same result namely:

    id    contract_id    code_id   units_alloc
    91         64            54       80.00

But if I try to run this through my contracts_controller and view I get:

    id    contract_id    code_id   units_alloc
    1         1           1               ---I think this record comes from the @contract.codes.build
    1         1                     80.00 ---I think this record comes from the @contract.codelines.build(:units_alloc => params[:units_alloc],:contract => @contract)

Here are my models:

class Contract < AR::Base

has_many :codelines
has_many :codes, :through => :codelines

accepts_nested_attributes_for :codes

attr_accessible :codes_attributes,:codes,:authnum,:st_date,:end_date

end

class Codeline < AR::Base

belongs_to :contract
belongs_to :code

end extra attribute field in this model is 'units_alloc'

class Code < AR::Base

has_many :codelines
has_many :contracts, :through => :codelines

end

The new/create action of my app/controllers/contracts_controller.rb

def new

@contract = Contract.new
@contract.codes.build
@contract.codelines.build(:units_alloc => params[:units_alloc],:contract => @contract)

end

def create

 @contract = Contract.new(params[:contract])
 if @contract.save
   flash[:success] = "New Contract has been saved"
   redirect_to @contract
 else
   @title = "You have some errors"
   render 'new'
 end

end

the partial for my view in app/views/contracts/_fields.html.haml

= f.fields_for :codes do |ff|
  .field
     = ff.label :name, "Code Name"
     %br/
     = ff.text_field :code_name
  .field
  .
  .
= f.fields_for :codelines do |ff|
  .field
    = ff.label :name, "Units Alloc"
    %br/
    = ff.text_field :units_alloc 

I think the two build statements in the new/action of the controller are creating the two records in the codelines table, but it is the only way that I can get the input fields for codes and codelines to show in the form.

Can you please have a look at this and give me some direction?

Thanks.

2 Posts
Login to add your message