I have the following association between entities in the system:
Store
Vendor
and User
store can have many vendors,
vendor can belong to multiple stores.
A user can have multiple stores, but if its a user who is related to vendor, say a person who works for that vendor, then the behavior of that user changes.
Also, for a store there can be multiple roles.
I tried polymorphic association, but since the behavior of the user changes depending on roles and whether he is a store user or a vendor user, I cannot use that.
STI can also not be used since a vast amount of columns will differ. Any ideas will be helpful.
If I'm understanding your requirements accurately you want to model:
A vendor can have many stores
A store can have many vendors
A vendor can have many users
A store can have many users
That would require a has_and_belongs_to_many relationship between vendor and store. It would also require a polymorphic association between user and vendor/store. You should be able to use a polymorphic association. That way you could manage system behaviour for each user by checking their roles and associations. If you created a polymorphic association named userable for example, you could user user.userable to get either the vendor or the store and vendor.users or store.users to access users for those instances.
For your user model, regarding this line in your question:
"but if its a user who is related to vendor, say a person who works for that vendor, then the behavior of that user changes"
I would add a column to my user table called user_type and create some user types that you can use to filter out and assign privileges to. The user_type column could be a string field and explicitly named something like related and not_related, simply an integer 1 or 2, or more, or even a boolean field if there aren't going to be too many user_types.
Related
I am currently trying to create a system which allows for specific users to create a Course record which can be enrolled in by many other users. I've tried a few association techniques such as has_and_belong_to_many, has_many :through and number of other setups but have been unable to get it right.
Basically all that I need is the following:
Course belongs to (is created by) a single User (foreign_id => admin_id).
Course has many enrolled Users (Join Table?).
User has many created Courses.
User can belong to many Courses.
If you have any idea how this would be accomplished I would greatly appreciate your input.
A pretty good design is Canvas LMS.
In short:
A User is just a user.
A Course is just a course.
An Enrollment is an association between a user and a course. An enrollment has a type, which is either a student, a teacher, a TA or an observer. Each type has its own set of permissions.
So, if a user is not in any course, he/she is nothing but a user. A user can at the same time be a teacher in course A and a student in course B. Also, he/she can be both a student and a TA in the same course.
You can add your own enrollment types in your application, such as creator.
I want to setup a work order system in a tree structure like so
so the workorder belongs to a tenant, but also belongs to the property he/she lives in, and belongs to the landlord.
I know I can't have belongs_to :through. I want to be able to see all of the work order submitted by each tenant, and see all work order per property, and per landlord.
so if a landlord click on an work order, it will say which house it is for, and which tenant submitted this order.
So what is the best way to model this? polymorphic? or just straight up, belongs to?
Work orders belong to tenants, properties, and landlords. A work order must have all of those set when it is created. Landlords have many properties. Properties have many tenants, tenants have many work orders.
To see all work orders submitted by a tenant just do tenant.workorders. To see all he work orders per property per landlord you need to get all of the landlord's properties and then get all of the work orders for each of those properties.
I am designing a multi-tenant app. A business rule requires a user to belong to many accounts (and accounts to have many users). To facilitate the join, there will be a has_many :through relationship between Accounts and Users with the accounts_users model holding additional information such as last_logged_in, is_active, is_guest, etc. The user will be authenticated against the usual email/pw located in the users table. For every record (i.e. a post, task, etc.) created in the db, the creator's user_id and account_id will be attached to it.
So, my question is: which user_id should the current_user be associated with - the one from the user's table (user_id) or the one from the accounts_users' table (accounts_users_id)?
Thoughts: it seems using the accounts_users_id would add an extra layer of security since it would be unique to the user for the particular account they are logged into.
Any additional thoughts/insight/experience would be appreciated!
I have an application where there are users, which are managed by Devise. The application's actual users will add people as "friends" and one other type, lets call them "workers". The "friends" and "workers" are, or I would like them to be, all of type User, at the end of the day.
The catch is that there is a need for a User to be able to have a single person (User) in the system that is both a "friend" and a "worker" for them. There is also a need for non-duplication of Users by their unique id's, which in this case would be mobile phone number. If a given user adds another user as a "friend", and then subsequently adds them as a "worker", for example, it should simply be an association of some sort, and not a new User in the system.
I know how I would handle this in a traditional sense, but I'm sure there is some clever way with either STI or polymorphic associations to handle this in rails.
Any thoughts? It's worth noting that the various user types all have virtually identical fields (or will) associated with them - pretty straightforward id, name, mobile, etc.
I guess the trick is that any of the Users need to be able to have either or both of the "friend" or "worker" types associated to them, and each of those types should be able to have combinations of the other two associated with them.
It sounds to me like the whether someone is a friend or a worker should be an attribute of the join model between the two people rather than an attribute of either person.
That way a person can be a friend of one person and another person's worker.
I have been trying different techniques while designing this application, which to me is very complicated as there are many solutions to chose from. Deciding which of these solutions is the best has become my full time job for the last few weeks.
Background:
I have a User model which contains some very basic authentication functionality. The application will have three different types of users; admins, buyers, and sellers. The user type will be determined during sign up, where a check box will ask if the user is a seller. If the box is checked, the user is a seller, and if the box is unchecked, it's assumed their just a buyer. I would rather not have a drop down menu to select the user type (Buyer, Seller). Easy so far.
Details:
Sellers have a profile, and users who visit the site will be able to browse through the different sellers and view their profile. Buyers do not have a profile, and should not be listed on the site for users to see. If that's not complicated enough, buyers should have the option to change their account type and become a seller. Similarly, sellers can change their account type and "deactivate" their seller account, removing them from the list of sellers.
Design options:
Single table inheritance:
What I came up with when attempting to implement this using STI was suboptimal. I was faced with two options: a messy controller, which made the decision of what type of user to create based on the check box mentioned above (one controller - UsersController), or two different sign up forms that were identical (two controllers - BuyersController, SellersController).
has_one or "has_none" Profile association:
class User < ActiveRecord::Base
has_one :profile # only if the user_type or role is "seller"
end
class Profile < ActiveRecord::Base
belongs_to :user
end
Here I would use something like CanCan or declarative_authorization, and let the user chose his/her role via the check box mentioned above. This introduces a security risk, as there will be an admin role and I don't want this to be open for mass assignment.
I guess either way you look at it I'll have a messy controller with conditionals on how to create the user. Unless I choose to have two check boxes ("I am a seller," and "I am a buyer"), but this seems redundant. It also seems as though whichever design I choose, I'll be faced with some hackish solutions.
Maybe introduce some model that lies between the User and user type?
Any opinions?
I don't really think you need either STI or Polymorphism. A single user model should suffice. I would add three methods to your user model (administrator?, buyer?, seller?) and also add scopes that will return only buyers, only sellers, or only admins.
In your case, it sounds like you have a real minimal number of roles for users (2 now, expanding to 3 with admins). I would probably use the technique Ryan discusses in the "Embedded Associations" Railscast.
I've done something very similar in my latest project, and then used CanCan (in my case, the 2.0 alpha branch, as I find it simpler) on top of that. Your ability class would look something like this (in 2.0 syntax, but you can do the same with 1.x, I'm sure)
class Ability
include CanCan::Ability
def initialize(user)
if user.seller?
can :create, :profile
else
...
end
end
end
So far it sounds like you have a flag that indicates their user type, or a column with type string, etc.
You haven't indicated any behavior that depends on this--not showing up in listings etc. can be handled with scopes. Admin can be handled with a flag.
I don't see the problem yet, at least not a problem of a few weeks scope.
A 3rd option.
...buyers should have the option to change their account type and become
a seller. Similarly, sellers can change their account type and
"deactivate" their seller account, removing them from the list of
sellers.
Have you considered not allowing switching of accounts? If a buyer wants to become a seller, then they create a new "seller" account. It would work the same for seller to buyer. It would mean having 2 controllers for the signup, etc. but it would keep the separation you're looking for. If the two must be mutually exclusive you could do a rudimentary email check to verify the user doesn't already have an account and if they do, they must de-activate the existing account prior to creating a new one.