0

25 Ruby Code Factoids

1. phương thức ‘methods’

Trong Ruby một đối tượng Object có thể nhập .methods để xem tất cả các phương thức có thể của đối tượng đó.

2.3.0 :001 > 4.methods - Object.methods
 => [:%, :&, :*, :**, :+, :+@, :-, :-@, :/, :<<, :>>, :[], :^, :abs, :abs2, :angle, :arg, :between?, :bit_length, :byte, :bytes, :ceil, :chr, :coerce, :conj, :conjugate, :day, :days, :denominator, :div, :divmod, :downto, :even?, :exabyte, :exabytes, :fdiv, :floor, :fortnight, :fortnights, :gcd, :gcdlcm, :gigabyte, :gigabytes, :hour, :hours, :i, :imag, :imaginary, :in_milliseconds, :integer?, :kilobyte, :kilobytes, :lcm, :magnitude, :megabyte, :megabytes, :minute, :minutes, :modulo, :month, :months, :multiple_of?, :negative?, :next, :nonzero?, :numerator, :odd?, :ord, :ordinal, :ordinalize, :petabyte, :petabytes, :phase, :polar, :positive?, :pred, :quo, :rationalize, :real, :real?, :rect, :rectangular, :remainder, :round, :rszf, :second, :seconds, :singleton_method_added, :size, :step, :succ, :terabyte, :terabytes, :times, :to_bn, :to_c, :to_d, :to_default_s, :to_f, :to_formatted_s, :to_i, :to_int, :to_r, :truncate, :upto, :week, :weeks, :year, :years, :zero?, :|, :~]

2. biến _

Trong IRB sử dụng biến gạch dưới _ sẽ tổ chức đánh gia dòng cuối cùng của mã thực thi.

Khi biến được sử dụng trong code nó là một chỉ số từ các developer rằng tham số này sẽ không được sử dụng. Ví dụ: "Được chia thành các cột 4"

2.3.0 :002 > [0,1,2,3,4,5,6,7,9].group_by.with_index {|_,index| index % 4 }.values
 => [[0, 4, 9], [1, 5], [2, 6], [3, 7]]

Trong khuôn khổ Minitest, bắt đầu từ phiên bản 5.6.0, việc sử dụng gạch dưới là một alias cho các thử nghiệm kiểu này.

spec(4).must_be :even?
_(4).wont_be :odd?

3. phương thức instance_exec

Phương thức instance_exec có sẵn cho tất cả các Object, và mọi thứ tron Ruby đều là một đối tượng, và khi bạn sử dụng nó bạn mở singleton_class của đối tượng để làm việc. Mọi thứ bạn có thể làm trong một Class bạn cũng có thể làm trong một instance_exec

num = Object.new
num.instance_exec {
  def == other
    other == 3
  end
}
num == 4
# => false
num == 3
# => true

Bạn còn có thể sử dụng nó trong một Proc nó có thể khiến mọi người điên lên nếu bạn làm. Nhưng đây chỉ để bạn biết rằng có thể làm nó:

prc = proc {|num| num == 4}
prc.instance_exec { def == other; other == 3 end  }

prc.call(4)
# => true
prc.call(3)
# => false

prc == 4
# => false
prc == 3
# => true

4. Đối tượng Enumerator::Lazy

Một đối tượng Enumerator::Lazy sẽ cho bạn trở lại một đối tượng cùng một lúc từ bộ sưu tập của bạn với việc truy cập tùy chọn trên mỗi mục.

def do_the_lazy(array_input)
  Enumerator::Lazy.new(array_input) do |yielder, value|
    yielder << value
  end
end

x = do_the_lazy([1,2,3,4,5,6])
# => #<Enumerator::Lazy: [1, 2, 3, 4, 5, 6]:each>

x.next
# => 1
x.next
# => 2
x.next
# => 3
x.force
# => [1, 2, 3, 4, 5, 6]

5. Struct has Enumerable as its ancestor

Bạn có thể sử dụng bất kỳ phương thức từ nó và viết một số phương thức nhỏ trên Struct mình.

