2011-09-03 11 views
6

मैं रेल के लिए नया हूं, और मैं अपने दूसरे रेल ऐप पर काम कर रहा हूं।उपयोगकर्ताओं के लिए रेल मॉडल संरचना

ऐप के उपयोगकर्ताओं के लिए अलग-अलग भूमिकाएं होंगी, लेकिन कुछ उपयोगकर्ताओं के पास कई भूमिकाएं होंगी।

साइट के प्रत्येक उपयोगकर्ता एक कलाकार होंगे। कुछ उपयोगकर्ताओं के पास एक मॉडरेटर की भूमिका होगी।

मैं इसे कैसे व्यवस्थित करूं? मैंने उपयोग किए गए कुछ PHP ऐप्स में, केवल एक उपयोगकर्ता है, और फिर is_admin के लिए डेटाबेस कॉलम है, लेकिन मैंने रेल ऐप्स के स्रोत को देखा है और उपयोगकर्ता और व्यवस्थापक आदि के लिए अलग-अलग मॉडल देखे हैं। हालांकि मैं मुझे यकीन नहीं है क्यों।

तो, क्या मेरे पास एक आदर्श विशेषता वाला एक एकल उपयोगकर्ता मॉडल होना चाहिए, जो मॉडरेटर हो सकता है, और उसके बाद मेरे विचारों, मार्गों आदि में उपयोगकर्ताओं को "कलाकार" कहें?

या मेरे पास एक उपयोगकर्ता मॉडल होना चाहिए, एक मॉडरेटर मॉडल जो इससे प्राप्त होता है, और एक कलाकार मॉडल जो उपयोगकर्ता से संबंधित है?

मैं वास्तव में उलझन में हूं।

उत्तर

7

आप डेविस और कैनकन के रत्नों की तलाश कर सकते हैं। यह जोड़ी वास्तव में शक्तिशाली संयोजन है। यह दो मॉडल उपयोगकर्ता और भूमिका बनाता है। भूमिका में आप उनके लिए नए मॉडल बनाने के बिना नई भूमिकाएं बना सकते हैं। हालांकि यह मॉडल क्षमता बनाता है, यहां आप भूमिकाओं के लिए पहुंच नियम परिभाषित कर सकते हैं।

मैनुअल: http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/

यहाँ आप वसीयत के और कैनकैन के स्रोतों और Wikies पा सकते हैं:

भूमिका:

https://github.com/plataformatec/devise

https://github.com/ryanb/cancan

मेरे मॉडल इस तरह दिखता है।आरबी

class Role < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

User.rb

class User < ActiveRecord::Base 
    has_many :accounts 
    has_and_belongs_to_many :roles 

    # Include default devise modules. Others available are: 
    # :token_authenticatable, :confirmable, :lockable and :timeoutable 
    devise :database_authenticatable, 
     :recoverable, :rememberable, :trackable, :validatable 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :email, :username, :password, :password_confirmation, :remember_me, :role_ids 

    def role?(role) 
    return !!self.roles.find_by_name(role.to_s.camelize) 
    end 

end 

Ability.rb

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    user ||= User.new # guest user 

    if user.role? :administrator 
     can :manage, :all 
    elsif user.role? :operator 
     can :read, Account 
     can :read, Server 
    elsif user.role? :customer 
     can :manage, Account 
     can :read, Server 
    end 
    end 
end 

नियंत्रक में आप केवल इस दो पंक्तियों जोड़ना होगा:

class YourController < ApplicationController 
    before_filter :authenticate_user! 
    load_and_authorize_resource 

    ... 

end 
+0

यह मेरा सुझाव होगा। मुझे इस दृष्टिकोण के बारे में क्या पसंद है कि यह आपके शेष एप्लिकेशन तर्क से व्यवसाय नीति को अलग करने के लिए प्रोत्साहित करता है। –

+0

हां यह अलगाव अच्छा और लचीला क्षमताओं देता है। मैं इसे एक प्रोजेक्ट में इस्तेमाल कर रहा हूं, जहां डेवलपर्स ने बहुत ही असहज प्रमाणीकरण प्रणाली बनाई, जहां नई भूमिकाएं और क्षमताओं को जोड़ने के लिए मुझे प्रत्येक नियंत्रक और मॉडल में बहुत सारे कोड लिखना पड़ा। मैं पुराने सिस्टम को हटाने और डेविस और कैनकन को स्थापित करने और कॉन्फ़िगर करने के लिए लगभग दो घंटे के लिए काफी समय बिताया हूं। अब मैं खुश हूँ। और जब मेरे पास खाली समय होगा तो मैं भूमिकाओं और क्षमताओं का प्रबंधन करने के लिए उपयोगकर्ता इंटरफ़ेस लिखने की योजना बना रहा हूं। इन प्रणालियों के साथ यह काम बस बन गया है। –

+0

हमने इसे कई अनुप्रयोगों में उपयोग किया है और हम 'सर्वश्रेष्ठ-नस्लों' दृष्टिकोण होने के लिए तैयार-कैनकन मिश्रण भी पाते हैं। प्रमाणीकरण/प्राधिकरण के लिए इस वर्ष मानक के रूप में इसे कई संगठनों द्वारा तेजी से अपनाया जा रहा है। –

