سؤال

أنا أستخدم الارتباطات متعددة الأشكال لتتبع التعليقات في مشروعي.جميع الأشياء مستقيمة جدًا.

تكمن المشكلة التي أواجهها في الاستعلام بناءً على الارتباط متعدد الأشكال والانضمام من نموذج التعليق إلى مالكه.

لذا ...

لدي نموذج تعليق

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

ووضع ForumTopics:

class ForumTopic < ActiveRecord::Base
  has_many :comments, :as => :commentable
end

لدي العديد من النماذج الأخرى "القابلة للتعليق" والتي ليست مهمة في الوقت الحالي.كل هذا يعمل.

ما أحاول القيام به هو العثور على جميع التعليقات التي تنتمي إلى ForumTopic بشرط محدد (في هذه الحالة، 'featured' == true).

عندما أحاول استخدام أداة البحث للانضمام إلى النماذج:

@comments = Comment.find(:all 
            :joins => :commentable
            :conditions => ["forum_topics.featured = ? ", true] 
            )

أتلقى الخطأ التالي:

لا يمكن تحميل الارتباط متعدد الأشكال بفارغ الصبر: قابل للتعليق

باستخدام AR "تضمين بناء الجملة":

@comments = Comment.find(:all 
            :include => :forum_topics
            :conditions => ["forum_topics.featured = ? ", true] 
            )

عائدات:

لم يتم العثور على الارتباط المسمى 'forum_topics'؛ربما أخطأت في كتابتها؟

إذا حاولت الانضمام باسم جدول بدلاً من اسم الارتباط (سلسلة بدلاً من الرمز):

@comments = Comment.find(:all,
            :joins => "forum_topics",
            :conditions => ["forum_topics.featured = ? ", true] 
            )

أرى:

الخلية خطأ:"تعليقات" الجدول غير معروفة:حدد التعليقات. من التعليقات forum_topics حيث (forum_topics.featured = 1)*

(يمكنك أن ترى هنا أن بناء جملة الاستعلام الأساسي معطل تمامًا وأن الصلة مفقودة تمامًا).

لست متأكدًا مما إذا كان ما أفعله ممكنًا أم لا، وهناك طرق أخرى لتحقيق النتيجة المطلوبة ولكن يبدو الأمر كذلك يجب تكون قابلة للتنفيذ.

أيه أفكار؟أي شيء أنا في عداد المفقودين؟

هل كانت مفيدة؟

المحلول

وأرغ!

وأعتقد أنني وجدت المشكلة.

عند الانضمام عن طريق:

@comments = Comment.find(:all,
        :joins => "forum_topics",
        :conditions => ["forum_topics.featured = ? ", true] 
        )

وتحتاج كلها انضمام!

:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id",

وانظر-رهيبة من أي وقت مضى: http://guides.rubyonrails.org/active_record_querying.html#joining-tables

نصائح أخرى

وهناك سؤال من العمر، ولكن هناك وسيلة أكثر نظافة لتحقيق ذلك من خلال إنشاء ارتباط مباشر لنوع معين جنبا إلى جنب مع متعددة الأشكال:

#comment.rb
class Comment < ActiveRecord::Base

  belongs_to :commentable, polymorphic: true
  belongs_to :forum_topics, -> { where( comments: { commentable_type: 'ForumTopic' } ).includes( :comments ) }, foreign_key: 'commentable_id'

  ...

end

وأنت ثم قادرة على تمرير :forum_topics إلى includes التخلص من الحاجة إلى الفوضى الانضمام:

@comments = Comment
  .includes( :forum_topics )
  .where( :forum_topics => { featured: true } )

ويمكنك بعد ذلك زيادة تنظيف هذا عن طريق تحريك الاستعلام في نطاق:

#comment.rb
class Comment < ActiveRecord::Base

  ...

  scope :featured_topics, -> { 
    includes( :forum_topics )
    .where( :forum_topics => { featured: true } ) 
  }

  ...

end

وترك لك أن تكون قادرة على القيام بكل بساطة

@comments = Comment.featured_topics

أنت في حاجة إلى الشرطية، بالإضافة إلى القضبان 3+

ألمح الكثير من الأشخاص إلى ذلك في الإجابات والتعليقات، لكنني شعرت أن الناس، بما فيهم أنا، سوف يتعثرون إذا وصلت إلى هنا ولم أقرأ جيدًا بما فيه الكفاية.

إذن، هذه هي الإجابة الصحيحة، بما في ذلك الشرط قطعاً ضروري.

@comments = Comment.joins( "INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id" )
                   .where( comments:     { commentable_type: 'ForumTopic' } )
                   .where( forum_topics: { featured:         true         } )

شكرًا للجميع، وخاصةJits وPeter و@prograils على تعليقاتهم.

والحل المقبول لا تعمل بمجرد إدخال نموذج آخر يحتوي على الارتباط باستخدام "commentable". commentable_id ليست وحيدة، وبالتالي عليك أن تبدأ استرجاع التعليقات خاطئة.

وعلى سبيل المثال:

وعليك أن تقرر لإضافة نموذج الأخبار التي تقبل التعليقات ...

class News < ActiveRecord::Base
   has_many :comments, :as => :commentable
end

والآن قد تحصل على اثنين من السجلات مرة أخرى إذا قمت بعمل تعليق على forum_topic مع معرف 1 والمادة الإخبارية مع معرف 1 باستخدام الاستعلام الخاص بك:

:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id"

وربما يمكن أن تحل المشكلة عن طريق تزويد commentable_type كأحد الشروط الخاصة بك، ولكن لا أعتقد أن هذا هو أفضل وسيلة لمعالجة هذه المسألة.

وجئت عبر هذا المنصب، وأنه يؤدي بي إلى بلدي الحل. باستخدام commentable_type باعتبارها واحدة من شروطي ولكن باستخدام LEFT JOIN خارجية بدلا من ذلك. وستدرج أن موضوعات المنتدى وسيلة دون تعليق.

LEFT OUTER JOIN `comments` ON `comments`.`commentable_id` = `forum_topics`.`id` AND `comments`.`commentable_type` = 'ForumTopic'

فحص للعمل تحت القضبان 5:

الحل 1:

@comments = Comment
              .where(commentable_type: "ForumTopic")
              .joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id")
              .where(forum_topics: {featured: true})
              .all

أو

الحل 2:

@comments = Comment
              .joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id AND comments.commentable_type = 'ForumTopic'")
              .where(forum_topics: {featured: true}).all

انتبه إلى بناء جملة SQL الخام:لا يُسمح بالنقرات الخلفية.يرى http://guides.rubyonrails.org/active_record_querying.html#joining-tables .

أنا شخصيا أفضل الحل 1 لأنه يحتوي على عدد أقل من بناء جملة SQL الخام.

لا يشمل

والقضبان ومتعدد الأشكال الانضمام افتراضيا ولكن هذا جوهرة تساعدك على تنضم علاقة متعددة الأشكال الخاصة بك مع سهولة. https://github.com/jameshuynh/polymorphic_join

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top