2012-04-26 28 views
14

Có thể viết một phạm vi với các đối số tùy chọn để tôi có thể gọi phạm vi có và không có đối số không?Có thể có phạm vi với các đối số tùy chọn không?

Cái gì như:

scope :with_optional_args, lambda { |arg| 
    where("table.name = ?", arg) 
} 

Model.with_optional_args('foo') 
Model.with_optional_args 

tôi có thể kiểm tra trong khối lambda nếu một arg được đưa ra (như được mô tả bởi Unixmonkey) nhưng trên gọi phạm vi mà không cãi nhau tôi đã nhận một ArgumentError: wrong number of arguments (0 for 1)

Trả lời

18

Có. Chỉ cần sử dụng * như bạn sẽ làm trong một phương pháp.

scope :print_args, lambda {|*args| 
    puts args 
} 
0

Chắc chắn.

scope :with_optional_args, Proc.new { |arg| 
    if arg.present? 
    where("table.name = ?", arg) 
    end 
} 
+0

Bạn sẽ không muốn bao gồm một dự phòng khi không args được thông qua? –

+0

Tôi gặp lỗi nếu tôi không vượt qua một đối số: ArgumentError: sai số đối số (0 cho 1) – tonymarschall

+2

Bạn có thể sử dụng Proc.new thay vì lambda để tránh lỗi đối số. Xem thảo luận cũ này về [this] (https://rails.lighthouseapp.com/projects/8994/tickets/90-enhancement-add-support-for-named-scopes-with-optional-arguments) – Christian

8

tôi đã sử dụng scope :name, ->(arg1, arg2 = value) { ... } một vài tuần trước, nó làm việc tốt, nếu bộ nhớ của chính xác. Để sử dụng với ruby ​​1.9+

20

của Ruby 1,9 khối mở rộng để có các tính năng tương tự như phương pháp làm (giá trị mặc định là trong số đó):

scope :cheap, lambda{|max_price=20.0| where("price < ?", max_price)} 

Gọi:

Model.cheap 
Model.cheap(15) 
3

Chỉ muốn cho bạn biết rằng theo guide, cách được đề xuất để chuyển đối số cho phạm vi là sử dụng một phương pháp lớp học, như sau:

class Post < ActiveRecord::Base 
    def self.1_week_before(time) 
    where("created_at < ?", time) 
    end 
end 

Điều này có thể mang lại cách tiếp cận rõ ràng hơn.

5

Bạn có thể sửa đổi điều kiện phạm vi của mình dựa trên một đối số đã cho.

scope :random, ->(num = nil){ num ? order('RANDOM()').limit(num) : order('RANDOM()') } 

Cách sử dụng:

Advertisement.random # => returns all records randomized 
Advertisement.random(1) # => returns 1 random record 

Hoặc, bạn có thể cung cấp một giá trị mặc định.

scope :random, ->(num = 1000){ order('RANDOM()').limit(num) } 

Cách sử dụng:

Product.random # => returns 1,000 random products 
Product.random(5) # => returns 5 random products 

Chú ý: Cú pháp hiển thị cho RANDOM() là cụ thể cho Postgres. Cú pháp được thể hiện là Rails 4.

0

Sử dụng *

scope :with_optional_args, -> { |*arg| where("table.name = ?", arg) } 
Các vấn đề liên quan