2

मुझे लगता है कि आपको अलग-अलग मॉडल बनाने की ज़रूरत नहीं है क्योंकि आपके पास प्रत्येक के लिए विशिष्ट फ़ील्ड नहीं हैं। तो आपको बस प्रत्येक उपयोगकर्ता की "भूमिका" निर्धारित करनी होगी। दो विकल्प: तालिका तालिका में भूमिका तालिका बनाएं या भूमिका फ़ील्ड जोड़ें। दोनों समाधान काम करते हैं, दूसरा अधिक लचीला है लेकिन कम अनुकूलित है।

लेकिन, आपके विशेष मामले में, आपके पास जटिल भूमिका प्रबंधन नहीं है ताकि आप एक सरल समाधान पा सकें। यदि आपके सभी उपयोगकर्ता कलाकार हैं तो आपको इसे अपने कोड में निर्दिष्ट करने की आवश्यकता नहीं है, यह उपयोगकर्ता के अंतर्निहित विवरण में निहित है। तो आपको बस सहेजना है कि कोई उपयोगकर्ता व्यवस्थापक है या नहीं और मुझे लगता है कि बूलियन फ़ील्ड "is_admin" बनाने का सबसे अच्छा समाधान है।

उसके बाद आप इस तरह, अपने संरक्षित नियंत्रकों में कुछ before_filter बनाना पड़ेगा:

before_filter => :authorize, :only => :new, :edit, :create, :update, :destroy 

def authorize 
    redirect_to :root if not current_user.is_admin? 
end 

और आपको लगता है कि जैसे सरल अनुरोध कर सकते हैं:

@artists = User.all 
@moderators = User.where(:is_admin => true) 

आप एक अधिक के लिए देखो, तो पूर्ण प्रमाणीकरण प्रणाली आप इस छोटे मणि की जांच कर सकते हैं: https://github.com/ryanb/cancan

लेकिन मुझे लगता है कि इस पल के लिए यह मामला नहीं है। यदि आपके पास एक साधारण समस्या है तो एक साधारण समाधान की तलाश करें!

+1

एआर में बूलियन मान 'foo?' विधियों का उत्पादन करते हैं जो सशर्त के लिए बहुत अच्छे हैं, और रूबी के पास 'जब तक' के रूप में बेहतर नहीं है। उनको एक साथ जोड़ना: 'redirect_to: रूट जब तक current_user.is_admin?' – coreyward

+0

ActiveRecord सहायक के लिए अच्छी टिप्पणी, मुझे यह नहीं पता था! सरल समाधान के लिए –

+0

+1। रूबी के बारे में अच्छी बात यह है कि आप बूलियन फ़ील्ड का उपयोग कर सकते हैं और 'is_admin? 'इंटरफ़ेस रख सकते हैं जब आप एक अलग रोल मॉडल या किसी अन्य चीज़ में बदल जाते हैं। –

2

आप के लिए की जरूरत है कोड है जो विशिष्ट और भूमिका या व्यवस्थापक जैसे विशिष्ट है या मॉडरेटर एक अन्य समाधान आधार उपयोगकर्ता मॉडल बनाना होगा जो अन्य सभी वर्गों से प्राप्त होगा। फिर आप एक व्यवस्थापक वर्ग और एक मॉडरेटर क्लास बना सकते हैं जो उपयोगकर्ता मॉडल से प्राप्त होता है। इसका मतलब यह होगा कि आप अपने कोड में उपयोगकर्ताओं की भूमिका को लगातार जांचने से बच सकते हैं उदा। current_user.do_some_admin_thing if current_user.is_admin?। अपनी कक्षाओं इस

class User < ActiveRecord::Base 
    # base user methods in here 
end 

class Moderator < User 
    def do_moderator_thing 
    # perform a moderator task 
    end 
end 

class Admin < Moderator 
    def do_admin_thing 
    # perform an admin task 
    end 
end 

कुछ ऐसा दिखाई देगा इस उदाहरण में उपयोगकर्ता वर्ग है सबसे बुनियादी विशेषाधिकार, मध्यस्थों सब कुछ उपयोगकर्ताओं कर सकते हैं प्लस मॉडरेटर विशिष्ट विधियों और व्यवस्थापक सब कुछ उपयोगकर्ता और मॉडरेटर कर सकते हैं प्लस व्यवस्थापक विशिष्ट कर सकते हैं कर सकते हैं तरीकों।

सभी अलग-अलग उपयोगकर्ता भूमिकाएं डेटाबेस में एक ही तालिका का उपयोग करती हैं लेकिन आपकी चिंताओं को कक्षाओं में अच्छी तरह से अलग किया जाता है जो आपके कोड के माध्यम से अत्यधिक सशर्तों से बचाता है जो उपयोगकर्ता को हर समय क्या भूमिका निभाता है।

