2010-02-14 40 views
5

Giả sử chúng tôi có một trang web nhiếp ảnh. Bất kỳ tác giả nào cũng có thể đăng ký để nhận thông tin cập nhật từ bất kỳ tác giả nào khác. Rõ ràng là nếu tác giả A được đăng ký tác giả B mà không có nghĩa là B được đăng ký với A. Vì vậy, chúng ta xây dựng mô hìnhLàm cách nào để tạo các mối quan hệ nhiều-nhiều-nhiều trong Rails?

class Author < ActiveRecord::Base 
    has_many :subscriptions 
    has_many :subscribed_by_author, :through => :subscriptions, :source => :subscribed_to 
end 

class Subscription < ActiveRecord::Base 
    belongs_to :author 
    belongs_to :subscribed_to, :class_name => "Author", :foreign_key => "subscribed_to" 
end 

Bằng cách này chúng ta có thể sử dụng

  1. some_author.subscribed_by_author - danh sách của các tác giả mà ai đó đã đăng ký.
  2. Đối với bất kỳ thuê bao chúng ta có thể biết cả hai đầu (ai đăng ký với ai)

Nhưng câu hỏi là làm thế nào để có được danh sách những người đăng ký một số tác giả chỉ sử dụng đường ray (không sử dụng SQL đồng bằng) tức là get câu trả lời cho: "Ai được đăng ký với some_author?"

Câu hỏi: có khả năng nào trong Rails để có được mối quan hệ làm việc cả hai bên tức là không chỉ viết some_author.subscribed_BY_author mà còn có some_author_subscribed_TO_author? Nếu có, thì nó là gì?

P.S. giải pháp rõ ràng là

  1. Thay đổi thiết kế cơ sở dữ liệu, thêm một cột có tên là "hướng"
  2. Tạo 2 ghi lại mỗi lần một thuê bao được tạo ra
  3. Thêm vào mô hình giả

    has_many: subscribed_BY_author ,: through =>: subscription,: source =>: subscribed_to,: conditions => "direction = 'by'"

    has_many: subscribed_TO_author,: through =>: subscriptions,: source =>: subscribed_to,: condit ions => "direction = 'to'"

Nhưng tôi tự hỏi nếu có giải pháp mà không thay đổi thiết kế cơ sở dữ liệu.

Trả lời

0
# Author model 
has_many :subscriptions_to, :class_name => "Subscription", :foreign_key => "subscribed_to" 
has_many :subscribed_to_author, :through => :subscriptions_to, :source => :author 

Theo như tôi biết - nó hoạt động! :)

+0

Thật không may là không.Nhưng nó đã cho tôi hướng đi đúng và mã sau đây đã làm việc # Mô hình riêng lẻ has_many: subscriptions_to,: class_name => "Subscription",: foreign_key => "subscribed_to" has_many: subscribed_to_author,: through =>: subscriptions_to,: source =>: tác giả Vì vậy, tôi chấp nhận câu trả lời này, nhưng bạn phải chỉnh sửa câu trả lời chính xác trước :) Cảm ơn! –

+0

Nó luôn luôn là niềm vui lớn của tôi để sửa chữa aswers của tôi :) – klew

2

Tôi muốn sử dụng HABTM đơn giản cho một cái gì đó đơn giản như thế này, nhưng bạn sẽ cần một bảng tham gia không có vấn đề gì.

create_table :subscriptions do |t| 
    t.column :author_id, :integer 
    t.column :subscriber_id, :integer 
end 

Point Tác giả với nó:

class Author < ActiveRecord::Base 
    has_and_belongs_to_many :subscribers 
    :class_name => "Author", 
    :join_table => "subscriptions", 
    :association_foreign_key => "subscriber_id" 

    def subscriptions # "subscribers" is already included above 
    self.subscribers.find(:all, :subscriber_id=>author.id) # hopefully not too 
    end              # much SQL 
end 

Nếu bạn đang thực sự cam kết tên phương pháp của bạn:

def subscribed_to_author 
    subscribers 
    end 

    def subscribed_by_author(author) 
    self.subscribers.find(:all, :subscriber_id=>author.id) 
    end 

Tạo một số kết nối (Tôi muốn làm SubscriptionsController là Resty)

SubscriptionsController < ApplicationController 
    def create 
    @author = Author.find(params[:author_id] # author to be subscribed to 
    @user = current_user # user clicking the "subscribe" button 

    @author.subscribers << @user # assuming authors should only 
    @author.save     # be able to subscribe themselves 
    end 
end 

Tên hiển thị hoặc bất cứ điều gì

@author.subscribers.each do |s| 
    s.name 
end 
# ...or...and...also... 
<%= render :partial => @author.subscribers -%> 
<%= render :partial => @author.subscriptions -%> 
+0

Cảm ơn bạn! Điều đó rất hữu ích. Bây giờ tôi đã tìm thấy hai phương pháp để giải quyết vấn đề. –

+0

@Sergii, Đó là những gì tôi đang nói về câu trả lời của tôi, điều mà tôi đã xóa khi Eric vượt trội. –

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