rails模型关联使用has_many:through

时间:2012-04-19 20:49:11

标签: ruby-on-rails model associations has-many-through

我有课程表和标签表。我使用has_many:through关系来关联它们,我的中间表是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

在我的一个视图中,我试图创建一个虚拟属性。我有...

    <div class="tags">
        <%= f.label :tag_name, "Tags" %>
        <%= f.text_field :tag_name, data: { autocomplete_source: tags_path} %>
    </div>

但我的课程表没有该属性tag_name,所以它调用我的方法

    def tag_name
       ????????
    end

    def tag_name=(name)
        self.tag = Tag.find_or_initialize_by_name(name) if name.present?
    end
但是我不知道该把什么放在????????。我试图在我的标签表中引用:name属性。

当时我使用了has_many和belongs_to关系。我的教训属于一个标签(这是错的),但我能够写...

tag.name

它有效。但是因为它有一个has_many:到现在为止,我不确定。我尝试使用tags.name,Lessons.tags.name等,但我似乎无法让它工作。我怎么能引用标签表名属性?谢谢

1 个答案:

答案 0 :(得分:2)

为我糟糕的英语道歉。

当您的Lesson属于Tag课时,只有一个tag,因此您的代码是正确的。但是现在Lesson有很多Tag s,它是集合(简单的数组)。所以,你的二传手必须更复杂:

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

getter方法应该是这样的:

def tag_names
  self.tags.map(&:name)
end

BTW,find_by_name等发现者已被弃用。您必须使用where