11

प्रोजेक्ट में मैं वर्तमान में रेल 4.0.0beta1 के तहत विकसित कर रहा हूं, मुझे उपयोगकर्ता आधारित प्रमाणीकरण की आवश्यकता थी जिसमें प्रत्येक उपयोगकर्ता को किसी इकाई से जोड़ा जा सकता था। मैं रेल के लिए थोड़ी नई हूं और ऐसा कुछ परेशानी कर रही है।बहु-टेबल विरासत

मॉडल निम्नलिखित है:

class User < ActiveRecord::Base 
end 

class Agency < ActiveRecord::Base 
end 

class Client < ActiveRecord::Base 
    belongs_to :agency 
end 

क्या मैं जरूरत है एक उपयोगकर्ता (मैं क्या संस्थाओं बुला हो जाएगा उन दो या तो एक एजेंसी या एक ग्राहक पर दोनों नहीं से जोड़ने के लिए सक्षम होने के लिए के लिए है)। इसमें कोई लिंक नहीं हो सकता है और अधिकांश लिंक पर।

पहली चीज़ जो मैंने देखा वह रेल में Mutli-Table inheritance (एमटीआई) कैसे करना है। लेकिन कुछ चीजें मुझे अवरुद्ध:

  • यह बॉक्स से बाहर उपलब्ध नहीं था
  • जवाहरात को लागू समाधान पुरानी है और या तो बहुत Complexe लग रहा था या
  • एमटीआई इस तरह के रूप में मुझे एक नौसिखिया के लिए लागू करने के लिए थोड़े कठिन लग रहा था नहीं पूरा
  • जवाहरात शायद rails4 के तहत तोड़ दिया है | के रूप में वे थोड़ी देर के

तो मैं एक और समाधान के लिए देखा के लिए अद्यतन नहीं किया गया था और मैं polymorphic associations पाया।

मैं कल के बाद से इस पर हो सकता था और उसे यह भी ActiveRecord, has_many :through, and Polymorphic Associations

मैं काम से ऊपर सवाल से उदाहरण बनाने में कामयाब रहे Rails polymorphic has_many :through की मदद और साथ काम करने के लिए कुछ समय लिया, लेकिन यह कुछ समय लिया और मैं आखिर में दो समस्याएं हैं:

  1. उपयोगकर्ता में संबंधों को हैसोन एसोसिएशन में कैसे परिवर्तित करें और लिंक की गई इकाई को "अंधेरे" तक पहुंचने में सक्षम कैसे हो?
  2. एक बाधा कैसे सेट करें ताकि कोई उपयोगकर्ता एक से अधिक इकाई न हो?
  3. क्या मैं चाहता हूं कि ऐसा करने का कोई बेहतर तरीका है?

उत्तर

11

यहाँ एक पूरी तरह से काम कर रहे उदाहरण है:

प्रवास फ़ाइल:

class CreateUserEntities < ActiveRecord::Migration 
    def change 
    create_table :user_entities do |t| 
     t.integer :user_id 
     t.references :entity, polymorphic: true 

     t.timestamps 
    end 

    add_index :user_entities, [:user_id, :entity_id, :entity_type] 
    end 
end 

मॉडल:

class User < ActiveRecord::Base 
    has_one :user_entity 

    has_one :client, through: :user_entity, source: :entity, source_type: 'Client' 
    has_one :agency, through: :user_entity, source: :entity, source_type: 'Agency' 

    def entity 
    self.user_entity.try(:entity) 
    end 

    def entity=(newEntity) 
    self.build_user_entity(entity: newEntity) 
    end 
end 

class UserEntity < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :entity, polymorphic: true 

    validates_uniqueness_of :user 
end 

class Client < ActiveRecord::Base 
    has_many :user_entities, as: :entity 
    has_many :users, through: :user_entities 
end 

class Agency < ActiveRecord::Base 
    has_many :user_entities, as: :entity 
    has_many :users, through: :user_entities 
end 

आप देख सकते हैं मैं एक गेटर और एक सेटर कहा कि मैं नाम "इकाई"।

ActiveRecord::HasManyThroughAssociationPolymorphicSourceError: Cannot have a has_many :through association 'User#entity' on the polymorphic object 'Entity#entity' without 'source_type'. Try adding 'source_type: "Entity"' to 'has_many :through' definition. 

