2011-12-23 11 views
5

मैं एचएबीटीएम संबंध, कैनकन, और ActiveRecord एक आत्म संदर्भ का उपयोग कर इस स्थिति को संभालने के तरीके पर फंस गया हूँ।आप कैनकन क्षमता कैसे लिख सकते हैं? और एचबीटीएम रिलेशनशिप के संदर्भ में दोनों कामों को सुलभ कर सकते हैं?

मैं accessible_by उपयोग करने के लिए वीडियो है कि दृश्य वीडियो और चैनल के बीच एक रिश्ता दिया जाता है का एक सेट निर्धारित करने के लिए कोशिश कर रहा हूँ, लेकिन जिसके परिणामस्वरूप SQL क्वेरी के भाग के लिए गलत तालिका नाम है। यहाँ रिश्तों हैं:

# video.rb 
class Video < ActiveRecord::Base 
    belongs_to :channel 
end 

# channel.rb 
class Channel < ActiveRecord::Base 
    has_many :videos 
    has_and_belongs_to_many :subchannels, :class_name => "Channel", :join_table => "channels_channels", :foreign_key => :parent_id, :association_foreign_key => :subchannel_id 
    has_and_belongs_to_many :parent_channels, :class_name => "Channel", :join_table => "channels_channels", :foreign_key => :subchannel_id, :association_foreign_key => :parent_id 
end 

# The appropriate channels_channels table exists with subchannel_id and parent_id fields. 

मैं एक कैनकैन क्षमता सभी सार्वजनिक वीडियो कि डिफ़ॉल्ट चैनल की सार्वजनिक उप चैनलों में हैं खोजने की जरूरत है।

# ability.rb 
can :read, Video, :permission => 'public', :channel => {:permission => 'public', :parent_channels => {:name => "Default"}} 

कंसोल में, जब मैं इस बाहर की कोशिश, मैं निम्नलिखित मिल:

> Video.accessible_by(Ability.new(nil)) 
SELECT "videos".* FROM "videos" INNER JOIN "channels" ON "channels"."id" = "videos"."channel_id" INNER JOIN "channels_channels" ON "channels_channels"."subchannel_id" = "channels"."id" INNER JOIN "channels" "parent_channels_channels" ON "parent_channels_channels"."id" = "channels_channels"."parent_id" WHERE "videos"."permission" = 'public' AND "channels"."permission" = 'public' AND "channels"."name" = 'Default' 
=> [] 

मैं जगह में कुछ रिकॉर्ड है कि एक वीडियो में परिणाम चाहिए है, और, और अधिक मैं निम्नलिखित की कोशिश की बिंदु पर, "parent_channels_channels"। "name" = 'default' होने के बाद क्वेरी के अंत की उम्मीद होगी, लेकिन तालिका "चैनल" स्थिर है, जिसके परिणामस्वरूप SQL डेटा संदर्भित होने के बाद गलत डेटासेट है चैनल का नाम, माता-पिता चैनल नहीं।

मैं क्षमता को बदलने के रूप में तालिका नाम के लिए मजबूर करने की कोशिश की इस प्रकार है:

can :read, Video, :permission => 'public', :channel => {:permission => 'public', :parent_channels => {"parent_channels_channels.name" => "Default"}} 

यह सही क्वेरी में परिणाम है, और accessible_by रिटर्न सही डाटासेट है, लेकिन फिर कर सकते हैं (: पढ़ें, वीडियो) उस परिणाम में एक वीडियो के लिए सेट रनटाइम त्रुटि में परिणाम।

NoMethodError: undefined method `parent_channels_channels.name' for #<Channel:0x007fef35593748> 

मैं कैसे तो यह दोनों कर सकते हैं के साथ काम करता इस क्षमता निर्दिष्ट करूँ? और सुलभ_by?

उत्तर

0

यह आपके कोड से मुझे स्पष्ट नहीं है कि आप इसे सही तरीके से मॉडलिंग कर रहे हैं या नहीं। क्या आप वास्तव में parent_channels और subchannels को एक HABTM रिश्ते बनना चाहते हैं, या यहां तक ​​कि एक ही मॉडल भी हो? हो सकता है कि आपके ऐप से कुछ वास्तविक-दुनिया के उदाहरण मुझे यहां मदद करेंगे लेकिन ऐसा लगता है कि आप एक माता-पिता वीडियो कैटलॉग चाहते हैं, और आप चैनलों के साथ एचएबीटीएम संबंध चाहते हैं, जिसके बाद प्रत्येक के पास वीडियो के साथ एक बहुत अधिक संबंध है।

तब आपके पास वीडियो श्रेणी में has_many हो सकता है: वीडियो,: through =>: चैनल संबंध।

class VideoCategory 
    has_and_belongs_to_many :channels 

    has_many :videos, :through => :channels 
end 

class Video 
    belongs_to :channel 
end 

class Channel 
    has_many :videos 

    has_and_belongs_to_many :video_cateogories 
end 

ऐसा लगता है कि आप चैनल क्लास को चैनल बनाने से अधिक करने की कोशिश कर रहे हैं। माता-पिता और बच्चों की अवधारणा habtm संबंधों में बहुत अधिक समझ नहीं लेती है। आम तौर पर यदि आप एक अभिभावक वर्ग और उप वर्ग चाहते हैं, तो आप 1 से कई रिश्ते चाहते हैं। बहुत से लोगों का तात्पर्य है कि न तो एसोसिएशन मूल वर्ग है (हालांकि यह यूआई में इसे पेश करने से अलग हो सकता है)।

यदि आपको वास्तव में स्वयं-रेफरेंसियल के रूप में ऐसा करना है, तो क्या आपने इसके बजाय स्कॉप्स का उपयोग करने का प्रयास किया है?

class Video 
    scope :public, lambda do 
    joins(:channel).where("videos.permission = 'public' and channels.permission = 'public'") 
    end 
end 

ऐसा लगता है कि स्कोप में और ability.rb से बाहर तर्क डाल आप बेहतर नियंत्रण वास्तव में क्या एसक्यूएल लिखा हो जाता है मदद कर सकता है - यह अमूर्त की परत है कि कैनकैन कर रही है निकाल देता है।

संबंधित मुद्दे

 संबंधित मुद्दे