Frage

Wie kann ich folgendes erreichen? Ich habe zwei Modelle (Blogs und Leser) und eine Tabelle, JOIN, die mir erlauben, einen N zu haben: M Beziehung zwischen ihnen:

class Blog < ActiveRecord::Base
  has_many :blogs_readers, :dependent => :destroy
  has_many :readers, :through => :blogs_readers
end

class Reader < ActiveRecord::Base
  has_many :blogs_readers, :dependent => :destroy
  has_many :blogs, :through => :blogs_readers
end

class BlogsReaders < ActiveRecord::Base
  belongs_to :blog
  belongs_to :reader
end

Was ich jetzt tun möchte, ist Leser in den verschiedenen Blogs. Die Bedingung ist allerdings, dass ich nur einen Leser zu einem Blog hinzufügen kann ONCE. Es muss also nicht alle Duplikate (gleicher readerID, gleicher blogID) in der BlogsReaders Tabelle. Wie kann ich erreichen das?

Die zweite Frage ist, wie kann ich eine Liste von Blog zu bekommen, dass die Leser nicht abonniert ist bereits (zB eine Dropdown-Auswahlliste zu füllen, die dann verwendet werden kann, um den Leser zu einem anderen Blog)?

War es hilfreich?

Lösung

Was ist mit:

Blog.find(:all,
          :conditions => ['id NOT IN (?)', the_reader.blog_ids])

Rails kümmert sich um die Sammlung von ids für uns mit Assoziationsmethoden! :)

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ ClassMethods.html

Andere Tipps

Einfachere Lösung das ist eingebaut in Rails:

 class Blog < ActiveRecord::Base
     has_many :blogs_readers, :dependent => :destroy
     has_many :readers, :through => :blogs_readers, :uniq => true
    end

    class Reader < ActiveRecord::Base
     has_many :blogs_readers, :dependent => :destroy
     has_many :blogs, :through => :blogs_readers, :uniq => true
    end

    class BlogsReaders < ActiveRecord::Base
      belongs_to :blog
      belongs_to :reader
    end

Beachten Sie die :uniq => true Option zum has_many Gespräch hinzugefügt wird.

Auch möchten Sie vielleicht has_and_belongs_to_many zwischen Blog und Reader betrachten, es sei denn, Sie einige andere Attribute würden Sie auf dem Join-Modell haben möchte (was man nicht tun, zur Zeit). Diese Methode hat auch eine :uniq opiton.

Beachten Sie, dass dies verhindert nicht aus den Einträgen in der Tabelle erstellen, aber es ist sicher, dass, wenn Sie die Sammlung Abfrage erhalten Sie nur eine der einzelne Objekte.

Aktualisieren

In Rails 4 die Art und Weise zu tun, es über einen Umfang Block ist. Die oben genannten Änderungen.

class Blog < ActiveRecord::Base
 has_many :blogs_readers, dependent:  :destroy
 has_many :readers,  -> { uniq }, through: :blogs_readers
end

class Reader < ActiveRecord::Base
 has_many :blogs_readers, dependent: :destroy
 has_many :blogs, -> { uniq }, through: :blogs_readers
end

class BlogsReaders < ActiveRecord::Base
  belongs_to :blog
  belongs_to :reader
end

Update für Rails 5

Die Verwendung von uniq im Rahmen Block einen Fehler NoMethodError: undefined method 'extensions' for []:Array verursachen. Verwenden distinct statt:

class Blog < ActiveRecord::Base
 has_many :blogs_readers, dependent:  :destroy
 has_many :readers,  -> { distinct }, through: :blogs_readers
end

class Reader < ActiveRecord::Base
 has_many :blogs_readers, dependent: :destroy
 has_many :blogs, -> { distinct }, through: :blogs_readers
end

class BlogsReaders < ActiveRecord::Base
  belongs_to :blog
  belongs_to :reader
end

Dies sollte Ihre erste Frage kümmern:

class BlogsReaders < ActiveRecord::Base
  belongs_to :blog
  belongs_to :reader

  validates_uniqueness_of :reader_id, :scope => :blog_id
end

Die Rails 5.1 Art und Weise

class Blog < ActiveRecord::Base
 has_many :blogs_readers, dependent:  :destroy
 has_many :readers,  -> { distinct }, through: :blogs_readers
end

class Reader < ActiveRecord::Base
 has_many :blogs_readers, dependent: :destroy
 has_many :blogs, -> { distinct }, through: :blogs_readers
end

class BlogsReaders < ActiveRecord::Base
  belongs_to :blog
  belongs_to :reader
end

Die Antwort auf diesen Link zeigt, wie das außer Kraft setzen „<<“ Methode zu erreichen, was Sie suchen, ohne Ausnahmen zu erhöhen oder eine separate Methode zu erstellen: Rails Idiom Duplikate in has_many zu vermeiden: durch

Ich denke, jemand mit einer besseren Antwort als diese kommen wird.

the_reader = Reader.find(:first, :include => :blogs)

Blog.find(:all, 
          :conditions => ['id NOT IN (?)', the_reader.blogs.map(&:id)])

[Bearbeiten]

Bitte beachten Sie Joshs Antwort unten. Es ist der Weg zu gehen. (Ich wusste, dass es einen besseren Weg, war da draußen;)

Die Top-Antwort sagt derzeit uniq im proc zu verwenden:

class Blog < ActiveRecord::Base
 has_many :blogs_readers, dependent:  :destroy
 has_many :readers,  -> { uniq }, through: :blogs_readers
end

Dies tritt jedoch die Beziehung in ein Array und kann die Dinge brechen, die Operationen auf eine Beziehung, kein Array.

auszuführen erwarten

Wenn Sie distinct es es als eine Beziehung hält:

class Blog < ActiveRecord::Base
 has_many :blogs_readers, dependent:  :destroy
 has_many :readers,  -> { distinct }, through: :blogs_readers
end

einfachste Weg ist, um die Beziehung zu einem Array serialisieren:

class Blog < ActiveRecord::Base
  has_many :blogs_readers, :dependent => :destroy
  has_many :readers, :through => :blogs_readers
  serialize :reader_ids, Array
end

Dann, wenn die Werte für die Leser zuweisen, gelten Sie sie als

blog.reader_ids = [1,2,3,4]

Wenn Beziehungen auf diese Weise zuweisen, werden Duplikate automatisch entfernt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top