Forum: Ruby on Rails Specify options with habtm

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.
Fc582698581884352e745d1d4c64699d?d=identicon&s=25 Joshua Muheim (josh)
on 2006-01-29 11:35
Hi all

I have the following models:

class member
  has_and_belongs_to_many :disc_jockeys
end

class disc_jockey
  has_and_belongs_to_many :members
end

The relation table is called disc_jockeys_members and has the following
fields:

disc_jockeys_members(disc_jockey_id, member_id, status)

So far, the field status can have values like valid, invalid, locked
etc., but it is not regarded yet by Rails. So I would like to integrate
it with the standard methods.

josh $ script/console
>> m = Member.find(:first)
>> m.disc_jockeys # Returns all associated disc jockeys
>> m.disc_jockeys(:status => 'valid') # Returns associated disc jockeys with the status 
valid

The 4th line above should change the query

SELECT * FROM disc_jockeys  LEFT JOIN disc_jockeys_members ON
disc_jockeys.id = disc_jockeys_members.disc_jockey_id WHERE
(disc_jockeys_members.member_id = 25 )

to

SELECT * FROM disc_jockeys  LEFT JOIN disc_jockeys_members ON
disc_jockeys.id = disc_jockeys_members.disc_jockey_id WHERE
(disc_jockeys_members.member_id = 25 and disc_jockeys_members.status =
'valid')

Now my question: What ActiveRecord method do I have to edit to reach
this goal?

Thanks for help. :-)
Josh
2ccb2f7699267d258faaafce4ee997df?d=identicon&s=25 Cody Fauser (Guest)
on 2006-01-29 19:22
(Received via mailing list)
Josh,

Try this:

m = Member.find(:first)
m.disc_jockeys.find(:all, :conditions => "disc_jockeys_members.status
= 'valid'")


On 1/29/06, Joshua Muheim <forum@josh.ch> wrote:
> end
> josh $ script/console
> to
> Josh
>
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> Rails mailing list
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
Cody Fauser
http://www.codyfauser.com
Fc582698581884352e745d1d4c64699d?d=identicon&s=25 Joshua Muheim (josh)
on 2006-01-29 19:36
Thanks really a lot! :-)
Fc582698581884352e745d1d4c64699d?d=identicon&s=25 Joshua Muheim (josh)
on 2006-01-29 20:13
OK, so far, so good. I can access the special fields of the relationship
table now like any other attribute:

>> dj = m.disc_jockeys.find(:first, :conditions => "disc_jockeys_members.status = 
'invalid'") # Invalid DJ
>> dj.status = 'valid'
>> dj.save

This ends in a fatal error:

ActiveRecord::StaleObjectError in Djs#accept_member
Attempted to update a stale object

How can I change these attributes in the habtm relationship table?

Thanks a lot. :-)
Josh
2ccb2f7699267d258faaafce4ee997df?d=identicon&s=25 Cody Fauser (Guest)
on 2006-01-30 00:09
(Received via mailing list)
Josh,

You can't update the attributes in the join table.  You could remove
the object from the collection and then re-add it with the updated
status.  Search the archives of the mailing list for more potential
solutions, as this topic has been discussed quite a bit.


On 1/29/06, Joshua Muheim <forum@josh.ch> wrote:
> Attempted to update a stale object
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
Cody Fauser
http://www.codyfauser.com
Fc582698581884352e745d1d4c64699d?d=identicon&s=25 Joshua Muheim (josh)
on 2006-01-30 22:13
Cody Fauser wrote:
> You could remove
> the object from the collection and then re-add it with the updated
> status.
Thanks for that hint; but how can I tell Rails what status it should set
in the status field of the relationship table?

I searched the mailing lists, but didn't really know what terms to
use... any suggestions? :-)
Fc582698581884352e745d1d4c64699d?d=identicon&s=25 Joshua Muheim (josh)
on 2006-01-31 13:50
Great, after hours of asking stupid questions I found out that my PDF is
corrupt and that it's missing pages 241 to 252...
So now I found in the paper back version of the book that there's a
push_with_attributes method that solves my problem. Thanks anyway. :-)
2ccb2f7699267d258faaafce4ee997df?d=identicon&s=25 Cody Fauser (Guest)
on 2006-01-31 15:37
(Received via mailing list)
Josh,

This page from the documentation has a lot of really good information
on associations:
http://api.rubyonrails.org/classes/ActiveRecord/As...


Cody

On 1/31/06, Joshua Muheim <forum@josh.ch> wrote:
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
Cody Fauser
http://www.codyfauser.com
Fc582698581884352e745d1d4c64699d?d=identicon&s=25 Joshua Muheim (josh)
on 2006-01-31 16:14
Thanks. I found now the following:

http://wrath.rubyonrails.org/pipermail/rails/2006-...

I have added this code to my application.rb (just for testing purposes,
I will outsource it to lib later when it works), but the method is not
available!

josh $ script/console
>> m=Member.find 1
>> dj = DiscJockey.find 1
>> m.disc_jockeys.push(dj)
>> m.disc_jockeys.update_attributes(dj, :status => 'xxx')

This gives me a "NoMethodError: undefined method `update_attributes' for
DiscJockey:Class". I tried also this way:

class ActiveRecord::Associations::HasAndBelongsToManyAssociation
  def update_attributes(record, join_attributes = {})
    if record.is_a? ActiveRecord::Base
      record_id = record.id
    else
      record_id = record
    end
    cols, vals = [], []
    join_attributes.each do | key, val |
      cols << key.to_s
      vals << val
    end
    col_string = cols.join(' = ?, ')
    @owner.connection().update(sanitize_sql(["UPDATE #{@join_table} SET
#{col_string} = ? WHERE #{@association_class_primary_key_name} = ? AND
#{@association_foreign_key} = ?", vals, @owner.id, record_id].flatten),
"Update Attributes")
  end
end

But it doesn't work... What's wrong here? I don't have to restart the
server when I place the stuff in controller/application.rb, do I?

Greets
Josh
2ccb2f7699267d258faaafce4ee997df?d=identicon&s=25 Cody Fauser (Guest)
on 2006-01-31 17:02
(Received via mailing list)
Josh,

I just tried it, but I added:
module ActiveRecord
### Pasted code
end

Then I put the code in my lib folder as "patch_habtm.rb". Then in my
config/environment.rb file at the bottom put:
require 'patch_habtm'.

Restart WEBrick to reload the application and give it a try.

I didn't actually try updating, but the method is there:

i = Item.find(:first)
=> #<Item:0xb73ebecc @attributes={"name"=>"hammer",
"created_on"=>"2006-01-29 13:08:25", "id"=>"1", "description"=>nil,
"created_at"=>"2006-01-29 13:08:25"}>
>> i.locations.respond_to?("update_attributes")
=> true

If you get it to work you'll probably want to create a plugin for it
and then you can just drop it into your plugins folder in each of your
projects.

On 1/31/06, Joshua Muheim <forum@josh.ch> wrote:
> >> dj = DiscJockey.find 1
>     else
> #{@association_foreign_key} = ?", vals, @owner.id, record_id].flatten),
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> Rails mailing list
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
Cody Fauser
http://www.codyfauser.com
This topic is locked and can not be replied to.