How to customize devise form css in rails - ruby-on-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

Related

Rails 4 x premailer x SASS: import stylesheet in mailer view

In my Rails 4 app, I use mailers to send out emails to users.
These mailers are working fine.
Now, I would like to style them, so I installed the premailer-rails gem (and the nokogiri gem).
I restarted my server.
Then, I created a specific stylesheet for mailers: public/assets/mailers.scss
I my mailer view, I added:
<head>
<% stylesheet_link_tag mailers "public/assets/mailers.scss" %>
</head>
However, when a user opens the email in his inbox, for instance Gmail, the style is not applied.
Is there a particular way to include stylesheets in mailer views in Rails with premailer when using SASS?
What is mailers in you code snippet? If it is some helper that returns the name of the css file, then it's ok. See here in documentation what is expected by stylesheet_link_tag method.
Anyway, whatever it is, you are missing = sign, and you need it in order to render anything into you view:
<head>
<%= stylesheet_link_tag mailers "public/assets/mailers.scss" %>
</head>
No,there is no certain way to conclude stylesheet.

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' %>

Live assets compilation only for one file in Rails

There is config.assets.compile=true parameter which enables so called "live compilation".
I need Rails to compile one specific asset (sample.css.scss.erb) on each request in live mode but the rest of assets should be still precompiled.
How can I achieve this?
Option 1 - put sample.css.scss.erb in a path different from config.assets.manifest (default="public/assets") and add it with javascript_include_tag
Option 2 - Remove it from the config.assets.precompile
config.assets.precompile -= %w( sample.css.scss.erb )
Make sure you clean then precompile to test it.
I did not test either option, please let us know if any works for you.
Live compilation for file is required when css is preprocessed by .css.erb file.
It means dynamically compiling css.
For example : allowing users to set the colors and would like to conditionally use "live compilation"
In that case i will suggest dynamically rendering /users/:id/styles.css.erb instead of live compilation.
Reason there might be millions of users and in production environment using Ec2 instance will cost you more. That's why i will suggest below solution:
First define your custom action on the UsersController:
# config/routes.rb
match '/users/:id/styles' => 'users#styles', :as => :user_styles
Link to the "stylesheet" in your layout:
# app/views/layouts/application.html.erb
= stylesheet_link_tag 'application', user_styles_path(current_user, :format => 'css')
Define the action in your controller. You could do whatever you want to retrieve the user's preferences here:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def styles
#colors = User.find(params[:id]).colors
end
end
That action will automatically render this view:
# app/views/users/styles.css.scss.erb
$background-color: <%= #colors[:background] %>;
body {
background-color: $background-color;
}
More ideas and suggetions are most welcome.

Can't override default devise gem views

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.

Rails 3.1 asset pipeline: how to load controller-specific scripts?

