質問

Rubyで気に入っている点の1つは、ほとんどが読みやすい言語であることです(自己文書化コードに最適です)

ただし、この質問に触発された: Rubyコードの説明 || = がルビーでどのように機能するかについての説明では、私は使用しないルビーのイディオムについて考えていました。率直に言って、私はそれらを完全に理解していません。

それで、私の質問は、参照された質問の例と同様に、真の熟練したルビープログラマーになるために知っておく必要のある一般的なルビーのイディオムは何ですか?

ところで、参照された質問から

a ||= b 

は同等です

if a == nil || a == false
  a = b
end

(修正してくれたIan Terrellに感謝)

編集:この点はまったく議論の余地のないものではないことがわかりました。実際、正しい展開は

(a || (a = (b))) 

理由については次のリンクをご覧ください:

これを指摘してくれたJö rg W Mittagに感謝します。

役に立ちましたか?

解決

同じファイルをライブラリまたはスクリプトとして機能させるマジックif句:

if __FILE__ == 
# put the first two words in a and b and the rest in arr
a,b,*arr = *%w{a dog was following me, but then he decided to chase bob}
# this holds for method definitions to
def catall(first, *rest)
  rest.map { |word| first + word }
end
catall( 'franken', 'stein', 'berry', 'sense' ) #=> [ 'frankenstein', 'frankenberry', 'frankensense' ]
# this library may be run as a standalone script end

配列のパックとアンパック:

this(:is => :the, :same => :as)
this({:is => :the, :same => :as})

メソッド引数としてのハッシュのシンタックスシュガー

