按顺序执行Rails虚拟属性设置器

时间:2010-09-20 03:33:07

标签: ruby-on-rails activerecord

我有一个带有几个虚拟属性设置器的ActiveRecord模型。我想构建一个对象,但不将其保存到数据库中。一个setter必须在其他人之前执行。怎么办?

作为一种解决方法,我分两步构建对象

@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

这似乎有效,但看起来很糟糕。还有更好的方法吗?

修改

根据neutrino的建议,我向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 个答案:

答案 0 :(得分:1)

使用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])

答案 1 :(得分:0)

我首先想到了在设置方法中删除重要属性,但是使用了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

这样,您的代码都不会改变正常的Rails样式

@other_model = @some_model.other_models.build(params[:other_model])