我正在尝试实现Ryan Bate的railscast#167中概述的rails标记模型。 http://railscasts.com/episodes/167-more-on-virtual-attributes
这是一个很棒的系统。但是,我无法获取表单将tag_names提交给控制器。 tag_names的定义是:
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
不幸的是,在我的情况下,@ tag_names永远不会在表单提交上分配。我无法弄清楚为什么。所以它总是默认为tags.map(&:name).join('')。这意味着我无法创建文章,因为它们的tag_names不存在,我也无法在现有标签上编辑这些标签。有人可以帮忙吗?
答案 0 :(得分:1)
简而言之,您的班级缺少一个二传手(或者在Ruby术语中,一个属性编写者)。有两种方法可以定义setter并处理将空格分隔的标记名称字符串转换为Tag对象并将它们保存在数据库中。
在您的课程中,使用Ruby的attr_writer
方法定义您的setter,并将标记名称的字符串(例如"tag1 tag2 tag3"
)转换为Tag对象,并在保存后的回调中将它们保存在数据库中。您还需要一个getter,它将文章的Tag
对象数组转换为字符串表示形式,其中标记用空格分隔:
class Article << ActiveRecord::Base
# here we are delcaring the setter
attr_writer :tag_names
# here we are asking rails to run the assign_tags method after
# we save the Article
after_save :assign_tags
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
private
def assign_tags
if @tag_names
self.tags = @tag_names.split(/\s+/).map do |name|
Tag.find_or_create_by_name(name)
end
end
end
end
Tag
个对象class Article << ActiveRecord::Base
# notice that we are no longer using the after save callback
# instead, using :autosave => true, we are asking Rails to save
# the tags for this article when we save the article
has_many :tags, :through => :taggings, :autosave => true
# notice that we are no longer using attr_writer
# and instead we are providing our own setter
def tag_names=(names)
self.tags.clear
names.split(/\s+/).each do |name|
self.tags.build(:name => name)
end
end
def tag_names
tags.map(&:name).join(' ')
end
end