# this
animals = Hash.new { [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {}
# is not the same as this
animals = Hash.new { |_animals, type| _animals[type] = [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {:squirrels=>[:Rocket, :Secret], :dogs=>[:Scooby, :Scrappy, :DynoMutt]}

ハッシュ初期化子:

x = Array.new
y = Array.new
class << x
  # this acts like a class definition, but only applies to x
  def custom_method
     :pow
  end
end
x.custom_method #=> :pow
y.custom_method # raises NoMethodError

メタクラスの構文

class Ticket
  @remaining = 3
  def self.new
    if @remaining > 0
      @remaining -= 1
      super
    else
      "IOU"
    end
  end
end
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> "IOU"

クラスインスタンス変数

 # know how to pack them into an object
 block = lambda { |e| puts e }
 # unpack them for a method
 %w{ and then what? }.each(&block)
 # create them as needed
 %w{ I saw a ghost! }.each { |w| puts w.upcase }
 # and from the method side, how to call them
 def ok
   yield :ok
 end
 # or pack them into a block to give to someone else
 def ok_dokey_ok(&block)
    ok(&block)
    block[:dokey] # same as block.call(:dokey)
    ok(&block)
 end
 # know where the parentheses go when a method takes arguments and a block.
 %w{ a bunch of words }.inject(0) { |size,w| size + 1 } #=> 4
 pusher = lambda { |array, word| array.unshift(word) }
 %w{ eat more fish }.inject([], &pusher) #=> ['fish', 'more', 'eat' ]

ブロック、プロシージャ、およびラムダ。生きて呼吸してください。

<*>

他のヒント

このスライドショーは、次のように、主要なRubyイディオムで完全に完了しています。

  • 2つの値を入れ替えます:

    x、y = y、x

  • 指定しない場合、デフォルト値をとるパラメーター

    def somemethod(x、y = nil)

  • 無関係なパラメーターを配列にまとめます

    def substitution(re、str、* rest)

など...

その他のイディオム:

%w %r 、および%(区切り文字

の使用
%w{ An array of strings %}
%r{ ^http:// }
%{ I don't care if the string has 'single' or "double" strings }

caseステートメントでの型比較

def something(x)
  case x
    when Array
      # Do something with array
    when String
      # Do something with string
    else
      # You should really teach your objects how to 'quack', don't you?
  end
end

...およびcaseステートメントでの === メソッドの全体的な不正使用

case x
  when 'something concrete' then ...
  when SomeClass then ...
  when /matches this/ then ...
  when (10...20) then ...
  when some_condition >= some_value then ...
  else ...
end

Rubyistsには自然に見えるはずですが、他の言語から来ている人にはそうでないかもしれません: for .. in each の使用>

some_iterable_object.each{|item| ... }

Ruby 1.9以降、Rails、またはSymbol#to_procメソッドにパッチを適用することにより、これは、ますますポピュラーなイディオムになりつつあります:

strings.map(&:upcase)

条件付きメソッド/定数定義

SOME_CONSTANT = "value" unless defined?(SOME_CONSTANT)

クエリメソッドと破壊的な(bang)メソッド

def is_awesome?
  # Return some state of the object, usually a boolean
end

def make_awesome!
  # Modify the state of the object
end

暗黙的なスプラットパラメータ

[[1, 2], [3, 4], [5, 6]].each{ |first, second| puts "(#{first}, #{second})" }

これが好き:

str = "Something evil this way comes!"
regexp = /(\w[aeiou])/

str[regexp, 1] # <- This

これは(ほぼ)同等です:

str_match = str.match(regexp)
str_match[1] unless str_match.nil?

または少なくとも、そのようなブロックを置き換えるために使用したものです。

あなたが賞賛し尊敬する人々からの人気のあるよく設計されたプラグインまたは宝石のコードを読むことをお勧めします。

私が遭遇したいくつかの例:

if params[:controller] == 'discussions' or params[:controller] == 'account'
  # do something here
end

対応する

if ['account', 'discussions'].include? params[:controller]
  # do something here
end

後でリファクタリングされる

if ALLOWED_CONTROLLERS.include? params[:controller]
  # do something here
end

さまざまなソースから抜粋したいくつかを次に示します。

&quot; unless&quot;を使用するおよび「まで」 「ない場合」の代わりにおよび「ない間」。 「限り」を使用しないようにしてください。 「その他」がただし、条件は存在します。

一度に複数の変数を割り当てることができます:

a,b,c = 1,2,3

さらに、一時なしで変数をスワップする:

a,b = b,a

必要に応じて、末尾の条件を使用します。例:

do_something_interesting unless want_to_be_bored?

クラスメソッドを定義する一般的に使用されているが、すぐには明らかではない(少なくとも私には)方法に注意してください:

class Animal
  class<<self
    def class_method
      puts "call me using Animal.class_method"
    end
  end
end

一部の参照:

  

ところで、参照先から   質問

a ||= b 
     

は同等です

if a == nil   
  a = b 
end

それは微妙に間違っており、初心者のRubyアプリケーションのバグの原因です。

nil false の両方(および唯一)がブールfalseと評価されるため、実際には a || = b は(ほぼ*)次と同等:

if a == nil || a == false
  a = b
end

または、別のRubyイディオムで書き直すには:

a = b unless a

(*すべてのステートメントには値があるため、これらは技術的には a || = b と同等ではありません。ただし、ステートメントの値に依存していない場合は表示されません違い。)

RubyのイディオムとフォーマットをカバーするWikiページを管理しています:

https://github.com/tokland/tokland/wiki/RubyIdioms

この略記if elseステートメントの正確な構文(および演算子の名前。コメントはありますか?)は常に忘れています。Ruby以外で広く使用されていると思いますが、他の誰かがここで構文を使用したい場合:

refactor < 3 ? puts("No need to refactor YET") : puts("You need to refactor this into a  method")

拡張

if refactor < 3
  puts("No need to refactor YET")
else
  puts("You need to refactor this into a  method")
end

更新

三項演算子と呼ばれる:

myvarを返しますか? myvar.size:0

マーシャリングオブジェクトを使用して簡単にディープコピーできます。 -Rubyプログラミング言語から取得

def deepcopy(o)
  Marshal.load(Marshal.dump(o))
end
  

ファイルとI / Oストリームは、   MethodおよびBindingオブジェクトと同様に、   マーシャリングするには動的すぎる。そこ   復元する信頼できる方法ではない   状態。

a = (b && b.attribute) || "default"

おおよそ:

if ( ! b.nil? && ! b == false) && ( ! b.attribute.nil? && ! b.attribute.false) a = b
else a = "default"

bが見つかったまたは見つからなかったレコードであるときにこれを使用し、その属性の1つを取得する必要があります。

If-then-elseまたはcase-whenが値を返すため短縮する方法が好きです:

if test>0
  result = "positive"
elsif test==0
  result = "zero"
else
  result = "negative"
end

書き換え可能

result = if test>0
  "positive"
elsif test==0
  "zero"
else
  "negative"
end

同じことがケースの場合に適用できます:

result = case test
when test>0 ; "positive"
when test==0 ; "zero"
else "negative"
end

バイナリファイルを操作するためのArray.packおよびString.unpack:

# extracts four binary sint32s to four Integers in an Array
data.unpack("iiii") 

magickが欠落しているメソッド

class Dummy  
  def method_missing(m, *args, &block)  
    "You just called method with name #{m} and arguments- #{args}"  
  end  
end

Dummy.new.anything(10, 20)
=> "You just called method with name anything and arguments- [10, 20]"

ルビーオブジェクトに存在しないメソッドを呼び出す場合、ルビーインタープリターは「method_missing」と呼ばれるメソッドが定義されていればそれを呼び出します。APIラッパーやdslを書くなどのいくつかのトリックのためにこれを使用できます。メソッドとパラメーター名

いい質問!

より直感的に&amp;コードが高速であるほど、より良いソフトウェアを構築しています。 Rubyを使用して、コードの小さな断片で自分の考えを表現する方法を紹介します。 詳細はこちら

地図

さまざまな方法でmapメソッドを使用できます:

user_ids = users.map { |user| user.id }

または:

user_ids = users.map(&:id)

サンプル

randメソッドを使用できます:

[1, 2, 3][rand(3)]

シャッフル:

[1, 2, 3].shuffle.first

そして慣用的でシンプルで簡単な方法...サンプル!

[1, 2, 3].sample

ダブルパイプと等しい/メモ

説明で述べたように、メモ化を使用できます:

some_variable ||= 10
puts some_variable # => 10

some_variable ||= 99
puts some_variable # => 10

静的メソッド/クラスメソッド

クラスメソッドを使用するのが好きです。&amp;を作成するのは本当に慣用的な方法だと思います。クラスを使用:

GetSearchResult.call(params)

シンプル。綺麗な。直感的。バックグラウンドで何が起こりますか?

class GetSearchResult
  def self.call(params)
    new(params).call
  end

  def initialize(params)
    @params = params
  end

  def call
    # ... your code here ...
  end
end

慣用的なRubyコードを記述するための詳細については、 こちら

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top