Parent/Child classes in Devise - ruby-on-rails

I'm newish to Rails and working on a project that I would like to create a parent/child relationship using devise. I've looked through a good bit of the literature on Devise, but didn't see any clear cut way to do what I'm trying to accomplish (though it's certainly possible I overlooked the answer because I was using different terminology).
Here's what I'd like to do:
Companies sign up using the normal devise registration flow with a little extra information - i.e. Company name, address, etc. They then add 'users' once inside the application. Users shouldn't have an external sign-up flow. I would like to each user to inherit the company information from Company.
Here is what I thought I'd try:
Generate both the Company and the User devise models.
Generate the User controller, modify the new action to #current_company.user.build
Would this accomplish what I'm trying to do?
Any further reading that you might be able to pass along would be appreciated!

Do this....
#app/models/company.rb
class Company < ActiveRecord::Base
has_many :users
end
#app/models/user.rb
class User < ActiveRecord::Base
devise ....
belongs_to :company
end
This is a has_and_belongs_to_many association.
What you should be doing is leaving companies to be its own model; don't include Devise on it at all.
Instead, you should make your User model the only one with the authentication. After that, each user will have to be related to a particular company (or if you wanted to use has_many :through, you could have a user a member of many companies).
You'd have to scope the Devise authentication around a company (IE company.users.exists? user); I've been working on that but don't have a thorough implementation yet.
There's a good ref here: Scope login to subdomain
This will allow you to have users for a particular company; which you'll be either be able to scope using subdomains (to make a crude "multi tenant" app), or to have a select box at sign-in or something.
Obviously, your lack of input means I've got to write a broad answer.
If I were you, I'd think about your desired flow.
Research multi tenancy with Rails (the apartment gem is good if you're using PGSQL) - this should give you a better idea on the way the application should work (IE how does a company need to support users).

Related

Devise Model inherit from another devise model

I'm creating an online real estate platform which facilitates (normal) Users and Real Estate agencies. This platform has following user types:
Normal Users: can search houses for rent/purchase, reviews agencies
etc.
Agencies: can upload posts for house rent/sell etc
Employee: works for a Agencies
Super Admin: manages the site
Team Member: manages portions of the site delegated by Super Admin
Each user type then has different fields (4 - 6 additional fields each). Normal Users and Agencies can self-register. Employees and Admins can be registered by Agencies and Super Admins respectively. Furthermore there are some different multiple roles for a user type (which is not relevant to discuss for this case).
Currently, I have three different devise models (User, Agencies & Super Admin). They have different login and registration forms but share same session [Reference: [https://github.com/plataformatec/devise/wiki/How-to-Setup-Multiple-Devise-User-Models]][1] User has facility to register via social media (OmniAuth) but Agency must has to register via private Email Id. And Admins will only be registered by Super Admins.
Here comes requirement [PROBLEM]:
The following fields are what I've identified as being shared between the three user types above: Email address & Username They must be unique for all cases. For example, if an agency has a username then user can't register with same username. At the moment, we are not meeting above requirement as we have different tables/models for different type of user.
MY PLAN
Now, since these are all really different users who interact with different sections of the application, so it feels clean to have three different devise models. Therefore, what I think is to create a parent devise model which should be inherited by all type of user models. This way can help me to solve my problem. But now, I'm not confident that how can I inherit parent devise model and use it for my case.
Second option is to use STI (Single Table Inheritance). But my major concern with this approach is that it will create mess with registration and security things.
Now here is my problem with my researched options. What would you recommend me to chose. Moreover, it'd be great if you put an example for elaboration.
P.s. I am inclined to the first one option as I have already done with three different models and their login/registration stuff. :)
Not sure how your going to accomplish this without a roles system.. I suppose you could namespace or scope it out but wouldnt be the most secure to keep access to a specific user group.. atleast in my oppinion.
You could Use Single Table Inheritance (STI)..
Essentially you could do something like this (if i understand you correctly)
class User < ApplicationRecord
# MASTER
end
class AnotherUser < User
# Inherits attributes from User Table
end
going this route you will need to add type:string to your User model.
here are a few reference links:
http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html
http://eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-rails/
they helped me when i ventured down the STI path..
For example, In a project I did this like so:
class User < ApplicationRecord
# Devise Modules Here
end
class Admin < User
end
class SuperAdmin < User
end
now the tricky part I found was creating these users.. i opted to create a controller and a link, so in my app a User is created only by an admin or superadmin, and an admin can only be created by a superadmin

want to give access for many organsation

We are developing a online rails application for schools, but we want to separate that all schools to each other.
Like slack website that manage many organisation from one application and organisation only access that data.
Also like trello, they also separate organisations in one application.
So what is the best approach is use for such type of application?
How we implement this in our ruby on rails application,that we separate all schools in our Database?
Okay.
Multi Tenancy
If you're coming from the world of "native" software, you'll be best reading up on multi tenancy:
(source: theenterprisearchitect.eu)
Rails apps are multi tenant by virtue of them running through a network; they run a single instance of an app, which is then accessible to anyone on that network (remember, the Internet is a huge network).
Rails provides all the functionality you mentioned above, with the added benefit of having a lot of world-leading companies using it to run (Twitter, AirBnb, Groupon etc have all famously used Rails).
You need to read up on database system design for your application, specifically...
MVC
To better understand how you'd make an application like you referenced, you need to understand the MVC (Model View Controller) programming pattern, and it's value within the world of object-orientated system design, especially pertaining to Rails:
Rails, like many other frameworks, uses MVC to build objects. These objects are defined by the programmer, but basically allow you to create the relevant data required to provide functionality to an application like you mentioned.
Specifically, each time you access a Rails app - you'll be essentially manipulating objects filled with data from the db. I'll explain any specifics in an update if you need it.
In regards your question, the way to integrate multiple organizations/entities into a single application is to set up the database schema to manage the organization as the "parent", with users and data as extra elements:
#app/models/company.rb
class Company < ActiveRecord::Base
has_many :users
has_many :invoices
has_many :clients, through: :invoices
end
#app/models/user.rb
class User < ActiveRecord::Base
belongs_to :company
has_many :invoices
end
#app/models/invoice.rb
class Invoice < ActiveRecord::Base
belongs_to :company
belongs_to :user
has_many :clients
end
This will give you the ability to use something like the following:
#config/routes.rb
constraints Account do
root "invoices#index" #-> http://company.url.com
resources :invoices #-> http://company.url.com/invoices/3
end
#lib/account.rb
class Account
def matches?(request)
Company.exists?(request.subdomain)
end
end
You'd then be able to use Devise to sign the user into the organization, allowing them to add / edit invoices as they need.
Each time you edit or update an invoice, a user will be assigned to it, allowing you to determine who created it etc.
Without going deeper into the code, that's what I think you need to know.
As concern of database design, you can design something like:
You should manage a organization model where each organization must be a sub-domain and your other model like User etc.. should be associate with organization model.You can extract the subdomain name from request url (like request.host, request.subdomain etc..) and find the records as per this subdomain request.
As concern of resource permission you can use cancan gem where you can manage resource accessibility through a single file.
https://github.com/CanCanCommunity/cancancan
Hope it is helpful for your initial design.

Multiple devise models vs permission based

The application I'm building is to allow users to download vouchers. Employers sign up for an account, add employees (who get a login), select which vouchers to enable, and then employees can see the enabled vouchers and download.
I initially created two devise models: employee and employer. This was so active record associations would be simple (employer has_many employees, employee has_many vouchers). But this would also mean separate database tables and therefore separate sign in forms.
I looked into single sign in forms for multiple users and this seemed to have the consensus that you should instead have a single User model and use CanCan and Rolify for permissions. But the problem with that is you cannot (I believe?) do active record associations between these two roles (not separate models).
I next looked at subclassing so I could do associations, but it has issues as people say Rails isn't really meant to subclass, and it seems a bit hacky.
So I'm left feeling like I have to choose the lesser of evils, whereas I really just want to find the right way.. Thanks in advance for any help.
So a friend of mine solved this very elegantly for me, for everyones reference:
Good question. It’s a great problem that deals with the intersection between good engineering (model implementation, database design) and user experience (single sign in form).
Assuming that Employees and Employers differ enough, it makes sense to implement them as separate models. But it also makes sense to have a single sign in form—employees and employers shouldn’t have to care that they’re signing into the right form.
Single table inheritence usually appears to be the ideal solution, but tends to best be avoided in Ruby on Rails applications unless absolutely necessary.
I’ve actually thought about this problem before, so I would suggest an implementation along these lines:
An Employer model.
An Employee model.
A SignIn/Login/Credentials/WhateverYouWantToCallIt model.
In terms of employer/employee associations, as before:
Employee belongs_to :employer
Employer has_many :employees
Now, considering that both models are able to sign in, it makes sense to separate these credentials into their own SignIn model. If you do some reading up on polymorphic associations (http://guides.rubyonrails.org/association_basics.html#polymorphic-associations), you’ll find that they are awesome for creating relationships where the association can be with different models.
So now you need to create associations between sign in credentials and employers and employees:
SignIn :belongs_to :signinable, polymorphic: true
Employer has_one :sign_in, as: :signinable
Employee has_one :sign_in, as: :signinable
The elegance of this solution (in my opinion), is that you’re able to separate your SignIn, Employer and Employee models, which not only conforms to good Ruby on Rails conventions, but is good database normalisation practice. At the same time, you have a SignIn model that makes it trivial to implement a better sign in form experience that allows both employers and employees to sign in.

Rails 3.2 Are there any advantages to using a separate model for user accounts and profiles?

I would just like to know if there is any advantage to having a different model to the users and the users profile.
This way I would make storing of user details such as first and last name, address and D.O.B separate from the authentication.
Currently I want to use devise for authentication, but am hoping that if I would need or want to change this in the future, doing this would make it easier.
Also I'm thinking there could be some slight performance advantages in not using one model with a larger number of rows?
If you want to prepare for multi-provider authentication (e.g. with omniauth) it's a good idea to separate authentication and identity in your schema. For instance
class User < ActiveRecord::Base
has_many :authorizations
end
class Authorization < ActiveRecord::Base
belongs_to :user
end
Then you'd have separate authentication records for each provider the user uses to sign-in, e.g. your local login, Twitter, Facebook, etc.
It may also be useful to have an Authority model that has_many :authorizations as a good place to keep data (e.g. icons, api keys) specific to each provider.

Multi - User Multi Environment

I'm looking to create an app, where each user can create their own... "Universe" in a way, with the amount of items and names that makes sense to them, etc.
I've never done this before, so far I've had the typical cases where you have users and admins, but they're both looking essentially at the same thing. Here each user will have a separate environment.
Obviously a user should not be able to see someone else's environment.
Can someone please point me to the right direction on this subject? Maybe some useful gems or resources I could use to get started?
Any advice is welcome!
I'd start with using a plugin for authentication, e.g. AuthLogic or Devise are two popular examples.
Both of these let you define a User class.
Then, when you are showing the user their stuff in their environment, you can make sure you only show them their own stuff by using has_many, and has_one, and has_and_belongs_to_many relationships in rails.
e.g. if it was facebook, you might have something like this
Class User < ActiveRecord::Base
has_many :news_items
has_many :friends
has_many :messages
end
In your code you could then refer to
#user.news_items
#user.friends
#user.messages
And the relationships would ensure you were only showing information belonging to that user.
(Caveat: in reality the relationships will be more complicated, and you will probably need more complicated logic, but this should get you started)

Resources