अंत में, यहाँ परीक्षण मैं की स्थापना कर रहे हैं: ऐसा इसलिए है क्योंकि has_one :entity, through: :user_entity निम्नलिखित त्रुटि को जन्म देती है। मैं उन्हें देता हूं ताकि हर कोई समझ सके कि आप उन वस्तुओं के बीच डेटा सेट और एक्सेस कर सकते हैं। मैं अपने फैक्टरीगर्ल मॉडल का विस्तार नहीं करूँगा लेकिन वे बहुत स्पष्ट हैं

require 'test_helper' 

class UserEntityTest < ActiveSupport::TestCase 

    test "access entity from user" do 
    usr = FactoryGirl.create(:user_with_client) 

    assert_instance_of client, usr.user_entity.entity 
    assert_instance_of client, usr.entity 
    assert_instance_of client, usr.client 
    end 

    test "only right entity is set" do 
    usr = FactoryGirl.create(:user_with_client) 

    assert_instance_of client, usr.client 
    assert_nil usr.agency 
    end 

    test "add entity to user using the blind rails method" do 
    usr = FactoryGirl.create(:user) 
    client = FactoryGirl.create(:client) 

    usr.build_user_entity(entity: client) 
    usr.save! 

    result = UserEntity.where(user_id: usr.id) 
    assert_equal 1, result.size 
    assert_equal client.id, result.first.entity_id 
    end 

    test "add entity to user using setter" do 
    usr = FactoryGirl.create(:user) 
    client = FactoryGirl.create(:client) 

    usr.client = client 
    usr.save! 

    result = UserEntity.where(user_id: usr.id) 
    assert_equal 1, result.size 
    assert_equal client.id, result.first.entity_id 
    end 

    test "add entity to user using blind setter" do 
    usr = FactoryGirl.create(:user) 
    client = FactoryGirl.create(:client) 

    usr.entity = client 
    usr.save! 

    result = UserEntity.where(user_id: usr.id) 
    assert_equal 1, result.size 
    assert_equal client.id, result.first.entity_id 
    end 

    test "add user to entity" do 
    usr = FactoryGirl.create(:user) 
    client = FactoryGirl.create(:client) 

    client.users << usr 

    result = UserEntity.where(entity_id: client.id, entity_type: 'client') 

    assert_equal 1, result.size 
    assert_equal usr.id, result.first.user_id 
    end 

    test "only one entity by user" do 

    usr = FactoryGirl.create(:user) 
    client = FactoryGirl.create(:client) 
    agency = FactoryGirl.create(:agency) 

    usr.agency = agency 
    usr.client = client 
    usr.save! 

    result = UserEntity.where(user_id: usr.id) 
    assert_equal 1, result.size 
    assert_equal client.id, result.first.entity_id 

    end 

    test "user uniqueness" do 

    usr = FactoryGirl.create(:user) 
    client = FactoryGirl.create(:client) 
    agency = FactoryGirl.create(:agency) 

    UserEntity.create!(user: usr, entity: client) 

    assert_raise(ActiveRecord::RecordInvalid) { 
     UserEntity.create!(user: usr, entity: agency) 
    } 

    end 

end 

मुझे आशा है कि यह किसी के लिए कुछ मदद की जा सकती है।मैंने पूरे समाधान को यहां लगाने का फैसला किया क्योंकि यह मुझे एमटीआई की तुलना में एक अच्छा की तरह लगता है और मुझे लगता है कि इसे किसी ऐसे व्यक्ति को नहीं लेना चाहिए जो उस तरह कुछ सेट करने के लिए है।

+0

@Crystark मुझे उपरोक्त फ़ाइल का परीक्षण करते समय निम्न त्रुटि मिलती है NameError: uninitialized निरंतर UserWithClient –

0

उपर्युक्त उत्तर मुझे कुछ परेशानी दे रहा था। विशिष्टता को सत्यापित करते समय मॉडल नाम के बजाय कॉलम नाम का उपयोग करें। Validates_uniqueness_of बदलें: उपयोगकर्ता को validates_uniqueness_of: user_id।

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