غادر الانضمام في القضبان / mysql
-
12-09-2019 - |
سؤال
أنا مبتدئ في القضبان وحاول أداء النقد الأيسر في mysql.
هناك كائنين - المستخدم والرسالة.
المستخدم has_and_belongs_to_many رسائل، رسالة has_and_belongs_to_many المستخدمين
حاليا، ببساطة عن طريق كتابة User.Messages أحصل على استعلام متابع في وحدة التحكم
SELECT * FROM `messages` INNER JOIN `messages_users` ON `messages`.id = `messages_users`.message_id WHERE (`users_messages`.group_id = 1 )
رسالة مع مقيدة == FALSE غير متصل بأي مستخدم ولكني يمكن الوصول إليها من قبل أي مستخدم، وأحتاج إلى إضافة رسالة جمع. جميع (مقيد => خطأ) للمستخدم.
الاستعلام الذي من شأنه أن يحل مشكلتي سيكون:
select * from messages left join messages_users on messages_users.message_id=messages.id and messages_users.user_id=1 where (messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true);
كيف أكتبها في القضبان بأناقة قدر الإمكان؟
هل سيكون مثل
Message.find(:all,:conditions => "(messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true)", :joins => "left join messages_groups on messages_users.message_id=messages.id and messages_users.user_id=1 " )
أو هل يمكن أن يكون أجمل؟
أنا أستخدم القضبان 2.3.2
شكرا، بافل
المحلول
يبدو لي أنك تحاول سحب شيئين في هذا الاستعلام: 1) جميع الرسائل غير مرتبطة للمستخدم مع تقييد = False و 2) جميع الرسائل مرتبطة بالمستخدم الحالي مع تقييد = صحيح.
إذا كنت أفهم ذلك بشكل صحيح، فأنا لا أرى طريقة أفضل للقيام بذلك إذا كنت تريد القيام بذلك كاستعلام واحد. ومع ذلك، إذا كنت مفتوحا لفكرة جعلها استفسارا، فيمكنك تنظيفه قليلا في التعليمات البرمجية (مع إبطاء الإعدام). هنا هو الإعداد البديل:
class Message < ActiveRecord:Base
has_and_belongs_to_many :users
named_scope :restricted, :conditions => {:restricted => true}
named_scope :unrestricted, :conditions => {:restricted => false}
named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM messages_users)"
end
class User < ActiveRecord:Base
has_and_belongs_to_many :messages
end
للحصول على القائمة في رمز أقل، ولكن تتطلب ضربتين من الزيارات التي يمكنك القيام بها:
@current_user.messages.restricted + Message.unrestricted.public
في كلتا الحالتين إذا كان هناك أي قدر كبير من البيانات في هذه الجداول، تحتاج إلى التأكد من فهرستها بشكل صحيح أو أن هذا سيبضيء مع أي حمولة. إذا كان هذا التطبيق مع الكثير من الرسائل التي يتم إرسالها، فربما تكون أفضل حالا مع الاستعلام الفردي. إذا كانت مجرد وظيفة جانبية لن يتم استخدامها كثيرا، فربما أتناول الإصدار الأنظف.
ما هو من المحتمل أن يعمل بشكل أفضل من منظور النموذج هو التخلص من علاقة Habtm ونموذج العلاقة بشكل صريح. ثم لديك مكان مفيد لتتبع البيانات الأخرى حول عملية إرسال / التسليم / التسليم / الاستقبال (مثل وقت التتبع المرسل، وقراءة الوقت، إلخ). لا يغير أي من المناقشة أعلاه، وأفضل فقط أن يكون لديه الكثير إلى Habtm.
class Message < ActiveRecord:Base
has_many :subscriptions
has_many :users, :through => :subscriptions
named_scope :restricted, :conditions => {:restricted => true}
named_scope :unrestricted, :conditions => {:restricted => false}
named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM subscriptions)"
end
class User < ActiveRecord:Base
has_many :subscriptions
has_many :messages, :through => :subscriptions
end
class Subscription < ActiveRecord:Base
belongs_to :message
belongs_to :user
end
نصائح أخرى
لماذا لا تستخدم: تشمل؟
أعتقد أن named_scopes قد تكون جوابك. في النموذج الخاص بك وضع شيء مثل:
named_scope :restricted, :conditions => {:restricted => true}
named_scope :unrestricted, :conditions => {:restricted => false}
ثم يمكنك الاتصال بأشياء مثل:
Message.restricted
=> All restricted messages
User.first.messages.unrestricted
=> All unrestricted messages belonging to the first user.
أعتقد أن هذه العمل من خلال جمعيات Habtm.