0

我正在尝试推出自己的标签系统。我的设置(目前)很像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
4

1 回答 1

2

attr_accessibleattr_writer是两个完全不同的东西。前者是 Rails 4 之前的概念,您将可批量分配的属性列入白名单。后者是在您的类上创建一个实例方法,让您可以公开设置一个值,但不能读取它。

还有attr_readerattr_accessor

attr_accessor可能是您感到困惑的地方attr_accessible。此方法类似于attr_writer,不同之处在于它同时提供了读取器和写入器方法。attr_reader与它相反attr_writer,它为您提供了一个读取值但不写入值的实例方法。

于 2013-10-15T12:38:30.343 回答