application with multiple "accounts", each containing multiple users - ruby-on-rails

I am trying to build an application with multiple "accounts", each containing multiple users.
I've started with the gem Devise to create user authentication, and I've created Accounts and Preferences MVC's with scaffolding.
The Account model has_one Preferences, and has_many Users
The User model and Preferences model belongs_to my Account model
I've tested these relationships in the console and they seem to work..
What I would like to do, is make sure that when users are logged in, they can only view records associated with their account. From what I've seen, the current_user helper can be used, but I would like to use something like a "current_account".
1. First question is, is there a resource, Gem, method that can help me to create this current_account variable?
2. Second question would be, what do I need to put in my View for this to work? For instance, if a user wants to update his Preferences associated with his account, how would we call this in the _form partial, would if be something like this?
<%= #account.preference.opt_in %>
and if they wanted to see all of the users in the account, would it be something like this?
<% #customer.user.each do |account| %>
<%= user.email %>
<% end %>
Please let me know if I'm overlooking anything major, I've been working on this the last few days.

If I understand correctly, you are looking for a multi-tenancy solution. If so, you don't need to come up with your own solution, as there are well established patterns out there.
You can try the Milia gem, which fits in nicely with devise.

Related

I want to change the page view based on whether the user is an admin

In rails, I have a model for users which has a flag for admins (yes, no). If the logged_in user is an admin, I'd like to be able to show different elements of the page using erb.
I'm currently doing this with logg in users vs non logged in users using this code
<% if current_user %>
But how would I specify if current_user is admin in the erb?
Or, is erb the best place to do this since it is exposed to the browser? If not, any suggestions for other ways to accomplish this in the model or controller?
I'm not using Devise for the user authentication currently.
When you say they have a flag, does that mean they have an attribute called admin?
If so, any model with a boolean in rails, you can check with:
<% if current_user.admin? %>
If there is another way of determining whether the user is an admin or not, you'll need to add an admin? method to the user class, which you can use to determine their status in the view.
You can use user is_admin column name in views.
<% if current_user.is_admin? %>

How do I take this from the console to a controller and view

I'm learning Ruby on Rails (my first MVC) and have successfully setup a many-to-many relationship between "Agents" and "Zipcodes." What I'm trying to do currently is to get the associated agent based on the zip code entered by the user. I'm able to so successfully in the console, but am having a difficult time translating it to a controller and view.
What I do in the console:
zip = Zipcode.find_by_zip(gets.chomp)
=> 92562
zip.agents
The hangup I'm having is how to translate this into an action that I can access from a view with a form.
I've started by defining the action (agents#find), but am stumped as to whether this is correct and what comes after it.
def find
#user_zip = Zipcode.find_by_zip(params[:zip])
end
Hopefully someone awesome in here can point a n00b in the right direction.
When just starting with rails, I'd suggest avoiding custom actions like #find as much as possible, and instead sticking to the "Big 7" RESTful routes. Rails is really smooth when you work with it and do what it expects.
It sounds like maybe you're trying to identify a given zipcode, and then list all the agents associated with it. That sounds like a #show on Zipcode.
config/routes.rb
resources :zipcodes
app/controllers/zipcodes_controller.rb
ZipcodesController < ApplicationController
def show
#zipcode = Zipcode.find_by_zip(params[:id])
end
end
app/views/zipcodes/show.html.erb
<div>
<p>This zipcode has the following agents:</p>
<ul>
<%= #zipcode.agents.each do |agent| %>
<li>Agent #<%= agent.id %></li>
<% end %>
</ul>
</div>
You can see this page by browsing to /zipcodes/[zip].
Just put #user_zip = Zipcode.find_by_zip(params[:zip]) in the controller instead of the model.
In the view you will be able to call #user_zip.
Welcome to Rails! I recently started learning Rails as well, but I think I can help: A controller action will redirect by default to a view with the same name. So after assigning the value of #user_zip, the controller will serve up agents/find.html.erb, which will have access to #user_zip. Since #user_zip is an instance of Zipcode, you'd be able to use #user_zip.agents.
Somewhat tangential, but I also suggest considering using search rather than find for the action name, only because find and its variations are used elsewhere in Rails.

if can? in Ruby on Rails

In a Ruby on Rails application that I inherited from someone, I have code that looks like so
<% if can? :create, :objects %>
<%= link_to 'Add New Object', new_object_path %>
This web application has a login and users have different permissions that are defined in a table called groups_roles (which groups (ex. admin, user) have which roles (ex. add new objects))
I want to add new permissions, so where do I do that at? Where are these things defined? How does Ruby know which table to get the different permissions from, and how does it know what :create and :objects are in the code above?
The app seems to be using the cancan gem by ryan bates. You can specify the permissions in the app/models/ability.rb file.
It simply reads the ability file to determine if a user can perform some action or not. These actions correspond directly to the actions you have defined in the controller class.
Cancan has a great wiki at its github repositiory. Also, the screencast by ryan is an excellent place to start off with.
I do not know how the application is working, but the can? comes from the cancan gem. See the screencast.

CanCan - checking permissions inside a model

im starting here with cancan and i would like to know how can i check for permissions inside a model or the best way to achieve what i want that is:
In my User form i have checkboxes for roles assignment but only Admins can do that. i Already hide the checkboxes in the html with <% if can? :assign_roles, #user %> but a bad intentioned user may edit the html and add the checkboxes and choose wich role he wants.
So i decided to use a before_save method to check whether the current_user can assign roles but i dont have access to can? method inside models.
Is there a better way to make this verification?
You can try this to archive your goal. So you will be able to use can? and cannot? methods inside your models in your model context.

Making sure I got the idea . - Ruby on rails login system

I am currently reading a book, and learning ruby on rails. (Agile Web Development with Rails 4th Edition) .In the book it says how to write a simple product list and display it. I am modifying this idea, to create a user login system.
I am only working on the views now.
So I just need to make sure that my idea is right. My idea is:
The show.html file from the USER model, show data for one user. (given of course its ID)
for example : http://localhost:3000/users/980190974 will give me the html page for the current user right? Now I can allow the user to edit his/her information by using the
<%= link_to 'Edit', edit_user_path(#user) %> link or restrict him from viewing other users by removing the <%= link_to 'Back', users_path %> << that lists all the users from the database. But before the user views his/her details he must login, using his email and password. So by making an html page, that takes 2 strings (username, and password) searches my mySQL database and return the user ID , that I then use to "render" the user's HTML page.
Is my way of thinking correct? Or am I just completely irrelevant on how Ruby on Rails works? O_o
You are heading in the right direction. One thing to point out is that simply removing the link <%= link_to 'Back', users_path %> is not sufficient to avoid other users from accessing the /users path. In the (user) controller you have to use something like:
class UserController < ApplicationController
def index
unless current_user.is_admin
redirect_to user_path(current_user)
return
end
... rest of code here
end
end
where current_user could be a method returning the user object

Resources