使用与符号,实例变量和属性相同的字符串重构Rails控制器代码

时间:2013-07-11 02:40:08

标签: ruby-on-rails ruby

我在控制器中有以下代码,我想知道将它重构为一个部分的最佳方法。

if @country
    if s.address
        s.address.country = @country
    else
        s.address = Address.create(:country => @country)
    end
end

if @state
    if s.address
        s.address.state = @state
    else
        s.address = Address.create(:state => @state)
    end
end

if @zip
    if s.address
        s.address.zip = @zip
    else
        s.address = Address.create(:zip => @zip)
    end
end

如果这里有一个变种,我会做类似

的事情
    [:country, :state, :zip].each do |location|
        ...
    end

但在这种情况下我使用的是:country,.country和@country;什么是利用它们具有相同“根”字符串的更好方法?谢谢!

2 个答案:

答案 0 :(得分:3)

[:country, :state, :zip].each do |e|
  if v = instance_variable_get("@#{e}")
    if s.address
      s.address.send(e) = v
    else
      s.address = Address.create(e => v)
    end
  end
end

答案 1 :(得分:1)

我建议:

  1. 遵循瘦控制器,胖模型最佳实践并从控制器中删除所有业务逻辑。
  2. 使用有意义的变量名称。你的例子中s是什么?如果学生 - 为什么不称它为student
  3. 假设countystate是文本值而非关联字段,我会将您的代码更改为以下内容:

    在控制器中:

    student.create_or_update_address(county: @county, state: @state, zip: @zip)
    

    在student.rb (或其他模型,如果s不是学生)

    def create_or_update_address(options)
      address_attributes = options.delete_if { |k, v| v.empty? }
    
      if address
        address.update_attributes(address_attributes)
      else
        s.address = Address.create(address_attributes)
      end
    end