Reputation: 3281
i have a lessons table and a tags table. i associate both of the them using a has_many :through relationship and my middle table is tags_relationship.rb
class Lesson < ActiveRecord::Base
attr_accessible :title, :desc, :content, :tag_name
belongs_to :user
has_many :tag_relationships
has_many :tags, :through => :tag_relationships
end
class Tag < ActiveRecord::Base
attr_accessible :name
has_many :tag_relationships
has_many :lessons, :through => :tag_relationships
end
in one of my views, im trying to create a a virtual attribute. i have...
<div class="tags">
<%= f.label :tag_name, "Tags" %>
<%= f.text_field :tag_name, data: { autocomplete_source: tags_path} %>
</div>
but my lessons table doesn't have that attribute, tag_name, so it calls my method instead
def tag_name
????????
end
def tag_name=(name)
self.tag = Tag.find_or_initialize_by_name(name) if name.present?
end
however im not sure what to put inside the ????????. im trying to refer the :name attribute inside my tags table.
back then i used a has_many and belongs_to relationship. my lesson belonged to a tag (which was wrong) but i was able to write...
tag.name
and it worked. but since its a has_many :through now, im not sure. i tried using tags.name, Lessons.tags.name, etc but i cant seem to get it to work. how can i refer to the tags table name attribute? thank you
Upvotes: 0
Views: 858
Reputation: 106
Apologize for my bad english.
When your Lesson
was belonged to Tag
lesson had only one tag
, so your code was right. But now Lesson
has many Tag
s, and it is collection (array in simple words). So, your setter must be more complex:
def tag_names=(names)
names = if names.kind_of? String
names.split(',').map{|name| name.strip!; name.length > 0 ? name : nil}.compact
else
names
end
current_names = self.tags.map(&:name) # names of current tags
not_added = names - current_names # names of new tags
for_remove = current_names - names # names of tags that well be removed
# remove tags
self.tags.delete(self.tags.where(:name => for_remove))
# adding new
not_added.each do |name|
self.tags << Tag.where(:name => name).first || Tag.new(:name => name)
end
end
And getter method should be like this:
def tag_names
self.tags.map(&:name)
end
BTW, finders like find_by_name
are deprecated. You must use where
.
Upvotes: 2