Devise CanCan Roles and Profile - ruby-on-rails

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.

Related

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!

rails g scaffold needs explanation - form_for submits to index?

I am trying to understand the stuff going on during the creation of an object using the pages generated by the command rails g scaffold ModelName.
What I don't understand is that given a model Location, the _form.html.erb form-tag looks like this:
<%= form_for(#location) do |f| %>
This would, if I understand it correctly, point the form submission to location_path, which is like the index (or list) of all locations stored in the database.
Why is the form not pointing to create or update? Where on the way are the objects actually created? I'd be really grateful if someone could describe the flow here, like
_form.html.erb submits to
create in locations_controller.rb which redirects to
index in locations_controller.rb, which renders
sometemplate.html.erb
Where the form submits depends on #location.new_record?.
If it’s a new record, it will POST to locations_path: /locations. That maps to LocationsController#create.
If it’s an existing record, it will PUT (or PATCH on newer versions of Rails) to location_path(#location): /locations/:id. That maps to LocationsController#update.
As #Pavan suggests in the comment, a look at the existing routes can help with understanding routing:
rake routes

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.

Rails naming convention issue

My question pertains to a Rails naming convention conundrum. My application has sign up, sign in, sign out features.
For the sign up page, I used form_for(#user) helper.
For the sign in page I used a form_for(:session, url: sessions_path). But in my routes.rb file I have included the resources :sessions instead of the singular as mentioned in the argument of form_for helper in the sign in page.
If someone could:
1.) Solve this particular form_for issue
2.) More importantly point me in the direction where I can learn/read about Rails naming conventions, I would be highly indebted.
I bet that #user has been initialized with User.new - this is a new user. When you sign up you want to create a new user so you can translate form_for(#user) as "form for a new user". Note that in this case you provide form_for an ActiveRecord User instance, which is the way it was meant to be used.
When you give form_for a symbol and not an instance of an ActiveRecord model, it uses the symbol to nest the inputs inside the form. For example, if you put <%= f.text :name %> in your form it will generate <input name="session[name]" type="text">. Also, when an existing user signs in you do not want to create a new user(like in step 1), you just want to create a new session for an existing user, thus posting to sessions_path looks very intuitive.
You can type the command rake routes in your terminal and get all the named routes set for your application, this will give you a very good insight of how rails converts the resources command into named routes.
For further info read the following:
Rails Routing Guide
form_for ApiDock documentation

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