0

我有一个课程表和一个标签表。我使用 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 :through now,我不确定。我尝试使用 tags.name、Lessons.tags.name 等,但我似乎无法让它工作。我如何引用标签表名属性?谢谢你

4

1 回答 1

2

为我糟糕的英语道歉。

当你Lesson所属的Tag课程只有一个tag,所以你的代码是正确的。但是现在Lesson有很多Tags,而且是collection(简单来说就是数组)。因此,您的设置器必须更复杂:

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

顺便说一句,像这样的查找器find_by_name已被弃用。您必须使用where.

于 2012-04-19T21:13:16.610 回答