简体   繁体   中英

rails 4 mass assignment issue with strong params and attr_accessor

So I discovered a weird issue while trying to use mass assignment on a model that also had an attr_accessor for an attribute that was being updated through a mass assigned strong params hash. I was curious as to why this happens - and is it supposed to happen?

Here is my controller methods for update and the strong params -

  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

And when I do this in the corresponding device model being updated, it will not throw any errors, but the fields - department, and entity will remain unchanged after the update method.

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

Now when I remove the attr_accessor on department_id, the mass_assigned strong params hash will save properly when @device.update is called in the controller and all is well. It took me a while to figure out that the attr_accessors were what was tripping up the mass assignment.

Your device model already has an implicit department_id by virtue of this line:

belongs_to :department

By additionally declaring attr_accessor :department_id you are overwriting this implicit attribute (and its ActiveRecord persistence magic) with a concrete getter and setter based on a @department_id instance variable (which has no persistence magic at all). That's probably not what you had in mind.

So when you perform the mass assignment, the @department_id value will get changed, but the underlying belongs_to association will not. Hence your observation that the department association is not updated in the database.

To summarize: you don't need attr_accessor :department_id because ActiveRecord generates something similar to it automatically when you declare belongs_to :department .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM