Выполнение установщиков виртуальных атрибутов Rails по порядку - PullRequest
0 голосов
/ 20 сентября 2010

У меня есть модель ActiveRecord с несколькими установщиками виртуальных атрибутов. Я хочу построить объект, но не сохранить его в базе данных. Один сеттер должен выполняться раньше остальных. Как это сделать?

В качестве обходного пути я строю объект в два этапа

@other_model = @some_model.build_other_model
@other_model.setup(params[:other_model)

Где setup:

class OtherModel < ActiveRecord::Base
  def setup(other_params)
     # execute the important_attribute= setter first
    important_attribute = other_params.delete(:important_attribute)

     # set the other attributes in whatever order they occur in the params hash
    other_params.each { |k,v| self.send("#{k}=",v) }
  end
end

Кажется, это работает, но выглядит глупо. Есть ли лучший способ?

EDIT

за предложение нейтрино , я добавил метод к SomeModel:

class SomeModel < ActiveRecord::Base
  def build_other_model(other_params)
    other_model = OtherModel.new(:some_model=>self)
    other_model.setup(other_params)
    other_model
  end
end

Ответы [ 2 ]

1 голос
/ 20 сентября 2010

Хорошо, что вы выполняете эти манипуляции в методе OtherModel, потому что вы можете просто вызвать этот метод и не беспокоиться о порядке присваиваний. Поэтому я бы оставил эту часть, а просто вызвал ее из метода SomeModel:

class SomeModel < ActiveRecord::Base
  def build_other_model(other_params)
    other_model = build_other_model
    other_model.setup(other_params)
    other_model
  end
end

Так что тогда у вас будет

@other_model = @some_model.build_other_model(params[:other_model])
0 голосов
/ 15 марта 2011

Я взял вашу идею сначала удалить важный атрибут в вашем методе установки, но вместо этого использовал alias_chain_method, чтобы сделать его более прозрачным процессом:

def attributes_with_set_important_attribute_first=(attributes = {})
  # Make sure not to accidentally blank out the important_attribute when none is passed in
  if attributes.symbolize_keys!.include?(:important_attribute)
    self.important_attribute = attributes.delete(:important_attribute)
  end

  self.attributes_without_set_important_attribute_first = attributes
end

alias_method_chain :attributes=, :set_important_attribute_first

Таким образом, ваш код не должен меняться по сравнениюобычный стиль рельсов

@other_model = @some_model.other_models.build(params[:other_model])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...