Pregunta

Supongamos que tenemos un sitio de fotografía. Cualquier autor puede suscribirse para recibir actualizaciones de cualquier otro autor. Obviamente, si el autor está suscrito a un autor que B no significa que B está suscrito a A. Así construimos modelos

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

De esta manera podemos usar

  1. some_author.subscribed_by_author -. La lista de los autores a los que está suscrito some_author
  2. Para cualquier suscripción que podemos conocer ambos extremos (que esté suscrito a quién)

Sin embargo, la cuestión es cómo conseguir que la lista de personas suscritas a algún autor utilizando sólo los carriles (no utilizando SQL normal) es decir obtener la respuesta a: "¿Quién está suscrito a some_author"

Pregunta: ¿hay alguna posibilidad de rieles para obtener la relación de trabajo a ambos lados es decir, no sólo la escritura some_author.subscribed_BY_author pero tener some_author_subscribed_TO_author? Si hay uno, entonces ¿qué es?

P.S. solución obvia es

  1. Cambiar el diseño de la base de datos, añadiendo una columna denominada "dirección"
  2. Crear 2 registros cada vez que se crea una suscripción
  3. Añadir a la modelo de autor

    has_many: subscribed_BY_author,: a través de =>: suscripciones,: fuente =>: subscribed_to,: condiciones => "dirección = 'por'"

    has_many: subscribed_TO_author,: a través de =>: suscripciones,: fuente =>: subscribed_to,: condiciones => "dirección = 'a'"

Pero me pregunto si hay una solución sin cambiar el diseño de la base de datos.

¿Fue útil?

Solución

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

Por lo que yo sé - que funciona! :)

Otros consejos

que haría uso de HABTM llanura de algo tan simple como este, pero vas a necesitar una tabla de unión no importa qué.

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

Punto de Autor a ella:

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

Si usted está realmente comprometido con sus nombres de método:

  def subscribed_to_author
    subscribers
  end

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

Crea algunas conexiones (que me gustaría hacer SubscriptionsController sea 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

Los nombres para mostrar, o lo que sea

@author.subscribers.each do |s|
  s.name
end
# ...or...and...also...
<%= render :partial => @author.subscribers -%>
<%= render :partial => @author.subscriptions -%>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top