Can't override default devise gem views - ruby-on-rails

I want to use my devise generated views (with command rails g devise:views users) from app/views/users.
I already have set these options from app/initializers/devise.rb:
config.scoped_views = true
config.default_scope = :user
but it still uses default devise views from /usr/lib/ruby/gems/1.8/gems/devise-2.0.4/app/views/devise/
So what should I do?
Thanks.

I was having this same problem and it took me forever to figure it out. Setting config.scoped_views = true is the first step, but there's another step that's not as clear.
If you look closely at some of the views that get generated by rails g devise:views users you'll see that the templates include <%= render "devise/shared/links" %> at the bottom of the file. Since you have generated these views, the shared links are now located in users/shared/links. Since devise doesn't find anything in devise/shared/links anymore, it uses the default links view instead.
Change <%= render "devise/shared/links" %> to <%= render "users/shared/links" %>and you're set!

For a custom login view, when you're using the default User devise resource, I think all you need is to create app/views/devise/sessions/new.html.erb. And, just for the moment, let's forget about the CRUD interface. And undo those config/initializers/devise.rb settings. Just see if you can get that working.

Related

Rails Modify Scaffold Form

Using rails 5.0.0 for building a simple timecard module for a web application. My question is how do I go about modifying a form which is automatically being rendered by rails scaffold
rails g scaffold Timesheet user:string clock:string time:datetime
=== new.html.erb file ===
<%= render 'form', timesheet: #timesheet %>
In the user string want to add <%= current_user.email %> and in clock string want to add a drop-down? What is the best way to do this? Already have database table in place etc...
Illustration below
Thanks in advance!
The form is in an automatically generated partial, located in app/views/timesheets/_form.html.erb.
Ok, in: app/views/timesheets - you should find your form. If you change something in form, check it with your 'new' merhod (or with last method - if you didn't change/add anything: this method will get your params) in controller.
When you run
$rails generate scaffold <name>
you will auto-generate a ready to use controller, model, and views with a full CRUD (Create, Read, Update, Delete) web interface.
You can modify each of the CRUD operations to your liking, in your case timesheets view which is located in app/views/timesheets/.

Adding custom javascript to device

In my javascripts folder for my rails application, I've added both a device.js file as well as a device/registrations.js file. I was under the impression that when I'm routed to the registration page, rails would automatically pick up the correct javascript files, but for some reason it's not working.
Is there anything that needs to be added so that it can use custom javascript code?
You can include that in your registration view of devise by doing:
<%= javascript_include_tag 'devise/registrations' %>
To generate the views do
rails g devise:views
EDIT
Another way would be in the views/devise folder create a partial _registrations.html.erb
Put your js code in there and then do
<%= render 'registrations' %>

How to customize devise form css in rails

Command rails generate devise:views successfully created folders under \app\views\users
I am looking to customize the devise forms but not sure whether the css to be placed in application.css or i need to separately create user.css.scss. Googled a bit and check git doc for this but none is specifying for CSS handling in devise.
Let me know the correct way of handling it
Devise will use you default layout. So the CSS that you are using in your views/layouts/application.html.erb will be used in your generated devise views.
If you want devise specific layouts, you can create a views/layouts/devise.html.erb file where you can serve devise specific CSS. It will pick it up automatically because of Rails naming conventions.
The above will work for any controller, just add a file in layouts named after the controller eg. views/layouts/reservations.html.erb for ReservationsController
You can also add specific layouts for the Devise::RegistrationsController by making a directory views/layouts/devise and adding views/layouts/devise/registrations.html.erb
If you are doing controller-specific stylesheets, that is, if you switched off automatic compilation of all of your stylesheets into application.css, you should name your stylesheet after a devise controller, e.g.:
registrations.css.scss
and add it to Rails.application.config.assets.precompile list in assets.rb.
The placement of the stylesheet is standard, app/assets/stylesheets/ so watch for name collisions between devise's controllers and yours.
To pick up a controller-specific stylesheet in a layout you need something like this:
Rails up to 4.1
<%= stylesheet_link_tag controller_name, media: 'all' if Rails.application.assets.find_asset("#{controller_name}.css") %>
Rails 4.2+
<%= stylesheet_link_tag controller_name, media: 'all' if asset_present?("#{controller_name}.css") %>
# ...meanwhile, somewhere in the helpers...
def asset_present?(name)
# Rails 4.1 had Rails.application.assets filled out in all environments.
# Rails 4.2 has it filled only when config.assets.compile == true which is only
# in development by default.
if Rails.application.assets.present?
Rails.application.assets.find_asset(name)
else
Rails.application.assets_manifest.files.values.map { |v| v['logical_path'] }.include?(name)
end
end
To generate device view run this line
rails generate devise:views
and do what ever you want with page styling.
to read more Click here

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.

Where to put partials shared by the whole application in Rails?

Where would I go about placing partial files shared by more than one model?
I have a page called crop.html.erb that is used for one model - Photo.
Now I would like to use it for another model called User as well.
I could copy and paste the code but that's not very DRY, so I figured I would move it into a partial.
Since it's shared between two models - where would I place that partial?
Thanks!
The Rails convention is to put shared partials in /app/views/shared.
Update
Layout inheritance is now in the guides under layout and rendering
Template inheritance works similarly.
Rails 3.1 and following versions implement template inheritance, so I think the correct place for shared partials is now /app/views/application/, say you are in products#index you can do the following:
-# products#index
= render #products.presence || 'empty'
-# /app/views/application/_empty.html.haml
There are no items
btw it's application because the connection is the controller inheritance, so this assumes ProductsController < ApplicationController
This way if you implement /app/views/products/_empty.html.haml that will be taken, the above is a fallback for all the missing partials, and I can't check right now, but I think even for the template itself...
Railscast: template inheritance!
TL;DR
Rails 3.1, Rails 4, Rails 5 and whatever comes next
app/views/application
The engine searches this path automatically if the view is not found in the controller path.
Rails 3 and prior
app/views/shared
The engine does NOT search this path automatically.
Long story
Rails 3 (and prior version) have no default location for storing shared views.
The unofficial convention is to store shared views in app/views/shared. Wherever you'd end up storing them though, you have to specify the path
# render app/views/shared/menu.html.erb
<%= render :partial => "shared/menu" %>
This suggestion was popularized by Agile Web Development with Rails.
Rails 3.1 introduces an official standard for where to store shared views:
app/views/application
Thanks to this standard, the engine now automatically looks for templates in app/views/application. As a result, you don't have to use the full path anymore.
Those curious can follow here the thought process behind this decision.
Old syntax
# render app/views/application/menu.html.erb
# unless menu.html.erb is found in appp/views/my_controller
<%= render :partial => "menu" %>
New syntax
# render app/views/application/menu.html.erb
# unless menu.html.erb is found in appp/views/my_controller
<%= render partial: "menu" %>
Of course, you can still place your shared views wherever you want and reference them by path
<%= render :partial => "my_own_special_shared_folder/menu" %>
Unless you have a very good reason to do this though, please stick to the new standard and store your shared views in app/views/application.
The Rails View uses app/views/layouts for shared partials like header and footer, but the Ruby on Rails Guide uses app/views/shared in an example. I guess it comes down to personal preference. I would use layouts for high-level stuff like a main nav or a footer, but shared for more narrow controller-level stuff like a form.
I general have a shared folder in my views that contains commonly used partials.
I arrived here in 2021 (rails 6) and got confused by the answers (many different ways).
I asked some senior rails developers what they'd do and they also gave me 2 different answers.
But TL;DR
Create a folder called 'shared' or 'application' inside your views folder (e.g. app/views/shared or app/views/application.
Then simply move the partial there, and access it with either
<%= render partial: 'shared/socials' %>
# or
<%= render partial: 'application/socials' %>
or even simpler
<%= render 'shared/socials' %>
# or
<%= render 'application/socials' %>
It doesn't matter where you put them. You can render any partial at any arbitrary location by providing the file's path to render - it doesn't need to be associated with the controller that's rendering it. I use a directory simply called partials under the view directory, and call partials in it like this:
render :partial => 'partials/mypartial'

Resources