2

人の名前に多くの属性を割り当てたいのですが、属性が空の場合は更新しますが、属性に既に値がある場合はスキップします。コードは次のようになります。

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

コードの重複を避けるためにこれを行うエレガントな方法はありますか?

4

5 に答える 5

2
%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"
于 2013-10-17T18:44:11.260 に答える
1

通常、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/value 関係を簡単に検索できます。

問題は、これを動的に行うためのコードを生成するまでに、単純な||=ベース ブロックを既に作成して、先に進んでいる可能性があることです。デバッグ時間が短縮され、何が何に影響するかが非常に明確になり、保守性が向上します。ですから、よりダイナミックであることで実際に長期的に有用なものが得られるかどうかはわかりません。これは、コードを記述するときによく行うトレードオフの 1 つです。

于 2013-10-17T20:14:42.830 に答える
1
%w[ first middle last title suffix ].each do |a|
  send("#{a}=", send("#{a}_parsed")) unless send(a)
end
于 2013-10-17T18:40:34.980 に答える
0

これは私がすることです

["first", "middle", "last", "title", "suffix"].map do |method|
  self.send("#{method}=", send("#{method}_parsed")) unless self.send(method) 
end
于 2013-10-17T18:41:10.317 に答える
0

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

sendスコープの状態(プライベートパブリック保護)に関係なくメソッドを呼び出すため、sを回避しようとします。

于 2013-10-17T19:18:50.107 に答える