J'ai rails application qui a trois différents types d'utilisateurs et je les ai tous besoin de partager les mêmes informations de profil commun. Cependant, chaque utilisateur différent a aussi des attributs uniques eux-mêmes. Je ne sais pas comment séparer les différents domaines.
J'utilise concevoir strong> pour l'authentification et cancan strong> pour l'autorisation. Par conséquent, j'ai un modèle utilisateur avec un ensemble de rôles qui peuvent être appliquées à l'utilisateur. Cette classe ressemble à ceci: p> Je ne veux pas polluer le modèle de l'utilisateur avec cette info donc je le jeter dans un modèle de profil. Cette partie est assez simple. Ce tour du modèle de l'utilisateur dans quelque chose comme ceci: p> si un utilisateur est un propriétaire ils ont des champs uniques ... p> Si un utilisateur est membre ils ont quelques champs supplémentaires comme par exemple: p> ... p> et un modèle de magasin contiendra un has_many sur les membres que nous travaillons les membres du magasin. P> La question est autour des champs supplémentaires. Est-ce que je les configurer comme différentes classes? Mettez-les dans un autre
J'ai actuellement essayé quelques différentes façons de configurer cela: p> La première consiste à mettre en place le modèle de l'utilisateur en tant que root global p> class Admin
has_one :user
# admin fields go here.
end
class Owner
has_one :user
# owner fields go here.
end
class Member
has_one :user
# member fields go here.
end
class User < ActiveRecord::Base
# ... other code removed for brevity
has_one :profile
end
class Admin < User
# admin fields
end
class Owner < User
# owner fields
end
class Member < User
# member fields
end
class User < ActiveRecord::Base
# ...
# Roles association
has_many :assignments
has_many :roles, :through => :assignments
# Profile and other object types
has_one :profile
has_one :admin
has_one :owner
has_one :member
# ...
end
3 Réponses :
Je ne vais probablement pas vous donner une suggestion approuvée par des rails, mais .. p>
Séparer votre profil est un bon appel. Pensez à utiliser le modèle de décorateur pour un rôle. Vous pouvez avoir un adminuserdecorator, OwnerReCorDecorator ou MemberNerdecorator. Vous pouvez également ajouter de manière dynamique les champs supplémentaires directement sur l'instance (il est rubis après tout), mais je pense que cela deviendrait laid et compliqué. (Si vous voulez vraiment faire de mauvaises choses, utilisez un objet visiteur pour vous donner une instance de votre décorateur d'une méthode sur la classe d'utilisateurs.) P>
Aussi, pourquoi mettre la bande strie ou la configuration de paiement sur le propriétaire au lieu de faire partie des informations de magasin? Sauf peut-être qu'un propriétaire puisse avoir plusieurs magasins et utiliser les mêmes informations de paiement pour chaque magasin? p>
Oui, la configuration du paiement est sur le propriétaire car le propriétaire peut avoir de nombreux magasins.
Ma réponse suppose qu'un utilisateur donné ne peut être qu'un type d'utilisateur - par exemple. Seulement un administrateur ou un seul membre. Si tel est le cas, cela semble être un travail parfait pour Association polymorphe de Actionecord .
add_column :privilege_type, "ENUM('Admin','Owner','Member')", :null => false add_column :privilege_id, :integer, :null => false add_index :user, [:privilege_type, :privilege_id], :unique => true add_index :user, :privilege_type
C'est la réponse que je marque comme "cela a fonctionné" car quand je l'ai testé, cela fonctionnait assez bien. Merci pour la réponse très bien pensée et détaillée Jeffrey. :) Toutefois, après une consultation avec Michael Hartl (railstorial.org) à propos de certains produits MVP (produit viable minimum), j'ai décidé de lancer toutes les données de profil dans le modèle utilisateur afin de simplifier les interactions avec le modèle. Si le MVP prouve un succès et est rentable, je peux résoudre ce problème plus tard.
Vous avez déjà accepté une réponse, mais pour ce que vous valez, j'ai une situation similaire et j'ai choisi d'accéder à votre "modèle d'utilisateur en tant que racine d'agrégation". Mon modèle d'utilisateur contient toutes les informations "profil" et l'utilisateur, d'utiliser un exemple fictif, has_one: acheteur et has_one: vendeur. J'utilise un simple champ Tinyint comme BitFlags pour lequel les rôles que l'utilisateur tient, car les utilisateurs pouvaient être des acheteurs et des vendeurs (ou des autres rôles de TBD dont j'ai besoin à l'avenir). Si un bit est défini, vous pouvez assumer que l'association correspondante n'est pas nulle (qui n'a pas été un problème pour moi depuis que je vérifie toujours les BitFlags avant d'utiliser la référence de l'association). Je n'ai pas vraiment trop de champs uniques dans mes modèles de subordonnés réels, mais il est très utile de garder les choses déchecchées lorsque chaque modèle subordonné a des associations supplémentaires, comme si le vendeur a_one: Merchant_account "et un acheteur has_one: achat_history, etc. i Haven Il est encore allé en direct, mais quand je le ferai, je suivrai cet article avec des problèmes que je rencontre. P>