【问题标题】:ruby elegant way to reduce similar codes when assign attributesruby 优雅的方式来减少分配属性时的类似代码
【发布时间】:2013-10-17 18:34:16
【问题描述】:

我想为一个人的名字分配许多属性,如果属性为空,则更新它,但如果该属性已经有值,则跳过它。代码如下所示:

self.first = first_parsed unless self.first
self.middle = middle_parsed unless self.middle
self.last = last_parsed unless self.last
self.title = title_parsed unless self.title
self.suffix = suffix_parsed unless self.suffix

有什么优雅的方法可以避免重复代码吗?

【问题讨论】:

    标签: ruby variable-assignment


    【解决方案1】:
    %w(first middle last title suffix).each do |m|
      self.send("#{m}=",eval("#{m}_parsed")) unless self.send(m)
    end
    

    短代码测试:

    class Foo
      attr_accessor :first,:middle
      def meth(first_parsed,middle_parsed)
        %w(first middle).each do |m|
          self.send("#{m}=",eval("#{m}_parsed")) unless self.send(m)
        end
      end
    end
    
    foo = Foo.new
    foo.meth(11,'wax')
    foo.first # => 11
    foo.middle # => "wax"
    

    【讨论】:

    • 在示例中evaluation 传递给发送的参数只是缺乏意义;)
    【解决方案2】:
    %w[ first middle last title suffix ].each do |a|
      send("#{a}=", send("#{a}_parsed")) unless send(a)
    end
    

    【讨论】:

      【解决方案3】:

      通常,在 Ruby 中,我们会使用:

      self.first ||= first_parsed
      self.middle ||= middle_parsed
      self.last ||= last_parsed
      self.title ||= title_parsed
      self.suffix ||= suffix_parsed
      

      如果我要更动态地执行此操作,我会执行以下操作:

      class SomeClass
      
        def initialize(first_name=nil, middle_name=nil, last_name=nil, title=nil, suffix=nil)
          @first_name, @middle_name, @last_name, @title, @suffix = first_name, middle_name, last_name, title, suffix
        end
      
        def update(first_parsed, middle_parsed, last_parsed, title_parsed, suffix_parsed)
          {
            :first_name  => first_parsed,
            :middle_name => middle_parsed,
            :last_name   => last_parsed,
            :title       => title_parsed,
            :suffix      => suffix_parsed
          }.each{ |k, v|
            instance_var = "@#{ k }"
            self.instance_variable_set(instance_var, v) unless self.instance_variable_get(instance_var)
          }
        end
      
      end
      

      使用它:

      some_class_instance = SomeClass.new('foo', 'bar')
      some_class_instance
      # => #<SomeClass:0x007fcb030941a8
      #     @first_name="foo",
      #     @last_name=nil,
      #     @middle_name="bar",
      #     @suffix=nil,
      #     @title=nil>
      
      some_class_instance.update(
        *%w[
          new_first
          new_middle
          new_last
          new_title
          new_suffix
        ]
      )
      
      some_class_instance
      # => #<SomeClass:0x007fcb030941a8
      #     @first_name="foo",
      #     @last_name="new_last",
      #     @middle_name="bar",
      #     @suffix="new_suffix",
      #     @title="new_title">
      

      我更喜欢使用某种可视化映射,这就是符号到变量的散列存在的原因。使用字符串解析可以更动态地执行此操作,但是当算法的某些部分出现问题时,这可能会导致维护问题,而您可以判断的唯一方法是在循环内打印。使用这样的表可以很容易地搜索特定的 kev/值关系。

      问题是,当我们生成代码以动态执行此操作时,我们可能已经编写了一个简单的基于||= 的块,然后继续前进。调试时间会减少,很明显什么会影响什么,所有这些都会提高可维护性。所以,我不确定从长远来看,更具活力是否真的能买到任何有用的东西。这是我们在编写代码时经常做出的权衡之一。

      【讨论】:

        【解决方案4】:

        这就是我要做的

        ["first", "middle", "last", "title", "suffix"].map do |method|
          self.send("#{method}=", send("#{method}_parsed")) unless self.send(method) 
        end
        

        【讨论】:

          【解决方案5】:

          instance variable set 可以在这里提供帮助:

          class Person
            def some_setter_method
              %w(first middle last title suffix).each do |attr|
                unless instance_variable_get "@#{attr}"
                  instance_variable_set "@#{attr}", method(#{attr}_parsed).call
                end        
              end
            end
          end
          

          我尽量避免sends 因为它调用方法而不管它的范围状态(私有公共保护)。

          【讨论】:

          • 在这种情况下,您也可以使用public_send :)
          猜你喜欢
          • 2016-07-12
          • 1970-01-01
          • 1970-01-01
          • 2011-10-15
          • 1970-01-01
          • 2015-03-22
          • 1970-01-01
          • 2014-10-04
          • 1970-01-01
          相关资源
          最近更新 更多