Rails 应用程序中的虚拟属性 - 为什么attr_writer不让我的输入与我的 getter 和 setter 方



我正在尝试滚动自己的标记系统。我的设置(目前)很像acts_as_taggable_on,使用标签、可标记对象和标记将一个与另一个相关联。可标记是一个模块,它将包含在事件、用户以及可能还有一些其他类型的可标记对象中。目前,我只是想将其与事件连接起来。

我正在关注 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

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

还有attr_readerattr_accessor.

attr_accessor 也许是你与attr_accessible混淆的地方。此方法与attr_writer类似,只是它同时提供读取器和写入器方法。 attr_readerattr_writer 相反,因为它为您提供了一个实例方法,用于读取值,但不写入值。

最新更新