नए उपयोगकर्ताओं को बनाना सीधा भी Admin.new :name => 'bob' एडमिन क्लास होगा, फिर यह ध्यान रखता है कि उपयोगकर्ता को एक व्यवस्थापक के रूप में कैसे परिभाषित किया जाता है जो एक अच्छा इंटरफेस प्रदान करता है जहां आपको भूमिका प्रणाली के आंतरिक कार्यों को जानने की आवश्यकता नहीं होती है उपयोगकर्ताओं।

+0

कृपया इस प्रश्न के बारे में स्पष्ट होने के लिए अपना प्रश्न संपादित करें कि यह एकल तालिका विरासत का उपयोग कर रहा है और उस पर आधिकारिक रेल दस्तावेज से लिंक है। –

+0

प्रश्न अलग-अलग उपयोगकर्ताओं के लिए अलग-अलग व्यवहार के बारे में बात नहीं करता है, अलग-अलग चीजों को करने के लिए अलग-अलग प्राधिकरण। जब तक उपयोगकर्ता मॉडल का उदाहरण वास्तव में अलग व्यवहार नहीं करता है, तो यह विभिन्न उप-वर्ग बनाने के लिए अत्यधिक जटिल है। विरासत का अत्यधिक उपयोग एक विरोधी पैटर्न है। – Winfield

1

हालांकि मैं विश्वास करता हूं कि डेविस और कैनकन के संयोजन शक्तिशाली और काम करते हैं। आइए हम एसोसिएशन और प्रतिनिधिमंडल को ध्यान में रखते हुए एक अलग परिप्रेक्ष्य के साथ देखें।

एसोसिएशन: ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में, संघ वस्तुओं एक वस्तु उदाहरण एक और अपनी ओर से कोई कार्रवाई करने के कारण होने की अनुमति देता है कि के वर्गों के बीच एक संबंध को परिभाषित करता है।

प्रतिनिधिमंडल: प्रतिनिधिमंडल एक वस्तु का व्यवहार किया जा किसी अन्य वस्तु के व्यवहार के संदर्भ में परिभाषित करने के लिए अनुमति देता है। 'प्रतिनिधिमंडल' शब्द जिम्मेदारी के प्रतिनिधिमंडल को संदर्भित करता है। प्राथमिक प्रतिनिधिमंडल का जोर संदेश पास करने पर है जहां कोई ऑब्जेक्ट संदेश की प्रतिनिधि जिम्मेदारी ऑब्जेक्ट्स को संभाल नहीं सकता है जो संभावित रूप से (इसके प्रतिनिधि) हो सकता है।

इसके साथ, यदि हम अपने उपयोगकर्ता और भूमिकाओं को इस तरह डिजाइन करते हैं तो क्या होगा। कोई रोल क्लास नहीं है और उपयोगकर्ता इसके बजाय किसी विशेष वर्ग (कलाकार, व्यवस्थापक) का उत्तराधिकारी या विशेषज्ञ नहीं है, सभी (रोल) कक्षा में उपयोगकर्ता ऑब्जेक्ट और प्रतिनिधि शामिल हैं। जिस तरह से मैं सोच रहा हूँ और जिस तरह से रेल के साथ लागू करने के लिए कुछ इस तरह है:

class User < AR::Base 
    def user_method 
    end 
end 

class Artist < AR::Base 
    has_one :user 

    def artist_method 
    # perform an admin task 
    end 
end 

class Admin < AR::Base 
    has_one :user 

    def admin_method 
    # perform an admin task 
    end 
end 

यह role class model मॉडलिंग भूमिकाओं पर अपने लेख में फ्रांसिस जी Mosse द्वारा वर्णित है।

1

declarative authorization मणि के लिए यह मूल सेटअप है, मैं उपयोग करता हूं। लेकिन आप इसे मणि के बिना ही इस्तेमाल कर सकते हैं, अगर आपकी प्राधिकरण आवश्यकताएं उपयोगकर्ता की भूमिकाओं के प्रकार से पूछने से अधिक नहीं हैं।

इसे roles तालिका की आवश्यकता होती है, और ऐसा, ताकि वास्तव में आपकी कल्पना न हो।

class Role < ActiveRecord::Base 
    belongs_to :user 
end 

class User < ActiveRecord::Base 
    has_many :roles 

    def role_symbols 
    roles.map { |r| r.title.to_sym } 
    end 

    def admin? 
    has_role?(:admin) 
    end 
    # include more role booleans or write some ruby magic to be DRY 
    # ... 

    def has_role?(r) 
    role_symbols.include?(r.to_sym) 
    end 
end 

# give or take 
user = User.new 
user.roles << Role.new :title => "admin" 
user.roles << Role.new :title => "artist" 

user.role_symbols # => [:admin, :artist] 
user.admin? # => true 
user.has_role?(:artist) # => true 
0

आपके पास दो मॉडल उपयोगकर्ता और भूमिका हो सकती हैं। और भूमिका उपयोगकर्ता से संबंधित है।

रोल मॉडल में उपयोगकर्ताओं (जैसे व्यवस्थापक, मॉडरेटर) की भूमिका निर्दिष्ट करें।

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