class Pair < Struct.new(:first, :second)
  def same?
    inject(:==)
  end

  def add
    reduce(:+)
  end
end

a = Pair.new(4,4)
# => #<struct Pair first=4, second=4>
a.same?
# => true
a.add
# => 8

b = Pair.new(5,6)
# => #<struct Pair first=5, second=6>
b.same?
# => false
b.add
# => 11

6. $:

biến $: là biến load đường dẫn cho các gem Ruby. Cũng có thể thông qua $LOAD_PATH. Bạn có thể thêm các thư mục hiện tại đến đường dẫn tải của bạn với:

$: << '.'

7. inspect

Phươngthức inspect biểu diễn mặc định của một đối tượng Object khi bạn gọi Class#new và nó hiển thị nó trên dòng tiếp theo

class Human < Struct.new(:name, :age)
  def inspect
    "#{name} is a human of age #{age}"
  end
end

joe = Human.new("Joe", 43)
# => Joe is a human of age 43

8. Hash#invert

Phương thức invert cho phép bạn đảo ngược Hash cặp khóa - giá trị của bạn.

{a: 1, b: 2}.invert
# => {1=>:a, 2=>:b}

9. Method#to_proc

Bạn có thể chuyển các phương thức tớ proc nhờ to_proc. Lưu ý Chúng chỉ thực hiện khi cùng một loại đối tượng mà chúng đc định nghĩa.

def plus_one(x)
  x + 1
end

proc_increment = method(:plus_one).to_proc

proc_increment.call(4)
# => 5
[1,3,5,9].map(&proc_increment)
# => [2, 4, 6, 10]

10. require_relative

require_relative là một cách thuận tiện để tải tập tin ruby khác liên quan đến các tập tin vị trí hiện tại của bạn.

11. instance_methods

Trên bất kỳ class nào bạn có thể gọi phương thức instance_methods để tìm ra những trường hợ riêng của lớp sẽ được định nghĩa trên chúng.

12. Enumerable

Enumerable là một module mà bao gồm các kiểu siêu tập cơ bản như Array, Hash, hay Struct. Vì vậy, tất cả các loại đối tượng sẽ bao gồm các phương thức từ Enumerable.

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status  # => "active"

# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status    # => "archived"

# conversation.status = 1
conversation.status = "archived"

conversation.status = nil
conversation.status.nil? # => true
conversation.status      # => nil

13. defined?

từ khoá phương thức defined?hữu ích cho việc kiểm tra bất kì module, class, method được định nghĩa công khai. Trên các class trên các module bạn có có thể gọi các phương thức method_defined?, public_method_defined?, private_method_defined?, và protected_method_defined?

defined? Person
# => nil
class Person
end
# => nil
defined? Person
# => "constant"

14. string % value(s)

Bạn có thể chèn với loại chuyển đổi thành chuỗi bằng cách sử dụng phương thức phần trăm % như sau:

"Number: %f %f" % [1,2]
# => Number: 1.000000 2.000000

"Number: %e" % "6"
# => "Number: 6.000000e+00"

15. ternary operator _ ? _ : _

Nó là một cách viết tắt thay câu lệnh if else. nếu giá trị trước dấu chấm hỏi là đúng thì trả lại hàng đầu tiên sau dấu chấm hỏi. Nếu sai thì di chuyển qua các dấu chấm. Nó được khuyến khích sử dụng nếu biểu thức chỉ trên 1 dòng, có thể sử dụng thêm các dấu ngoặc cho dễ hiểu

true ? 10 : 20
# => 10
false ? 10 : 20
# => 20
false ? 10 : 20 ? 30 : 40
# => 30
false ? 10 : !20 ? 30 : 40
# => 40
false ? 10 : 20 ? 30 ? 50 : 60 : 40
# => 50
false ? 10 : 20 ? !30 ? 50 : 60 : 40
# => 60
false ? 10 : !20 ? 30 ? 50 : 60 : 40
# => 40

