2010-10-28 14 views
2

Je suis assez nouveau dans la configuration de la base de données dans Ruby et j'ai besoin d'aide pour la configurer correctement avec les modèles. Quelqu'un peut-il aider?Configuration de la base de données et du modèle dans Ruby On Rails

Fondamentalement, j'ai une organisation, qui aura au moins 2 types d'utilisateurs - membre et administrateur. Les organisations et les utilisateurs ont tous deux une adresse. Je pensais que c'était fondamentalement trois tables - Organisation, utilisateur et adresse, mais alors vraiment confus en essayant de penser à des modèles et des clés étrangères.

Quelqu'un peut-il suggérer le meilleur moyen de l'organiser? Je cours Rails 3 avec une base de données mySql

Merci pour votre temps

Sniffer

Répondre

5

J'aime beaucoup la réponse d'Adam Tanner, mais je la définirais un peu différemment. Tout d'abord, la façon dont une organisation s'associe aux administrateurs ne fonctionne pas comme décrit: vous devez avoir une clé étrangère différente dans votre table utilisateur, et spécifier cela dans l'association has_one :admin. Mais je ne pense pas que ce soit un bon chemin de toute façon, car il vous limite à un administrateur par organisation, et limite un utilisateur appartenant à une organisation.

Ma version est un peu plus compliquée, mais je pense que ça se passe bien. Premièrement, admin doit être un rôle qu'un utilisateur a ou n'a pas avec une organisation. Je traiterai d'abord le problème utilisateur/org, et enregistrerai le problème d'adresse pour plus tard.

Voici les migrations, que vous pouvez améliorer avec ce que d'autres domaines dont ils ont besoin:

create_table :organizations do |t| 
    # your fields go here 
end 

create_table :users do |t| 
    # your fields go here 
end 

create_table :memberships do |t| 
    t.integer :user_id 
    t.integer :organization_id 
    t.boolean :is_admin 
end 

add_index :memberships, [:user_id, :organization_id] 

Comme vous pouvez le voir, nous ajoutons une table d'adhésions, qui va connecter les utilisateurs et les organisations. Nous ajoutons également un index pour accélérer un peu l'association. Maintenant pour les modèles:

class Organization < ActiveRecord::Base 
    has_many :memberships 
    has_many :users, :through => :memberships 
end 

class User < ActiveRecord::Base 
    has_many :memberships 
    has_many :organizations, :through => :memberships 

    def membership_in organization 
    self.memberships.detect{|m| m.organization = organization} 
    end 

    def is_admin_for? organization 
    self.membership_in(organization).is_admin? 
    end 

    def set_admin_for organization, value 
    self.membership_in(organization).update_attribute(:is_admin, value) 
    end 
end 

class Membership < ActiveRecord::Base 
    belongs_to :organization 
    belongs_to :user 
end 

Ici, nous connectons nos utilisateurs et organisations par le biais des adhésions. Un utilisateur peut être un administrateur pour l'une des organisations auxquelles il appartient. J'ai créé quelques méthodes pour définir et obtenir le statut d'administrateur d'un utilisateur dans une organisation, dans le modèle d'utilisateur.

Suivant les adresses: Je l'ai déjà abordé celui-ci dans un billet de blog de la mine:

http://kconrails.com/2010/10/19/common-addresses-using-polymorphism-and-nested-attributes-in-rails/

Si vous avez des questions, s'il vous plaît demander. Bonne chance!

MISE À JOUR

Edward M. Smith a souligné dans les commentaires que mes méthodes d'administration ne sont pas très tolérant aux pannes.J'essayais de garder le code aussi propre que possible pour l'exemple, mais il a un point. Voici donc la version plus musclée que les comptes pour avoir tenté d'utiliser une appartenance à une organisation que l'utilisateur ne partie de:

def is_admin_for? organization 
    membership = self.membership_in(organization) 
    return false if membership.nil? 

    membership.is_admin? 
    end 

    def set_admin_for organization, value 
    membership = self.membership_in(organization) 
    return false if membership.nil? 

    membership.update_attribute(:is_admin, value) 
    end 

Comme toujours, le développement piloté par les tests est le meilleur, mais je n'ont généralement pas le temps de le faire pour les questions stackoverflow :)

+0

Question d'un rail/ruby ​​noob. 'membership_in' retourne nil ou l'instance d'organisation, n'est-ce pas? Que se passe-t-il sur un is_admin_for? appeler où l'utilisateur n'est pas dans l'organisation? N'est-ce pas appeler is_admin? sur zéro, et donc une erreur? –

+0

Très vrai, c'est beaucoup de code que j'ai tapé pour une réponse stackoverflow, donc je n'ai pas construit beaucoup de tolérance de panne, ou utiliser TDD comme je le ferais pour le code de travail :) Bonne prise, et je corrigerai il. –

+0

Oh, je ne critiquais pas. Je suis encore en train de travailler sur la compréhension de Ruby (j'ai dû chercher la méthode 'detect' sur les collections, par exemple) donc je voulais savoir si j'avais bien compris les choses. :) –

2
class Organization < ActiveRecord::Base 
    has_one :address, :as => :addressable 
    has_many :members, :class_name => "User" 
end 

class User < ActiveRecord::Base 
    has_one :address, :as => :addressable 
    belongs_to :organization 
end 

class Address < ActiveRecord::Base 
    belongs_to :addressable, :polymorphic => true 
end 

J'ai enlevé l'association d'administration, en partie parce qu'il ne fonctionnait pas de toute façon, la plupart du temps parce que Jaime a dit qu'il est la mauvaise façon de s'y prendre (la plupart des développeurs utilisent une sorte de système de rôles). Voir le post de Jaime pour un bon moyen de créer un système de rôle extensible.

Espérons que ça vous aide!

+0

Merci pour la réponse Adam. Après avoir regardé quelques références l'attribut: polymorphic a du sens. Je suis juste un peu confus comment j'ai mis en place ma base de données (désolé, je suis un débutant!). Ai-je raison de penser que l'organisation aura les champs suivants: id, orgname et User auront les champs id, username, organisation_id. Mais je suis confus sur la table d'adresse si cela a des champs clés étrangers pour organisation_id et user_id? Cela signifie-t-il que j'ai ajouté un champ de clé étrangère pour chaque objet qui réutilise une adresse? – Sniffer

+0

Ou auriez-vous deux nouvelles tables dans vos bases de données appelées UserAddress (avec address_Id et user_Id) et OrgAddresses (avec id_adresse et org_id). Si oui, comment les fixez-vous dans le modèle? – Sniffer

+0

Vous avez raison pour les tables Organisation et Utilisateur. La façon dont le polymorphisme fonctionne dans Rails est la table Address qui aura une colonne addressable_id et une colonne addressable_type. La colonne addressable_id contient l'ID de l'utilisateur/organisation/quelquechose, et le type addressable est une chaîne qui contient le nom de la classe du type d'objet tel que "User"/"Organization"/"Whatever" afin qu'il sache quelle classe instancier quand il le sort de la base de données. Vous pouvez créer ces colonnes automatiquement dans votre migration avec 't.references: adressable,: polymorphic => true'. –