0

Итак, я обнаружил странную проблему, пытаясь использовать массовое присвоение модели, которая также имела attr_accessor для атрибута, который обновлялся с помощью массива с сильным параметром. Мне было любопытно, почему это происходит - и это должно произойти?рельсы 4 проблема массового присвоения с сильными параметрами и attr_accessor

Вот мои методы контроллера для обновления и сильные 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 

И когда я делаю это в соответствующей модели устройства обновляется, он не будет бросать какие-либо ошибки, но поля - отдел, и после метода обновления объект останется неизменным.

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 

Теперь, когда я удаляю attr_accessor на DEPARTMENT_ID, то mass_assigned сильный PARAMS хэш сохранить должным образом, когда @ device.update называется в контроллере, и все хорошо. Мне потребовалось некоторое время, чтобы понять, что attr_accessors были тем, что приводило в движение массовое задание.

+1

Каковы поля 'Device' (поля базы данных), также вы попробовали вместо этого использовать' update_attributes'? Проверяя [этот ответ] (http://stackoverflow.com/a/27684300/312907), я чувствую, что это может вызвать проблемы, используя 'update'. Кроме того, из моего понимания, 'update' [устарело] (http://apidock.com/rails/ActiveRecord/Base/update/class) –

+0

Я изначально использовал update_attributes, но затем я нашел [это место в тех же документах ] (http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attributes), что update_attributes является псевдонимом для обновления. Но на ваш упомянутый ответ SO, update_attributes - это то, что я действительно хочу. Благодаря! – Riggeot

+0

Возможно, вы запутались в attr_accessor и attr_accessible: http://stackoverflow.com/questions/3136420/difference-between-attr-accessor-and-attr-accessible –

ответ

1

модель Устройство уже имеет неявный department_id силу этой линии:

belongs_to :department 

По дополнительно объявляющего attr_accessor :department_id вы перезаписать этот неявный атрибут (и его настойчивость магии ActiveRecord) с конкретным добытчика и setter на основе переменной экземпляра @department_id (которая вообще не имеет магии сохранения). Это, вероятно, не то, что вы имели в виду.

Поэтому, когда вы выполняете массовое присвоение, значение @department_id будет изменено, но базовая ассоциация belongs_to не будет. Следовательно, ваше наблюдение, что ассоциация отдела не обновляется в базе данных.

Подводя итог: вам не нужно attr_accessor :department_id, потому что ActiveRecord автоматически генерирует что-то похожее, когда вы объявляете belongs_to :department.

+0

Это имеет смысл. Я обнаружил, что с помощью аксессоров на месте я мог бы индивидуально выполнить '@device.entity = Entity.find (device_params [" entity_id "])' и так далее с каждым значением, а затем использовать 'if @ device.save do yada yada'. Это работало, и я предполагаю, потому что использование прямой связи с объектом идет прямо в ассоциации ActiveRecord и не использует getter/setter, сгенерированный из attr_accessor. Благодаря! – Riggeot

Смежные вопросы