我正在尝试推出自己的标签系统。我的设置(目前)很像acts_as_taggable_on,带有标签、可标记对象和标签以将一个与另一个相关联。Taggable 是一个模块,它将包含在事件、用户和可能的其他几种可标记对象中。目前我只是想把它与事件联系起来。
我正在关注Railscast #167。
在 railscast 中,虚拟属性 tag_names 可以通过attr_writer :tag_names
.
attr_accessible :tag_names
我的问题是,除非我使用(即'attr_accessible' 而不是'attr_writer'),否则我无法让tag_names 字段接受输入。
指定时attr_writer :tag_names
,我提交表单并收到错误:“无法批量分配受保护的属性:tag_names”。当我attr_accessible :tag_names
改为时,它似乎可以正常工作,但这是一个安全问题,对吧?(请注意:事件对象的数据库中没有tag_names 字段。)
为什么我不能复制 Railscast?我正在运行 Rails 3.2.11,Railscast 是从 2009 年开始的,但是我找不到任何说 attr_writer 在这个更高版本或类似的东西中已经被 attr_accessible 取代的东西。
谢谢你的帮助!
我的活动表单的相关部分:
<%= f.input :tag_names, label: "Tags (separate by commas)" %>
我的事件模型:
class Event < ActiveRecord::Base
include Taggable
# Default - order by start time
default_scope :order => 'events.start_time ASC'
belongs_to :creator, :foreign_key => "creator_id", :class_name => "User"
validates_presence_of :creator
(etc)
我的可标记模块:
module Taggable
extend ActiveSupport::Concern
included do
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings
attr_accessible :tag_names
end
def tag(name)
name.strip!
tag = Tag.find_or_create_by_name(name)
self.taggings.find_or_create_by_tag_id(tag.id)
end
def untag(name)
name.strip!
t = Tag.find_by_name(name)
self.taggings.find_by_tag_id(t).destroy
end
# Return an array of tags applied to this taggable object
def tag_list
Tag.joins(:taggings).where(taggings: {taggable_id: self})
end
# Getter method for virtual attribute tag_names
def tag_names
@tag_names || tags.map(&:name).join(', ')
end
# Setter method for virtual attribute tag_names
def tag_names=(names)
@tag_names = names.split(",").map do |n|
Tag.find_or_create_by_name(n.strip)
end
end
end