मेरे एप्लिकेशन में एक नौकरी मॉडल है। सिस्टम में प्रत्येक नौकरी में contact
है। यह उस व्यक्ति की तरह है जिसे आप कॉल करेंगे यदि आपको नौकरी के बारे में कोई सवाल पूछने की ज़रूरत है। एक संपर्क या तो client
या ग्राहक के कर्मचारी (ClientEmployee
) हो सकता है।ActiveRecord को जोड़ना :: पॉलिमॉर्फिक एसोसिएशन के माध्यम से पूछे जाने वाले संबंध
class Job < ActiveRecord::Base
belongs_to :contact, polymorphic: true
end
class Client < ActiveRecord::Base
has_many :jobs, as: :contact
has_many :employees, class_name: 'ClientEmployee'
end
class ClientEmployee < ActiveRecord::Base
belongs_to :client
has_many :jobs, as: :contact
end
ग्राहकों के पास commissioned_jobs
का विचार है। ग्राहकों ने नौकरियां शुरू की हैं वे नौकरियां हैं जिनके लिए ग्राहक संपर्क है या ग्राहक के कर्मचारियों में से एक संपर्क है।
class Client < ActiveRecord::Base
has_many :jobs, as: :contact
has_many :employee_jobs, through: :employees, source: :jobs
def commissioned_jobs
jobs << employee_jobs
end
end
एक तरफ: यह विधि एक हैक का एक सा है क्योंकि यह एक ActiveRecord::Relation
से एक सरणी देता है बल्कि है। यह भी दिलचस्प है कि अगर मैं कर्मचारी_jobs में नौकरियों को जोड़ना चाहता हूं तो यह उड़ाता है। यह मेरे उद्देश्यों के लिए कर सकता है या नहीं कर सकता है।
मैं Client
पर with_commissioned_jobs
नामक एक दायरा जोड़ना चाहता हूं। यह उन सभी ग्राहकों को वापस लौटाएगा जिनके पास नौकरियां हैं या जिनके पास नौकरियां हैं।
class Client < ActiveRecord::Base
def self.with_commissioned_jobs
# I can get clients with jobs using: joins(:jobs). How do
# I also include clients with employees who have jobs?
end
end
मैं इस विधि को कैसे कार्यान्वित करूं?
मैं रेल 3.2.9 का उपयोग कर रहा हूं।
अद्यतन:
मैं कुछ प्रगति की है और मैं अब दो तरीकों, जिनमें से प्रत्येक मैं क्या जरूरत का आधा करता है।
class Client < ActiveRecord::Base
# Return all clients who have an employee with at least one job.
def self.with_employee_jobs
joins(employees: :jobs)
# SQL: SELECT "clients".* FROM "clients" INNER JOIN "client_employees" ON "client_employees"."employer_id" = "clients"."id" INNER JOIN "jobs" ON "jobs"."contact_id" = "client_employees"."id" AND "jobs"."contact_type" = 'ClientEmployee'
end
# Return all clients who have at least one job.
def self.with_jobs
joins(:jobs)
# SQL: SELECT "clients".* FROM "clients" INNER JOIN "jobs" ON "jobs"."contact_id" = "clients"."id" AND "jobs"."contact_type" = 'Client'
end
end
अब सभी मैं क्या करने की जरूरत गठबंधन इन दोनों विधि एक ActiveRecord::Relation
में कहता है। मैं स्पष्ट रूप से यह कर सकते हैं:
def self.with_commissioned_jobs
with_jobs + with_employee_jobs
end
समस्या यह है कि कि Relation
का एक उदाहरण के बजाय एक सरणी देता है और मैं इस पर श्रृंखला अधिक दायरे नहीं कर सकता।
अद्यतन 2:
merge
का उपयोग या तो काम करने के लिए प्रकट नहीं होता। यहां एआर क्वेरी और परिणामी एसक्यूएल है।
joins(:jobs).merge(joins(employees: :jobs))
SELECT "clients".* FROM "clients" INNER JOIN "jobs"
ON "jobs"."contact_id" = "clients"."id"
AND "jobs"."contact_type" = 'Client'
INNER JOIN "client_employees"
ON "client_employees"."employer_id" = "clients"."id"
INNER JOIN "jobs" "jobs_client_employees"
ON "jobs_client_employees"."contact_id" = "client_employees"."id"
AND "jobs_client_employees"."contact_type" = 'ClientEmployee'
वैसे, यहां परीक्षण हैं जिन्हें मैं पास करने की कोशिश कर रहा हूं। पहला परीक्षण विफल रहता है क्योंकि जब मैं विलय का उपयोग करता हूं तो शून्य परिणाम होते हैं।
describe "with_commissioned_jobs" do
# A client with a job.
let!(:client_with) { create :client }
let!(:job) { create :job, contact: client_with }
# A client who does not himself have a job, but who has an employee
# with a job.
let!(:client_with_emp) { create :client }
let!(:employee) { create :client_employee, employer: client_with_emp }
let!(:emp_job) { create :job, contact: employee }
# A client with nothing. Should not show up.
let!(:client_without) { create :client }
it "should return clients with jobs and clients with employee jobs" do
Client.with_commissioned_jobs.should == [client_with, client_with_emp]
end
it "should return a relation" do
Client.with_commissioned_jobs.should be_instance_of(ActiveRecord::Relation)
end
end
क्या आपने द्वीप में देखा है? https://github.com/rails/arel इसमें प्रश्नों के लिए एक शर्त है, और जटिल संभालती है। – John
मैं निश्चित रूप से एक एरियल आधारित समाधान भी स्वीकार करूंगा। मैंने एक के साथ आने की कोशिश करने में काफी कुछ घंटे बिताए हैं और मुझे लगता है कि मैं इसे प्रबंधित करने में सक्षम नहीं हूं। –