문제

다음을 어떻게 달성 할 수 있습니까? 나는 두 가지 모델 (블로그와 독자)과 조인 테이블이있어서 그들 사이에 n : m 관계를 가질 수 있습니다.

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

내가 지금하고 싶은 것은 다른 블로그에 독자를 추가하는 것입니다. 그러나이 조건은 블로그에 독자를 한 번만 추가 할 수 있다는 것입니다. 따라서 복제물이 없어야합니다 (동일 readerID, 같은 blogID)에서 BlogsReaders 테이블. 이것을 어떻게 달성 할 수 있습니까?

두 번째 질문은 독자가 이미 구독하지 않은 블로그 목록을 얻는 방법입니다 (예 : 드롭 다운 선택 목록을 채우고 다른 블로그에 독자를 추가하는 데 사용할 수 있는가)?

도움이 되었습니까?

해결책

는 어때:

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

Rails는 협회 방법으로 우리를위한 ID 모음을 처리합니다! :)

http://api.rubyonrails.org/classes/activerecord/associations/classmethods.html

다른 팁

레일에 내장 된 더 간단한 솔루션 :

 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

참고 추가 :uniq => true 옵션 has_many 전화.

또한 고려하고 싶을 수도 있습니다 has_and_belongs_to_many 블로그와 독자 사이에, 가입 모델에 가고 싶은 다른 속성이 없다면 (현재하지 않는). 그 방법에는 a가 있습니다 :uniq Opiton.

이렇게하면 테이블에서 항목을 생성하지 못하지만 컬렉션을 쿼리 할 때 각 객체 중 하나만 얻을 수 있습니다.

업데이트

Rails 4에서는 범위 블록을 통한 방법입니다. 위의 변경.

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

레일에 대한 업데이트 5

사용 uniq 스코프 블록에서 오류가 발생합니다 NoMethodError: undefined method 'extensions' for []:Array. 사용 distinct 대신에 :

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

이것은 첫 번째 질문을 처리해야합니다.

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

  validates_uniqueness_of :reader_id, :scope => :blog_id
end

레일 5.1 길

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

이 링크의 답변은 예외를 제기하거나 별도의 메소드를 만들지 않고 원하는 것을 달성하기 위해 "<<"메소드를 무시하는 방법을 보여줍니다. Has_many의 복제를 피하려는 Rails 관용구 :

나는 누군가가 이것보다 더 나은 대답을 함께 올 것이라고 생각합니다.

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

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

편집하다

아래 Josh의 답변을 참조하십시오. 가는 길입니다. (나는 거기에 더 나은 방법이 있다는 것을 알고 있었다;)

최고 답변은 현재 사용한다고합니다 uniq Proc에서 :

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

그러나 이것은 관계를 배열로 시작하고 배열이 아닌 관계에서 작업을 수행 할 것으로 예상되는 것들을 깨뜨릴 수 있습니다.

사용하는 경우 distinct 그것은 그것을 관계로 유지합니다.

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

가장 쉬운 방법은 관계를 배열로 연속화하는 것입니다.

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

그런 다음 독자에게 값을 할당 할 때

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

이런 방식으로 관계를 할당 할 때 중복은 자동으로 제거됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top