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.
Related
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 %>
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.
I know that most CSS codes go under app/assets/stylesheets, but I have some snippets of CSS codes that are specific to only certain pages. For now, I just have these small CSS codes included in the view files, but I feel like there's ought to be a better way of handling this.
Any suggestion?
Rails convention is to put these in controller specific CSS files:
For example, if a ProjectsController is generated, there will be a new
file at app/assets/javascripts/projects.js.coffee and another at
app/assets/stylesheets/projects.css.scss. You should put any
JavaScript or CSS unique to a controller inside their respective asset
files, as these files can then be loaded just for these controllers
with lines such as <%= javascript_include_tag params[:controller] %>
or <%= stylesheet_link_tag params[:controller] %>.
Putting the CSS inside the views isn't a good idea as you lose features (fingerprinting, auto minification) that the asset management in Rails provides.
Read more here: http://guides.rubyonrails.org/asset_pipeline.html#how-to-use-the-asset-pipeline
In a Rails 3.1.0 project, I have Companies with a few customizable attributes like background_color and link_color. I want to be able to set some Sass variables like so:
$background_color: <%= #company.background_color %>
$link_color: <%= #company.link_color
...
This doesn't work because #company is nil when Sass does its thing. I'm not sure how to go about solving this in a way that's dynamic (companies can be created and colors can be changed and the views update immediately). Any suggestions?
I can think of a couple approaches off the top of my head:
Serve your stylesheet through a controller.
Use CSS classes to configure the colors and serve just that CSS through a controller, inlined partial, or a CSS #import.
Serving your stylesheet through a controller is pretty straightforward so there's not much to say. This might be a bit ugly and cumbersome.
For the second one, you'd add a couple extra CSS classes:
.custom-bg {
background-color: some-default-bg;
}
.link-fg {
color: some-default-fg;
}
/*...*/
Then any element that need to use the custom background color would need their usual CSS classes and custom-bg; similar shenanigans would be needed for the other configurable values. To supply the customized CSS, you could inline a <style> element into your HTML using a standard ERB partial or you could serve the CSS through a controller (either through <style src="..."> or #import). So you'd fake the SASSy goodness with old school multiple CSS classes in your HTML.
There's also JavaScript. You'd need some way to identify the elements that need their colors adjusted and then adjust them directly with things like this:
$('.need-custom-background').css('background-color', '...');
I think you might be able to do something just like what you have there, but you need to change the extensions of the files to '.css.scss.erb'
To follow up on this, I did create a stylesheet controller but it was rather contrived to get Sass parsing and asset pipeline load paths all working correctly. I ended up dumping that and reorganizing the styles so I could generate a static stylesheet for each company which gets regenerated and uploaded to S3 on company update.
Well, if you mean a dynamic object like a model loaded via a controller, you can't really, at least not very easily. This is because unlike HTML ERB templates, the SASS ones are generally rendered once and served statically unless something changes in the code or they are re-precompiled via rake (depending on your environment configs). But you can access some helper methods, global objects, and use some ruby in there by renaming the file with an "erb" extension e.g. application.css.scss.erb. See
https://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets
How can I use Ruby/Rails variables inside Sass?)
If you need styles based on dynamically loaded objects, like models, you can...
Write CSS styles literally in the template
Compile the stylesheets dynamically. See the top-rated answer here: How do I create dynamic CSS in Rails?
For some use cases you might accomplish the same thing by leveraging Rails/SASS's import path hierarchy (i.e. SASS #import 'partial_name_with_no_path' will search the importing SASS files folder first and then fall back to the top level - You can configure this as well).
Hey, I'm new to Rails and Ruby in general. I was wondering if it's possible to use an embedded ruby css file (css.erb), similar to using html.erb files for views.
For example, I'm using
<%= stylesheet_link_tag "main" %>
to link to my main.css file in public/stylesheets, but when I change the file extension from main.css to main.css.erb, it no longer renders the css..
Is this even possible, or is there a better way?
By the time this question was answered there was indeed no way to use .css.erb files in rails properly.
But the new rails 3.1 asset pipeline enables you to use asset helpers inside your css file. The css parsers is not binded a controller/action scope, but the ruby parser is now able to resolve some issues like image path references
.class { background-image: url(<%= asset_path 'image.png' %>) }
or embed an image directly into your css
#logo { background: url(<%= asset_data_uri 'logo.png' %>) }
source: http://guides.rubyonrails.org/asset_pipeline.html
You can also generate a "stylesheets" controller
./script/generate controller stylesheets main admin maintenance
You get something like this:
exists app/controllers/
exists app/helpers/
create app/views/stylesheets
exists test/functional/
exists test/unit/helpers/
create app/controllers/stylesheets_controller.rb
create test/functional/stylesheets_controller_test.rb
create app/helpers/stylesheets_helper.rb
create test/unit/helpers/stylesheets_helper_test.rb
create app/views/stylesheets/main.html.erb
create app/views/stylesheets/admin.html.erb
create app/views/stylesheets/maintenance.html.erb
And you can later use the app/views/stylesheets/ files as dynamically rendered css files.
The same method works for javascript files (javascripts controller)
I dont think so. Whats your intention - to use variables and have them be evaluated at runtime, or "compile" time (meaning like deploy time?). Also, what would be the ERB binding? Would it bind to the controller, like views and helpers are, so that ERB instance would have access to the instance variables set in the controller? I just pose this question as more of a theoretical exercise.
If you want to use variables in your CSS than you can use Haml's SASS. You dont get access to the controller's scope but you do get basic variables and looping. Plus other cool stuff like mixins.