How to seperate asset pipeline with different layouts - ruby-on-rails

I have a new project, and I have created 2 layouts for it.
The 1st layout is the main layout used for the application.
The 2nd layout is for the 'beta' landing page, where users can signup via email to recieve updates on the website. I am using bootstrap for this section.
My assets folder looks like:
/assets/
/assets/bootstrap/
/assets/.... (default folders generated by rails 4)
Is it possible for asset pipeline to server the assets for the 'beta' layout from the /assets/bootstrap tree?

You will have to use two layout files in app/views/layouts: one you just leave like it is and then you create a second that will be called something like application_bootstrap.html.erb. In the second one you will include a stylesheet link tag like <%= stylesheet_link_tag "bootstrap" %>. In the assets directory you will have the regular application.css where you have to make sure not to include the assets/bootstrap directory and a new bootstrap.css which simply requires the assets/bootstrap/ tree to be included.
Then in you controllers you can switch the layouts: layout application_bootstrap and it will include the new layout file which in return includes the new CSS that you created. Of course you could also switch the layout in the application_controller.rb based on user settings or whatever you choose.

Related

Use a different folder for assets

For a Rails application I am making I want to be able to switch 'themes' using a configuration file. The theme does not need to switch dynamically (while running, but will be known when the application starts).
I moved my stylesheets directory out of my assets directory, to a folder called : /app/themes/[themename]/assets/stylesheets.
The idea is to have multiple folders in the /app/themes directory, which can be used by the application.
REMARK: I didn't move my javascripts folder from the assets folder, because I still want to use that globally.
In my layout I use the following code, to load controller specific stylesheets:
<%= stylesheet_link_tag "#{controller_name}" if MyApp::Application.assets.find_asset("#{controller_name}") %>
Of course, my application no longer knows where my assets are and it serves me a page, where the assets are not loading (because of the if check mentioned above).
I added the following code to my config/initializers/assets.rb to make sure it also loads the assets from the theme directory:
Dir.glob("#{Rails.root}/app/themes/#{Settings.site.theme}/assets/**/").each do |path|
Rails.application.config.assets.paths << path
end
Settings.site.theme is a string value which is filled correctly and now the stylesheets actually load on the website. So YAY!
But here is the thing, the minute I change the config.assets.compile to false, it all fails (so on test and production).
MyApp::Application.assets.find_asset("#{controller_name}") is throwing the exception undefined methodfind_asset' for nil:NilClass`.
I am on Rails 5.0.0.1.
Anyone got an idea how to fix this?
I think a simpler way would be to namespace the themes under the stylesheets. That is, have a folder structure like this:
- app
- assets
- stylesheets
- theme-blue
- application.scss
- theme-red
- application.scss
- javascripts
- application.js
And then, in your layout file, you just point the stylesheet_link_tag to theme-blue/application, like this:
<%= stylesheet_link_tag "theme-blue/application" %>
Another way to do this is have multiple layouts, one for theme-blue and another one for theme-red. In the controller, do
class BlueController < ApplicationController
layout "theme_blue"
end
And the file app/views/layouts/theme_blue.html.erb will require the right css file.
You might need to add the scss files to config/assets.rb, but Rails will tell you if you need that.

How does css in rails work?

I'm making my first website with rails. I'm a little confused with how rails does css files.
How do you maintain separate styles for each page if rails combines all the css files in the stylesheets directory into application.css? For example, if I wanted to include extra css just for one page I can do that normally by just making a new css file and referencing it in html, but it seems that's not how rails does it. Is it bad/Does it work if I just do something like "<link rel="stylesheet"..." right in one of the views?
I see that rails makes a new css file for every controller I do. Does this just mean the code put into these files will only used on views associated with the specific controller?
So basically its been decided that its quicker to compile all the CSS for your whole site and then thats cached on the users browser than to serve every different pages CSS. So for each view, you put *= require viewname or if you have require_tree . in your application.css then it will autoload everything in that directory. The splitting of each CSS file is just purely for ease of development.
If you want to have seperate for each page then put stylesheet_link_tag "style" at the top of your view, and make sure it's not included in application.css. You will also need to add it to your asset compiling through:
# config/initializers/assets.rb
Rails.application.config.assets.precompile += %w( cssfile.scss )

How to organize assets based on multiple layouts and render them separately?

My rails application has 3 main layouts. I want to keep these 3 layouts separate from each in terms of their assets (images, javascript, css).
How can I organize my assets to keep them separate?
Are there any drawbacks if I just create 3 folders inside assets?
Should I create 3 folders inside of each images, javascript and stylesheets?
/assets/layout1/{images, javascripts, stylesheets}
/assets/layout2 ..
/assets/layout3 ..
or
/assets/images/layout1
/assets/images/layout2
..
/assets/javascripts/layout1
/assets/javascripts/layout2
..
In my controllers are am doing this:
class Layout1Controller < AC
layout "layout1"
class Layout1Controller < AC
layout "layout2"
But the problem is ALL of the javascript and css etc. gets rendering on every page. How can I break them out into 3 separate files? Or is this just not possible when using the asset pipeline?
Check 2.2.1 Search Paths paragraph of official guide (The Asset Pipeline):
The default locations are: the images, javascripts and stylesheets
directories under the app/assets folder, but these subdirectories are
not special - any path under assets/* will be searched.
So both approaches are acceptable, and which one to use is a matter of personal preference I think.
Personally the second approach is more clear to me, either way you'll end up duplicating the structure (images, stylesheets, javascripts inside of each layout directory or each layout inside images, etc.).

What's the layouts folder for in Rails?

I understand that .html.erb files go within app/views or its subfolders. But what is the app/views/layouts folder in particular for in Rails?
app/views/layouts is the folder in which rails looks for the layouts.
From http://guides.rubyonrails.org/layouts_and_rendering.html#finding-layouts :
To find the current layout, Rails first looks for a file in
app/views/layouts with the same base name as the controller. For
example, rendering actions from the PhotosController class will use
app/views/layouts/photos.html.erb (or
app/views/layouts/photos.builder). If there is no such
controller-specific layout, Rails will use
app/views/layouts/application.html.erb or
app/views/layouts/application.builder. If there is no .erb layout,
Rails will use a .builder layout if one exists. Rails also provides
several ways to more precisely assign specific layouts to individual
controllers and actions.
What is a layout?
A layout defines the surroundings of an HTML page. It's the place to define common look and feel of the page.
The RailsCasts episode - All About Layouts - though very old, is still very useful in this context.
Layout in rails framework is very important folder, main layout of your application is define here as application.html.erb and all the views are yielded here using <% yield %>

Relative filename in ERB files

I am putting my ERB files in app/view. The problem is that sometimes I make mistakes when including CSS and JS files. I refer to them as "js/include.js" or "css/default.css" instead of /js/include.js and /css/default.css
However, these files are located in the public directory not the app/views directory so as a result the page breaks.
Is there a way to change the default behavior so that it looks in public folder whenever I refer to these files relatively?
If you stick with the Rails conventions you'll save yourself some grief. Use stylesheet_link_tag and javascript_include_tag in your layouts. And don't scatter css and js includes around your views. Use custom layouts instead.
For example, if you have an admin interface with a different look and different behavior you could add app/views/layouts/admin.html.erb. Then, in AdminController specify that it should use the admin layout. You can also specify the layout at the controller action level if you need to.

Resources