문제

루비에 대해 내가 좋아하는 한 가지는 대부분 읽기 쉬운 언어라는 것입니다 (자체 문서화 코드에 적합합니다).

그러나이 질문에서 영감을 얻었습니다. 루비 코드가 설명되었습니다그리고 방법에 대한 설명 ||= 루비에서 일하는데, 나는 내가 사용하지 않는 루비 관용구에 대해 생각하고있었습니다. 솔직히 말해서 나는 그들을 완전히 사로 잡지 않았습니다.

그래서 제 질문은 참조 된 질문의 예와 비슷하지만, 진정으로 능숙한 루비 프로그래머가 되려면 공통적이지만 명백하지 않은 루비 관용구는 무엇입니까?

그건 그렇고, 참조 된 질문에서

a ||= b 

동일합니다

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

(교정에 대한 Ian Terrell에게 감사합니다)

편집하다: 이 점은 완전히 논란의 여지가없는 것이 밝혀졌습니다. 올바른 확장은 사실입니다

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

이유는 다음과 같은 링크를 참조하십시오.

이것을 지적한 Jörg W Mittag에게 감사합니다.

도움이 되었습니까?

해결책

동일한 파일이 라이브러리 또는 스크립트 역할을하는 마법의 조항 :

if __FILE__ == $0
  # this library may be run as a standalone script
end

포장 및 포장 풀기 :

# 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(: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"

블록, Procs 및 Lambdas. 살고 숨을 쉬십시오.

 # 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' ]

다른 팁

이것 슬라이드 쇼 다음과 같이 메인 루비 관용구에 대해 매우 완전합니다.

  • 두 값을 바꾸십시오 :

    x, y = y, x

  • 지정되지 않은 경우 기본값을 취하는 매개 변수

    def somemethod(x, y=nil)

  • 외부 매개 변수를 배열로 배치합니다

    def substitute(re, str, *rest)

등등...

더 많은 관용구 :

사용 %w, %r 그리고 %( 구분자

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

사례 진술에서 비교를 입력하십시오

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 x
  when 'something concrete' then ...
  when SomeClass then ...
  when /matches this/ then ...
  when (10...20) then ...
  when some_condition >= some_value then ...
  else ...
end

루비이스트에게는 자연스럽게 보이지만 다른 언어에서 오는 사람들에게는 그렇지 않을 수도 있습니다. each 유리하게 for .. in

some_iterable_object.each{|item| ... }

루비 1.9+, 레일 또는 기호#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

암시 적 Splat 매개 변수

[[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

다음은 다양한 출처에서 나온 몇 가지가 있습니다.

"그렇지 않은 경우"와 "그렇지 않은"대신 "이 아닌"과 "때까지"를 사용하십시오. 그러나 "다른"조건이 존재하는 경우를 사용하지 않는 한 "사용하지 마십시오.

한 번에 여러 변수를 할당 할 수 있습니다.

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

그것은 미묘하게 틀렸으며 신규 이민자의 루비 응용 프로그램에서 버그의 원천입니다.

둘 다 (그리고 만) 이후 nil 그리고 false 부울 거짓으로 평가하고 a ||= b 실제로 (거의*)와 같습니다.

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

또는 다른 루비 관용구로 다시 작성하려면 :

a = b unless a

(*모든 진술은 가치가 있으므로 기술적으로는 기술적으로 동등하지 않습니다. a ||= b. 그러나 진술의 가치에 의존하지 않으면 차이가 보이지 않습니다.)

루비 관용구와 서식을 다루는 위키 페이지를 유지합니다.

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

나는 항상 다른 문장의 정확한 구문 (그리고 운영자의 이름을 댓글을 달 때?)이 속기의 정확한 구문을 항상 잊어 버린다.

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

업데이트

Ternary 운영자라고합니다.

Myvar를 반환 하시겠습니까? myvar.size : 0

당신은 쉽게 마샬링 물체로 심해 할 수 있습니다. - 루비 프로그래밍 언어에서 가져 왔습니다

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

방법 및 바인딩 객체뿐만 아니라 파일 및 I/O 스트림도 마샬링하기에는 너무 역동적입니다. 그들의 상태를 복원하는 신뢰할 수있는 방법은 없을 것입니다.

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

대략 :

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

B가 발견되었거나 발견되지 않은 레코드 일 때 이것을 사용하며, 그 속성 중 하나를 가져와야합니다.

나는 값을 반환하기 때문에 if-then-elses 또는 case가 단축 될 수있는 방법을 좋아합니다.

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]"

루비 객체에 존재하지 않는 메소드를 호출하는 경우 Ruby Interperter는 정의 된 경우 'Method_missing'이라는 메소드를 호출합니다. 이름

좋은 질문!

코드가 더 직관적이고 빠를수록 우리가 구축하는 더 나은 소프트웨어라고 생각합니다. 작은 코드 스 니펫으로 루비를 사용하여 내 생각을 어떻게 표현하는지 보여 드리겠습니다. 여기에서 자세히 알아보십시오

지도

다양한 방식으로 맵 방법을 사용할 수 있습니다.

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

정적 메소드 / 클래스 방법

나는 수업 방법을 사용하는 것을 좋아합니다. 수업을 만들고 사용하는 것이 관용적 인 방법이라고 생각합니다.

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

관용적 루비 코드를 작성하려는 자세한 정보는 읽으십시오. 여기

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top