2010-10-01 22 views
9

Dưới đây là một số mã sản xuất của tôi (tôi đã phải buộc ngắt dòng):Có find_or_create_by_ nhận mã băm trong Rails không?

task = Task.find_or_create_by_username_and_timestamp_and_des \ 
cription_and_driver_spec_and_driver_spec_origin(username,tim \ 
estamp,description,driver_spec,driver_spec_origin) 

Vâng, tôi đang cố gắng để tìm hoặc tạo một đối tượng duy nhất ActiveRecord::Base. Nhưng ở dạng hiện tại nó rất xấu. Thay vào đó, tôi muốn sử dụng một cái gì đó như thế này:

task = Task.SOME_METHOD :username => username, :timestamp => timestamp ... 

Tôi biết về find_by_something key=>value, nhưng nó không phải là một tùy chọn ở đây. Tôi cần tất cả các giá trị là duy nhất. Có một phương pháp sẽ làm tương tự như find_or_create_by, nhưng lấy một băm làm đầu vào? Hoặc cái gì khác với ngữ nghĩa similat?

Trả lời

19

Đường ray 3.2 được giới thiệu lần đầu tiên first_or_create tới ActiveRecord. Nó không chỉ có các chức năng được yêu cầu, nhưng nó cũng phù hợp trong phần còn lại của các mối quan hệ ActiveRecord:

Task.where(attributes).first_or_create 

Trong Rails 3.0 và 3.1:

Task.where(attributes).first || Task.create(attributes) 

Trong Rails 2,1-2,3:

Task.first(:conditions => attributes) || Task.create(attributes) 

Trong các phiên bản cũ hơn, bạn luôn có thể viết một phương thức có tên là find_or_create để đóng gói nếu bạn muốn. Chắc chắn làm được điều đó bản thân mình trong quá khứ:

class Task 
    def self.find_or_create(attributes) 
    # add one of the implementations above 
    end 
end 
+0

Yea, bạn chắc chắn có thể thêm nó đến AR :: Base, nhưng tôi thấy có một số hành vi mô hình cụ thể, giống như bạn có thể muốn chọn các cột cụ thể duy nhất để thực hiện tìm kiếm. Nhưng bạn luôn có thể ghi đè lên nó. – wuputah

4

Tôi cũng mở rộng phương thức @ wuputah để mất trong một mảng băm, mà là rất hữu ích khi sử dụng bên trong db/seeds.rb

class ActiveRecord::Base 
    def self.find_or_create(attributes) 
    if attributes.is_a?(Array) 
     attributes.each do |attr| 
     self.find_or_create(attr) 
     end 
    else 
     self.first(:conditions => attributes) || self.create(attributes) 
    end 
    end 
end 


# Example 
Country.find_or_create({:name => 'Aland Islands', :iso_code => 'AX'}) 

# take array of hashes 
Country.find_or_create([ 
    {:name => 'Aland Islands', :iso_code => 'AX'}, 
    {:name => 'Albania', :iso_code => 'AL'}, 
    {:name => 'Algeria', :iso_code => 'DZ'} 
]) 
Các vấn đề liên quan