16. ruby -e “#code”

Chạy đoạn mã ruby từ dòng lệnh

ruby -e "puts 1 + 1"
# => 2

17. %[]

%[Hello #{ "World!" } "Quoted" and 'quoted!']
# => "Hello World! \"Quoted\" and 'quoted!'"

18. erb

ERB là một thư viện của Ruby và bạn có thể sử dụng nó để thêm code Ruby với documents/strings khác.

require "erb"
ERB.new(%[<html><body>Hello <%= "Wor" + "ld!" %></body></html>]).result
# => "<html><body>Hello World!</body></html>"

19. ‘self’ có thể thay thê bằng tên Object

module Apple
  def Apple.chew
    "munch munch"
  end
end

Apple.chew
# => "munch munch"

def Apple.cut
  "chop chop"
end

Apple.cut
# => "chop chop"

class A
  def A.foo
    "bar"
  end
end

A.foo
# => "bar"

20. Đối tượng có phạm vi cao hơn có thể được truy cập với ::

module A
  def self.test
    "FOO"
  end
end

module Thing
  module A
    def self.test
      "BAR"
    end
  end

  def Thing.inner
    A.test
  end

  def Thing.outer
    ::A.test
  end
end

Thing.outer
# => "FOO"
Thing.inner
# => "BAR"

21. prepend

prepend thêm một module vào chuỗi gần đây nhât của lớp tổ tiên. Phương thức sẽ được gọi đầu tiên.

module A
  def split
    self.upcase
  end
end

String.prepend A

String.ancestors
# => [A, String, Comparable, Object, Kernel, BasicObject]
"asdf".split
# => "ASDF"

22. super

super gọi tên phương thức hiện thời của lớp tổ tiên và tiếp tục cho đến khi tìm được định nghĩa.

module A
  def split(*_)
    super("a")
  end
end

class B < String
  def split
    super("b")
  end
end

b = B.new("123abc")
# => "123abc"
b.split
# => ["123a", "c"]
B.ancestors
# => [B, String, Comparable, Object, Kernel, BasicObject]

String.prepend A

b.split
# => ["123", "bc"]
B.ancestors
# => [B, A, String, Comparable, Object, Kernel, BasicObject]

23. arity

arity cho bạn biết có bao nhiêu tham số mộột Proc hay phương thức sẽ lấy.

->{}.arity
# => 0
->_{}.arity
# => 1
->_,_{}.arity
# => 2
->*_{}.arity
# => -1
"".method(:upcase).arity
# => 0
String.instance_method(:upcase).arity
# => 0

23. class_eval with included

Sử dụng class_eval khi bạn đang viết các phương thức được đưa vào là cách tự nhiên hơn của việc update các class. Bạn sẽ viết định nghĩa của bạn cũng giống như khi bạn đang ở trong class.

class A
end

module Example
  def self.included(base)
    base.class_eval do
      def example
        "instance method"
      end

      def self.example
        "class method"
      end
    end
  end
end

A.include Example

A.example
"class method"

A.new.example
"instance method"

24. inherited

Khi bạn đang có một lớp kế thừa từ các lớp khác như là một "mixin" bạn có thể viết.

class Foo
  def self.inherited(base)
    base.class_eval do
      def bar
        "Drinking at the bar!"
      end
    end
  end

  def foo
    "bar"
  end
end

class A < Foo
end

A.new.foo
# => "bar"
A.new.bar
# => "Drinking at the bar!"

Foo.new.foo
# => "bar"
Foo.new.bar
#NoMethodError: undefined method `bar' for #<Foo:0x00000001916378>

25. Infinity

Bạn có thể sử dụng phương thức detect để trả lại phần tư đầu tiên đánh giá là đúng

[1,5,9,11,13,15,18,21,24,26,28].detect(&:even?)
# => 18

[1,5,9,11,13,15,18,21,24,26,28].detect {|number| number.even? }
# => 18

Tham Khảo http://6ftdan.com/allyourdev/2016/01/13/101-ruby-code-factoids/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí