rails 4 强参数和 attr_accessor 的批量分配问题

rails 4 mass assignment issue with strong params and attr_accessor

因此,我在尝试对模型使用质量分配时发现了一个奇怪的问题,该模型还具有 attr_accessor 属性,该属性正在通过质量分配的强参数哈希进行更新。我很好奇为什么会发生这种情况 - 它应该发生吗?

这是我的控制器更新方法和强参数 -

  def update
    @device = Device.find(params[:id])
    if @device.update(device_params)
      redirect_to device_path(@device)
    else
      render :edit
    end
  end

  private

  def device_params
    params.require(:device).permit(:department_id, :entity_id, :description, :device_model_id)
  end

而且我在更新对应的设备模型时,不会报错,但是更新方法后字段-department,entity会保持不变

class Device < ActiveRecord::Base
  attr_accessor :device_event, :sensor_event, :department_id

  delegate :name, to: :department, prefix: true, allow_nil: true
  delegate :name, to: :entity, prefix: true, allow_nil: true
  delegate :id, to: :department, prefix: true, allow_nil: true
  delegate :id, to: :entity, prefix: true, allow_nil: true
  delegate :firmware, to: :device_configuration, prefix: true, allow_nil: true
  delegate :sleeptime, to: :device_configuration, prefix: true, allow_nil: true

  has_many :sensors
  has_many :events
  has_many :sensor_data, through: :events
  has_many :device_data, through: :events
  belongs_to :device_type
  belongs_to :entity
  belongs_to :department
  has_one :device_configuration

  paginates_per 10

  def self.filter(params_hash)
    filter_params = ActiveSupport::HashWithIndifferentAccess.new(params_hash)
    devices = Device.where(filter_params)
  end

  def recent_sensor_event
    self.events.where(event_type_id: 1).last
  end

  def recent_device_event
    self.events.where(event_type_id: 0).last
  end
end

现在,当我删除 department_id 上的 attr_accessor 时,当在控制器中调用 @device.update 时,mass_assigned 强参数哈希将正确保存并且一切正常.我花了一段时间才弄清楚 attr_accessor 是导致批量分配失败的原因。

您的设备型号 已经 具有隐式 department_id 凭借此行:

belongs_to :department

通过 另外 声明 attr_accessor :department_id 您将用具体的 getter 和 setter 覆盖此隐式属性(及其 ActiveRecord 持久性魔法)基于 @department_id 实例变量(根本没有持久性魔法)。这可能不是你想要的。

因此,当您执行批量赋值时,@department_id 值会发生变化,但底层的 belongs_to 关联不会。因此,您观察到部门关联未在数据库中更新。

总而言之:您不需要 attr_accessor :department_id 因为 ActiveRecord 在您声明 belongs_to :department.

时会自动生成类似的东西