If I generate a new controller in Rails 3.1, also a javascript file with the name of the controller will added automatically. Firstly, I thought this javascript file will used only, when the related controller is called.
By default there is the instruction //= require_tree . in the application.js-file, that include every javascript file on it's tree.
How could I load only the controller specific script?
To load only the necessary name_of_the_js_file.js file:
remove the //=require_tree from application.js
keep your js file (that you want to load when a specific page is loaded) in the asset pipeline
add a helper in application_helper.rb
def javascript(*files)
content_for(:head) { javascript_include_tag(*files) }
end
yield into your layout:
<%= yield(:head) %>
add this in your view file:
<% javascript 'name_of_the_js_file' %>
Then it should be ok
An elegant solution for this is to require controller_name in your javascript_include_tag
see http://apidock.com/rails/ActionController/Metal/controller_name/class
<%= javascript_include_tag "application", controller_name %>
controller_name.js will be loaded and is in the asset also, so you can require other files from here.
Example, rendering cars#index will give
<%= javascript_include_tag "application", "cars" %>
where cars.js can contain
//= require wheel
//= require tyre
Enjoy !
I always include this inside my layout files. It can scope your js to action
<%= javascript_include_tag params[:controller] if AppName::Application.assets.find_asset("#{params[:controller]}.js") %>
<%= javascript_include_tag "#{params[:controller]}_#{params[:action]}" if AppName::Application.assets.find_asset("#{params[:controller]}_#{params[:action]}.js") %>
Your problem can be solved in different ways.
Add the assets dynamically
Please consider that this isn't a good solution for the production mode, because your controller specifics won't be precompiled!
Add to our application helper the following method:
module ApplicationHelper
def include_related_asset(asset)
# v-----{Change this}
if !YourApp::Application.assets.find_asset(asset).nil?
case asset.split('.')[-1]
when 'js'
javascript_include_tag asset
when 'css'
stylesheet_link_tag asset
end
end
end
end
Call the helper method in your layout-file:
<%= include_related_asset(params[:controller].to_param + '_' + params[:action].to_param . 'js') %>
Create specific assets for your controller actions. E. g. controller_action.js
Please don't forget to change YourApp to the name of your app.
Use yield
Add <%= yield :head%> to your layout head
Include your assets from your action views:
<% content_for :head do %>
<%= javascript_include_tag 'controller_action' %>
<% end %>
Please see the Rails guides for further information.
I like albandiguer's solution. With which I've found that javascript/coffeescript assets are not individually precompiled. Which causes all sorts of errors trying to use javascript_path. I'll share my solution to that problem after I address an issue a few people mentioned in his comments. Mainly dealing with only a partial set of controller named JavaScript files.
So I built an application helper to detect if the file exists in the javascript directory regardless of .coffee/.js extension:
module ApplicationHelper
def javascript_asset_path(basename)
Sprockets::Rails::Helper.assets.paths.select{|i|
i =~ /javascript/ and i =~ /#{Rails.root}/
}.each do |directory|
if Dir.entries(directory).map {|i| i.split('.')[0]}.compact.
include? basename
return File.join(directory, basename)
end
end
nil
end
end
This method will return the full path to the javascript file if it exists. Otherwise it returns nil. So following Pencilcheck's comment you can add this method for a conditional include:
<%= javascript_include_tag(controller_name) if javascript_asset_path(controller_name) %>
And now you have a proper conditional include. Now for the issue of precompiled assets. Generally for optimization you don't want assets precompiled individually. You can however do it if you must:
# Live Compilation
config.assets.compile = true
You can add this do your environment config file. Test it in your development environment file first. Again this is ill-advisable. The Rails asset pipeline uses Sprockets to optimize everything:
Sprockets loads the files specified, processes them if necessary,
concatenates them into one single file and then compresses them (if
Rails.application.config.assets.compress is true). By serving one file
rather than many, the load time of pages can be greatly reduced
because the browser makes fewer requests. Compression also reduces
file size, enabling the browser to download them faster.
PLEASE READ the documentation for further details of the mechanics of Sprockets (Asset Pipeline) http://guides.rubyonrails.org/asset_pipeline.html
Assets aren't precompiled individually. For example when I try:
<%= javascript_include_tag 'event' %>
I get:
Sprockets::Rails::Helper::AssetFilteredError: Asset filtered out and
will not be served: add Rails.application.config.assets.precompile +=
%w( event.js ) to config/initializers/assets.rb and restart your
server
So you can include which assets to be precompiled individually. We just need to add the relevant controller named javascript files in our asset initializer. Well we can do this programatically.
To get a list of controller names I will use ecoologic's example:
all_controllers = Dir[
Rails.root.join('app/controllers/*_controller.rb')
].map { |path|
path.match(/(\w+)_controller.rb/); $1
}.compact
And now to get the name of all javascript files that match the basename of the controller name you can use the following:
javascripts_of_controllers = Sprockets::Rails::Helper.assets.paths.select{|a_path|
a_path =~ /javascript/ and a_path =~ /#{Rails.root}/
}.map {|a_path|
Dir.entries(a_path)
}.flatten.delete_if {|the_file|
!the_file['.js']
}.collect {|the_file|
the_file if all_controllers.any? {|a_controller| the_file[a_controller]}
}
Then you can try:
# config/initializers/assets.rb
Rails.application.config.assets.precompile += javascripts_of_controllers
This will get you a list of all javascript files, without directory path, that match your controller name. Note if your controller name is plural, the javascript name should be as well. Also note if the controller is singular and the javascript file is plural this will still include it because of the_file[a_controller] will succeed on a partial match.
Feel free to try this out in your Rails.application.config.assets.precompile setting. I know that this gets you the list of files correctly. But I'll leave you to test it. Let me know if there are any nuances involved with precompiling this way as I am curious.
For a very thorough explanation on how assets precompile see this blog: http://www.sitepoint.com/asset-precompile-works-part/
I recently found a simple approach to use generated scripts for specific controller. I use for that solution gem gon. Add in a controller:
class HomesController < ApplicationController
before_filter :remember_controller
private
def remember_controller
gon.controller = params[:controller]
end
end
After that open your homes.js.cofee and add in the beginning of file:
jQuery ->
if gon.controller == "sermons"
# Place all functions here...
That is all.

Resources