Forum: Ruby on Rails Help On Associations Extension.

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.
Pedro C. (Guest)
on 2006-02-26 20:06
(Received via mailing list)
Hi to all,

I'm needing some help here ... I want to do an extension on a
has_and_belongs_to_many to build a custom add method to the
association.

i have a table locations that has a many-to-many association with a
tags tabel using a locations_tags table.

i want to add a method to the Location has_and_belongs_to_many
association so that i can do something like this on the location
model:

  myLocation.tags.add_by_names 'tag1 tag2 tag3'

On the extension i want to do something like this:

class Location < ActiveRecord::Base
  has_and_belongs_to_many :tags do
    def add_by_names tag_names
      tag_names.split(" ").each do |tag_name|
        tag = Tag.find_by_name(tag_name) || Tag.create(:name =>
tag_name)
        tags << tag unless tags.find(tag.id)
      end
    end
end

The problem is, that i cant feager out how to have access to location
tags collection inside my custom create method.

Is there a way to do this?

any help or point to some examples welcome.

thanks.
Pedro.
Josh S. (Guest)
on 2006-02-26 20:34
Hi Pedro,

I've been playing around with association extensions lately, and you
should know they aren't 100% stable yet. But they do work pretty well
for most stuff.

Something that isn't obvious is that the context for code in the
extension is the association itself. That means that a message on self
will be sent to the association object, in your example,
myLocation.tags.

Here's how I would write what you're attempting:

class Location < ActiveRecord::Base
  has_and_belongs_to_many :tags do
    def add_by_names(tag_names)
      tag_names.split(" ").each { |name| find_or_create_by_name(name) }
    end
end

That's untested but I think it should work ok. Note that I used the
dynamic finder find_or_create_by_name, which is pretty handy for just
what you're doing.

--josh


Pedro C. wrote:
> Hi to all,
>
> I'm needing some help here ... I want to do an extension on a
> has_and_belongs_to_many to build a custom add method to the
> association.
>
> i have a table locations that has a many-to-many association with a
> tags tabel using a locations_tags table.
>
> i want to add a method to the Location has_and_belongs_to_many
> association so that i can do something like this on the location
> model:
>
>   myLocation.tags.add_by_names 'tag1 tag2 tag3'
>
> On the extension i want to do something like this:
>
> class Location < ActiveRecord::Base
>   has_and_belongs_to_many :tags do
>     def add_by_names tag_names
>       tag_names.split(" ").each do |tag_name|
>         tag = Tag.find_by_name(tag_name) || Tag.create(:name =>
> tag_name)
>         tags << tag unless tags.find(tag.id)
>       end
>     end
> end
>
> The problem is, that i cant feager out how to have access to location
> tags collection inside my custom create method.
>
> Is there a way to do this?
>
> any help or point to some examples welcome.
>
> thanks.
> Pedro.
Pedro C. (Guest)
on 2006-02-27 01:19
(Received via mailing list)
Hi Josh,

I tried the code you sent, but its only saving the tag records and not
the association itself (the locations_tags record)...

The myLocations.tags does not contain the new tags after calling:

myLocation.tags.add_by_names

Any sugestions?

thanks.
Pedro.
Pedro C. (Guest)
on 2006-02-27 01:40
(Received via mailing list)
Hi,

Got it to work. Just a litle more magic required :) (added  self << find
... )

class Location < ActiveRecord::Base
 has_and_belongs_to_many :tags do
   def add_by_names(tag_names)
     self << tag_names.split(" ").each { |name|
find_or_create_by_name(name) }
   end
end

thanks a lot for you help.
Pedro.
Josh S. (Guest)
on 2006-02-27 02:36
Oh cool, nice work. I didn't know that part of the incantation. That
looks so pretty. I'm really starting to like association extensions a
lot.

--josh

Pedro C. wrote:
> Got it to work. Just a litle more magic required :) (added  self << find
> ... )
>
> class Location < ActiveRecord::Base
>  has_and_belongs_to_many :tags do
>    def add_by_names(tag_names)
>      self << tag_names.split(" ").each { |name| find_or_create_by_name(name) }
>    end
> end
Pedro C. (Guest)
on 2006-02-27 11:56
(Received via mailing list)
couldn't agree more. really beautiful stuff ...
This topic is locked and can not be replied to.