if can? in Ruby on Rails - 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.

Related

Accessing Views Within Ruby on Rails Application

I want to make a view for my website coded in RoR wherein all the available path are listed as links. Is there any way to access the views for various models from the program?
For example, something like:
<%model.views.each do |v| %>
<%= link_to v %>
<% end %>
You could use the sitemap_generator or dynamic_sitemaps gem to generate Sitemaps for your application.
You can use named routes, which allows you to create a link to a different part of your rails app, based on names you set in routes.rb. You can also include route parameters, too, which makes it easy to link to models.
In your routes.rb
get 'test_route/:id' => 'example#controller', as :test
In controllers/views:
link_to #example.name, test_path(id: #example.id)
Further reading on named routes
Im not sure why you want this :), but this will give you the routes
Rails.application.routes.routes
if you want to get all the paths as an array
Rails.application.routes.routes.collect {|r| r.path.spec.to_s }

Ruby on Rails: How to link/route from one view/page to another view/page with a different controller

I have a view template within the following file in my Rails application:
app/views/static_pages/mission.html.erb
I want to link to that page from a view template in a different folder (corresponding to a different page in the app):
app/views/home/home.html.erb
I don't know what to write in my mission method in the StaticPagesController. I'm also a newbie at Rails. I also don't know how to write the route for it and I suspect I may need to write a get 'something' in my routes.rb file.
Can anybody help with this?
What you are asking can be accomplished in this way:
In your routes.rb:
get "/path/to/your/mission/page", to: "static_pages#mission", as: "mission"
Then in your static_pages_controller.rb:
class StaticPagesController < ApplicationController
# You can leave the mission method blank, it will render
# the corresponding static_pages/mission.html.erb by default
def mission
end
end
This should set up the static page, so that when you visit: localhost:3000/path/to/your/mission/page, you should be able to see the mission.html.erb page rendered.
To link to the mission page from any other template, you can simply point a link to it, like so:
<%= link_to "Mission Page", mission_path %>
Or, since it's a static page, you can just hardcode the path into the markup:
Mission Page
Since you're new to Rails (welcome to the world of Rails btw :D), I hope you find these really great resources useful:
Official Rails Guides
Rails For Zombies
Railscasts by Ryan Bates
Hope this was helpful!

application with multiple "accounts", each containing multiple users

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.

Devise CanCan Roles and Profile

I am trying to create profile pages for my community site. I have followed video tutorials and read docs on github for both Devise gem and CanCan gem. I have installed and currently have a functioning authentication system thanks to these two gems and the tutorials at railscasts.
I am very new to ruby and rails so everything is still very literal. My first question relates to a line of code from CanCan wiki page
<!-- in users/_form.html.erb -->
<%= f.collection_select :role, User::ROLES, :to_s, :humanize %>
I do not see a users folder or this controller. Is this something I can generate - for example I ran
rails g devise User
Could I also run:
rails g controller Users
I have seen this question here but do not quite understand the answer. Will I get an error by generating the "Users" controller to handle the things I would like to do?
I generated the devise views, but don't see any controllers - I understand that these could be overwritten - although I dont quite understand how this would work. If I overwrite than would all default devise controller functionality still work plus overwritten controller?
If I can generate the "Users" controller, I assume I could just put a view template into that location for all of the profile view information. I apologize for the amount of questions and length of this post, but I think with a little help I could be off and running again. Thanks for any information provided.
Alright so I solved this! I will post my solution for anyone with a similar question who could potentially benefit.
One of my questions was:
Could I also run:
rails g controller Users
Yes this is what I did. I use nifty scaffold generators to generate the views so this command would actually look like the following
rails g nifty:scaffold user
It is important to note that I DID NOT pass any variables after user. Devise has already created Users table in the database. This would create a conflict. Rails thinks you would like to overwrite your original database - which you do not want to do.
Do this builds the correct structure for User CRUD. Next open your config/routes.rb file.
Using nifty generators add the resources :users to the top of this file - move this below the devise resource and prefix the path as described on this devise wiki page to resemble the code below.
devise_for :users, :path_prefix => 'd'
resources :users
This is very important to remove any conflicts with your User controller and the devise controllers url paths by adding the "/d/" prefix to all devise controllers.
As well as adding the following code to you users_controller update method:
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
Which ensures devise will validate correctly.
Now comes the fun - register a user if you have not done so already. You now have a profile page for that user located at:
localhost:3000/users/1
localhost:3000/users/2
localhost:3000/users/3
...ect
You can edit user show.html.erb page in the views folder to change what information will display on each users profile page.
As for my question about Roles:
<!-- in users/_form.html.erb -->
<%= f.collection_select :role, User::ROLES, :to_s, :humanize %>
You now have access to this in the user controllers created by nifty-scaffold generator, so you can add this code to your form if you were also following Ryan Bates methods to integrate CanCan roles as described here.
Hopefully this help some else.

1.8.x Ruby on Rails RESTful nested admin page and form_for problems

So I am creating a website that I want to have an admin directory in rails 1.8.x and I'm struggling a bit to get the form_for to link to the right controller. I am trying to be RESTful. What I basically want is an admin page that has a summary of actions which can then administer sub models such as:
/admin (a summary of events)
/admin/sales (edit sales on the site)
/admin/sales/0 (the normal RESTful stuff)
I can't use namespaces since they were introduced in Rails 2.0 (production site that I don't want to mess with updating rails and all that).
Anyway, what I have in the routes.rb is:
map.resource :admin do |admin|
admin.resources :sales
end
I am using the map.resource as a singleton as recommended by another site.
The problem comes in when I try to use the form_for to link to the subresource RESTfully. If i do :
form_for(:sales, #sale)
it never links to the right controller no matter what I try. I have also tried:
form_for [#admin, #sale] do |f|
and that does not work either (I am guessing since admin is a singleton which does not have a model, it's just a placeholder for the admin controller). Am I supposed to add a prefix or something? Or something into the sales controller to specify that it is a subcontroller to admin? Is there an easier way to do this without manually creating a bunch of routes? Thanks for any help.
You can use controller, action and html options something like following.
<%= form_for :sales, :controller=>controllerName, :action=>actionName, :id=>idParameter}, :html=>{:onsubmit=>"someFunction()"} do |f| %>
|
|
|
<% end %>

Resources