Dưới đây là mô hình ActiveRecord tôi, với Rails 3.2:Relation trên phạm vi trên ActiveRecord
class User < ActiveRecord::Base
has_one :criterion
has_many :user_offer_choices
end
class Offer < ActiveRecord::Base
has_many :user_offer_choices
def seen
user_offer_choices.where(seen: true)
end
def accepted
user_offer_choices.where(accepted: true)
end
end
class Criterion < ActiveRecord::Base
belongs_to :user
end
class UserOfferChoice < ActiveRecord::Base
belongs_to :user
belongs_to :offer
end
Tôi muốn để có được tất cả các tiêu chí của người dùng đã xem một lời đề nghị. Một cái gì đó như:
Offer.find(11).seen.users.criterions
nhưng tôi không biết làm thế nào để cho nó với ActiveRecord
Tôi biết tôi có thể làm điều gì đó như:
Criterion.joins(user: { user_offer_choices: :offer }).where(user: { user_offer_choices: {accepted: true, offer_id: 11} })
Nhưng tôi muốn để có thể sử dụng phạm vi của tôi trên phiếu mua hàng (đã xem & được chấp nhận). Vậy làm thế nào tôi có thể làm điều đó?
Edit: tôi đã tìm thấy những gì tôi đang tìm kiếm, phương pháp hợp nhất của Arel: http://benhoskin.gs/2012/07/04/arel-merge-a-hidden-gem
Tôi không muốn sử dụng bản đồ (hoặc phương pháp Enum khác), vì Ruby và ActiveRecord đơn giản sẽ không tạo SQL. –
Tại sao điều quan trọng là sử dụng SQL thay vì bản đồ? Điều đó dường như với tôi là một yêu cầu bắt buộc tùy ý. Nếu bạn nhận thấy, tôi đã chứng minh làm thế nào để đi từ lồng hai cuộc gọi bản đồ, (đó là cồng kềnh và khó đọc) để một giải pháp mà được thoát khỏi một bản đồ và sử dụng SQL và phạm vi của bạn. Bạn có thể thử mở rộng kỹ thuật đó, nhưng tôi nghĩ rằng giải pháp đó sẽ cồng kềnh. (Tìm hiểu thêm về bản đồ so với SQL trong bình luận tiếp theo.) –
Sử dụng bản đồ có một nhược điểm là nó lặp qua bộ sưu tập, nhưng sau đó thực hiện cuộc gọi đến cơ sở dữ liệu trong vòng lặp để dereference hiệp hội. Khi tôi thay đổi bản đồ lựa chọn thành có nhiều thông qua nó đã thực hiện một cuộc gọi SQL cho đối tượng Offer đã cho, và xây dựng phép nối cho chúng ta. Tuy nhiên, tôi sẽ không lo lắng về hiệu suất cho đến khi chúng tôi xác định rằng toàn bộ phản hồi trên web mất quá nhiều thời gian. –