Help On Associations Extension


#1

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.


#2

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.


#3

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.


#4

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 :slight_smile: (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


#5

couldn’t agree more. really beautiful stuff …


#6

Hi,

Got it to work. Just a litle more magic required :slight_smile: (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.