2011-11-05 20 views
9

Tôi đang học đường ray và quay lại ruby ​​để hiểu cách thức các đường ray (và ruby ​​thực sự hoạt động). Khi tôi thấy các cuộc gọi phương thức như:Sử dụng ký hiệu làm đối số cho phương pháp ruby ​​

validates validates :first_name, :presence => true 

Tôi bị lẫn lộn. Làm thế nào để bạn viết phương pháp trong ruby ​​chấp nhận các biểu tượng hoặc băm. Mã nguồn cho phương thức xác thực cũng gây nhầm lẫn. Ai đó có thể xin đơn giản hóa chủ đề này của việc sử dụng các biểu tượng như là đối số trong lớp ruby ​​và phương pháp dụ cho tôi?

CẬP NHẬT:

Tốt nhất @Dave! Nhưng những gì tôi đã thử là một cái gì đó như:

def full_name (:first_name, :last_name) 
    @first_name = :first_name 
    @last_name = :last_name 
    p "#{@first_name} #{last_name}" 
end 

full_name("Breta", "Von Sustern") 

Rõ ràng là làm tăng lỗi. Tôi đang cố gắng để hiểu: Tại sao là đi qua các biểu tượng như thế này như là đối số sai nếu biểu tượng giống như bất kỳ giá trị khác?

+0

Ký hiệu và băm là các giá trị giống như bất kỳ hình thức nào khác - không có gì khác biệt khi chuyển biểu tượng hoặc băm khác với bất kỳ thứ gì khác. Điều gì đặc biệt khiến bạn bối rối? –

+0

Điều làm tôi bối rối là tôi chưa bao giờ thấy một ví dụ về băm được sử dụng làm giá trị trong các phương thức ruby. Vì vậy, tôi không thể hình dung những gì bạn đang nói. –

+1

Bạn * vượt qua * biểu tượng, tên tham số vẫn chỉ là - tên tham số và không được có ký tự ':' hàng đầu. –

Trả lời

15

Ký hiệu và băm là các giá trị như bất kỳ giá trị nào khác và có thể được chuyển như bất kỳ loại giá trị nào khác.

Nhớ lại rằng mô hình ActiveRecord chấp nhận băm làm đối số; nó kết thúc lên được tương tự như sau (nó không phải đơn giản này, nhưng đó là ý tưởng tương tự cuối cùng):

class User 
    attr_accessor :fname, :lname 

    def initialize(args) 
    @fname = args[:fname] if args[:fname] 
    @lname = args[:lname] if args[:lname] 
    end 
end 

u = User.new(:fname => 'Joe', :lname => 'Hacker') 

này có lợi thế là không cần phải đặt băm trong xoăn-ngoặc {} trừ khi bạn cần để disambiguate các tham số (và có một vấn đề phân tích cú pháp khối cũng như khi bạn bỏ qua các lần parens).

Tương tự:

class TestItOut 
    attr_accessor :field_name, :validations 

    def initialize(field_name, validations) 
    @field_name = field_name 
    @validations = validations 
    end 

    def show_validations 
    puts "Validating field '#{field_name}' with:" 
    validations.each do |type, args| 
     puts " validator '#{type}' with args '#{args}'" 
    end 
    end 
end 

t = TestItOut.new(:name, presence: true, length: { min: 2, max: 10 }) 
t.show_validations 

này kết quả đầu ra:

Validating field 'name' with: 
    validator 'presence' with args 'true' 
    validator 'length' with args '{min: 2, max: 10}' 

Từ đó bạn có thể bắt đầu để xem cách những thứ như công việc này.

+0

Ngoài ra, hãy xem xét sử dụng phương thức 'fetch' để cung cấp các giá trị mặc định khi nhận các đối số bên trong một băm. –

4

Trong Ruby, nếu bạn gọi một phương thức với một loạt các name => value cặp ở phần cuối của danh sách đối số, mục này được tự động bọc trong một Hash và truyền cho phương pháp của bạn như là đối số cuối cùng:

def foo(kwargs) 
    p kwargs 
end 

>> foo(:abc=>"def", 123=>456) 
{:abc=>"def", 123=>456} 

>> foo("cabbage") 
"cabbage" 

