A Rails app where the User is also a "something else", not sure how to word this correctly - ruby-on-rails

I am working on a Rails app where the data model involves the following:
Companies, which have_many Restaurants
Restaurants, which have_many Reservations
Customers, which mave_many Reservations
My confusion comes from the fact that there are 3 distinct types of users:
An employee of the Company, who can see an admin dashboard showing data on all of the restaurants that company owns/manages
The restaurant itself (which will, in theory, have their dashboard open all day, and should be able to log into their own dashboard, but not be able to see any other restaurant's dashboard)
The customer, who has a UI to make a reservation at a certain restaurant
Should the Restaurant be a type of User?
Should each restaurant just get it's own standard user-login to access their specific restaurant? If this is the case, would a Restaurant have_one User, and I can use something like CanCanCan to restrict Users so that they can only access a Restaurant where the Restaurant's ID == User.restaurant.id?
This is my first app that addressed atypical User types, so I'm at a complete loss on this. Any guidance/best practices on how to address a situation like this would be much appreciated!
Additionally, I would like to use Devise for the User model(s). Thanks!

I would say, first of all, that it is only ever a User that is actually logging into your website. A restaurant can't log into a website. A user who is a representative of the restaurant can log in. Therefore the restaurant should not be a type of user.
A better fit is to give your users roles, and have one of the roles be "restaurant_manager" or something. These users would naturally be associated with the restaurant too, so your code could look something like
if current_user.role == "restaurant_manager"
#show extra links for the restaurant admin section
elsif current_user.role == "company_manager"
#show extra links for the company admin section
or something along those lines, and, like you suggest, you make sure that a user can only ever access their own restaurant/company in the restaurant/company admin sections.

Related

Check Role of user in spree Rails

I have 2 roles
1. user
2. Gatekeeper
my database is like this
table:spree_roles_users
fields:
role_id
user_id
Both users and gatekeeper have rights to create new visitor,
but on index page it should display visitors which are entered by gatekeeper only
so how to check role of user_id
example:
There is a society say "My society"
There are 5 users who are registered from My society ,3 users have "User" role, 1 user have "admin" role, and 1 user has "Gatekeeper" role.
All 5 of them can save Visitors form, but in index page,only those visitors should b visible which are entered by person with "Gatekeeper" role.
So how to check Id_user with spree_roles_users
so visitors entered by Gatekeeper should b visible
I think you might be more interested in Solidus (a fork of Spree) which has received a lot of work pertaining to permissions inside of Spree. The permissions are managed by CanCan and you can find them located inside of permission helpers.
https://github.com/solidusio/solidus/tree/master/core/lib/spree/permission_sets
Spree is not that mature when discussing permissions...

Complicated Website Structure - Rails

I what I consider to be an advanced beginner with Ruby on Rails (and web design in general). I have this project and I'm having trouble wrapping my head around how to implement a recent development.
Initially the project was a simple blog for businesses to post articles that promote their company. It was meant for businesses in a specific town only and I had no trouble setting that up. Now we're trying to broaden out and let the site cater to many towns.
We want to have a home page where you select a town. That takes you to a list of blog posts from businesses in that town. You can navigate to a directory, contact us form, profile page etc. My problem is, I'd like each town to act like mini-site, so the directory only shows business associated with the town and the header image changes to reflect which town you've chosen.
My initial approach to this problem was to set up a towns scaffold and put in associations between towns, users and posts. The problem is 'storing' the chosen town somehow so that I can, for example, show only businesses for a specific town in the directory.
At the moment I have, in the posts model
belongs_to :user
In the user model
has_many :posts
has_many :towns
I have an action in towns controller to handle the directory which only has the line:
#users = User.order('trading_name ASC').where(:town => #town.id.to_s)
and then I want to display those users in the directory view.
I also have the following in my towns controller
before_action :set_town, only: [:show, :edit, :update, :destroy, :directory]
To be honest though, I can't fully wrap my head around the associations needed or even if this is the correct path to take. As it stands I get the following error when I try to access the directory view
Couldn't find Town without an ID
and it references the following method in towns controller (I'm using the friendly_id gem)
def set_town
#town = Town.friendly.find(params[:id])
end
Am I heading down the correct route with these associations (and missing something) or is there a better approach I could be taking. Also, I hope I've explained myself clearly. Please ask if there's something that's confusing.
I'm not sure exactly what your requirements are, but I'd say:
A user probably doesn't "have many" towns.
A user does "have many" posts.
A town does "have many" posts.
A post belongs to a town, and also a user.
Then, on your home page, you'd have a form with a drop-downlist of towns, and it should sumbit to an action like choose_town or something.
Your choose_town action should save the name or id of the town in a Cookie. You know about cookies? They basically allow you to save little bits of info between requests, for a specific user. They are stored in a users browser, but are sent back/forth from the server on every request. See http://guides.rubyonrails.org/action_controller_overview.html#cookies
Then, your set_town method, called every request, will look in the cookie to find the right town.
edit: #japed mentioned session, along with cookies. The session is identified by a cookie - however, information stored in the session is saved on the server, and is not sent back and forth between the browser and the server. In this case, either one is probably fine.

Modelling multiple types of users with Devise and Rails 4

I have 3 types of "users"
Shop
Provider
Customer
The last 2 users will have similar attributes such as
First Name
Last Name
and so on
And the Shop user type will have the most contrast between types.
As far as behaviours they will all be quite different, although Provider and Shop will inherent many of customer behaviours.
It seems the behaviours can be dealt with CanCan as I've researched.
I'm now attempting to how I should authenticate these types.
I have looked at the STI model but I couldn't grasp where I would these extra attributes.
My mental model is as follower:
User is a table and model
The types are abstract models that inherit from this.
So I'm wondering, how do I add attributes such as Business address for just the Shop type?
Or is it that the User Table has a column called Type and that type is associated with these type tables? And within the type tables are the extra attributes?
Don't even bother bringing Devise into this; Devise is for authentication not authorization. Authentication is determining whether or not someone who visits your site is who you think they are, like logging in. Authorization is deciding whether or not a user is allowed to perform some sort of action, like creating a new post.
What you want to do is have some sort of system that assigns a normal user your three different types; CanCan will do something like that. One way to do this on your own is using a permissions number based system. Let's say normal users have permissions level at 100, shop has a level at 50, and provider at 25. Using this system you can determine what actions a user can perform without having to make separate models, which will make your schema unnecessarily complicated. Here's an example of how this would work with say the UserController:
def show
if current_user.permissions == 100
render "customer_show"
elsif current_user.permissions == 50
render "shop_show"
else
render "provider_show"
end
end
The easiest way to do this is to add a column to the user's table called permissions that defaults to say 100 when a new row is created. Here's what that migration would look like:
def change
add_column :users, :permissions, :integer, default: 100
end
As for authenticating, don't worry about it. Let devise do it's thing; every user, no matter what type, will login and sign up in the same way, maybe just having separate forms for each that has a hidden field to set the permissions level for that specific kind of user.
I know I'm late to the party but I'm putting this out for future SO searchers. You CAN authorize actions with Devise. If you have devise models for 'buyer' & 'seller' you can add 'buyer_signed_in?' for whatever action you only want buyers to be able to do. You can also do more specific role-based authorizations as well - check out Devise' page
All in all, Tsiege's solution sounds pretty interesting. Let us know if you had any success with it!

Authentication & Roles management for different users, howto solve this?

Could you help me to solve this ?
I'm creating a management application with to different users :
"User" they are definided in app, that's management person, won't change, and
"Student" they are definided in a table that would growing for the next 6 month (now I have maybe 10 students in this table, next month maybe 100)
Attribut between users and students are different
I should create an application with backend and frontend
Frontend could be used by user and student
Backend could be used only by user if they have "admin" flag
I would use ActiveAdmin for backend
But for Frontend i'm lost...
It seems that cancan and devise could solve this, but :
Should I create a User model and a Student model, or is there a better way ?
Howto manage the connection on the same frontend views(maybe should i create two different views) from two differents tables (users and students) ?
Student should receive a "student_role" automatically, howto do this ?
All idea would be greatly appreciated, many thanks to read me !
Nicolas
can can + devise is a great way to solve problems like this one,
also i would suggest only one model for the user and a usertype attribute that defines if its a student or a user, for the connections you can create a user controller and a student controller if you only need to show them to specific users and you can use cancan to authorize that like this:
class Ability
include CanCan::Ability
def initialize(user)
if user.usertype=1
can :read, Student
elsif user.usertype=2
can read, User
end
end
end
your student role can be the usertype = 1 or something
if you need more help ask me.

Ruby on Rails / MVC - Splitting Views for different user levels

I have a Rails application which handles hotel room reservations. I would like an admin to see all reservations and specific users to only see their reservations. Is the 'proper' way of doing this:
Create a new action for each user in the reservation controller
OR
Put an if statement in the index action, deciding whether to return all reservations or only those for a user id sent by parameter
I have it set up and working the second way but I'm not sure this is the correct way of doing things.
I would do this by having a single view, which is populated by the appropriate collection of reservations. For an admin this would be all reservations, but for a regular user the collection would only contain their bookings.
This then requires a single if statement in the controller to ascertain the appropriate reservations:
if user.is_admin?
#reservations = Reservation.all
else
#reservations = user.reservations
end
The above code assumes that you've setup an appropriate relationship between a user and their reservations, but you get the idea.

Resources