>> foo(:fluff) 
:fluff 

Không có gì "đặc biệt" về cách bạn viết phương pháp, đó là cách bạn gọi nó. Nó sẽ là hoàn toàn hợp pháp để chỉ cần vượt qua một đối tượng Hash thường xuyên như tham số kwargs. Phím tắt cú pháp này được sử dụng để triển khai thông số có tên trong API.

Biểu tượng Ruby chỉ là một giá trị như bất kỳ biểu tượng nào khác, vì vậy trong ví dụ của bạn, :first_name chỉ là một đối số vị trí thông thường. :presence là một biểu tượng được sử dụng như một khóa băm - bất kỳ loại nào có thể được sử dụng như một khóa băm, nhưng các biểu tượng là một lựa chọn phổ biến bởi vì chúng là các giá trị bất biến.

+1

Và quan trọng hơn là không thay đổi, chúng giao tiếp nhiều hơn ở chỗ chúng đặc biệt hoạt động như một cái tên hay nhãn hiệu cho một cái gì đó. –

2

Ký hiệu không giới hạn đối với băm. Chúng là số nhận dạng, không có dung lượng lưu trữ thêm của một chuỗi. Nó chỉ là một cách để nói "đây là ...."

Một định nghĩa chức năng có thể cho các cuộc gọi xác nhận có thể là (chỉ để đơn giản hóa, tôi không biết ra khỏi đỉnh đầu của tôi những gì nó thực sự là):

def validates(column, options) 
    puts column.to_s 
    if options[:presence] 
    puts "Found a presence option" 
    end 
end 

Chú ý cách biểu tượng đầu tiên là

+0

Chúng vẫn được lưu trữ, nó chỉ là mỗi nhãn duy nhất được lưu trữ chỉ một lần, giống như một chuỗi nội bộ. OTOH, họ cũng không đủ điều kiện tham gia GC (có thể họ đang ở 1,9), vì vậy họ sẽ tham gia suốt cuộc đời của ứng dụng. –

+0

Ký hiệu không phải là GC trong 1,9. – sheldonh

+0

Ruby 2.2 bây giờ có biểu tượng GC – DGM

2

Tôi nghĩ rằng tất cả các câu trả lời đều bỏ lỡ câu hỏi và thực tế nó được hỏi bởi một người - tôi đoán - không rõ ràng về biểu tượng là gì ?

Là người mới đến với Ruby, tôi có những nhầm lẫn tương tự và với tôi Câu trả lời như sau sẽ có ý nghĩa hơn

Phương thức Đối số là các biến cục bộ được điền thông qua các giá trị.

Bạn không thể sử dụng các ký hiệu là Đối số của mình, vì bạn không thể thay đổi giá trị của một biểu tượng.

+2

Tôi không chắc chắn ý bạn là gì bởi "bạn không thể sử dụng ký hiệu làm đối số", bởi vì bạn có thể ... 'foo (: bar)' là một hàm gọi hoàn hảo hợp pháp. Có lẽ tôi đã hiểu lầm? –

9

Tôi nghĩ tôi muốn thêm bản cập nhật cho Ruby 2+ vì đây là kết quả đầu tiên tôi tìm thấy cho 'biểu tượng làm đối số'.

Vì Ruby 2.0.0 bạn cũng có thể sử dụng biểu tượng khi xác định phương thức. Khi gọi phương thức, các ký hiệu này sẽ hoạt động gần giống như các tham số tùy chọn có tên trong các ngôn ngữ khác. Xem ví dụ dưới đây:

def variable_symbol_method(arg, arg_two: "two", arg_three: "three") 
    [arg, arg_two, arg_three] 
end 

result = variable_symbol_method :custom_symbol, arg_three: "Modified symbol arg" 

# result is now equal to: 
[:custom_symbol, "two", "Modified symbol arg"] 

Như đã trình bày trong ví dụ, chúng ta bỏ qua arg_two: khi gọi phương pháp này và trong cơ thể phương pháp chúng ta vẫn có thể truy cập vào nó như biến arg_two. Cũng lưu ý rằng biến số arg_three thực sự bị thay đổi bởi cuộc gọi hàm.

Các vấn đề liên quan