Changing between layouts requires refresh to see changes - ruby-on-rails

In my controller, I've got my show action using a different layout (e.g., foo.html.erb) than my application.html.erb. foo.html.erb has styles loading directly in the <head>, for example:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
{styles here}
</style>
</head>
<body>
<%= yield %>
</body>
</html>
Here is the controller code for how I'm resolving the layout:
class FoosController < ApplicationController
layout :resolve_layout
def show
end
private
def resolve_layout
case action_name
when 'show'
'foo'
else
'application'
end
end
end
The problem is, the application seems to cache the templates too heavily, and when I click through to a view that should be using the show template, I don't see those <head> styles without a refresh.
Am I handling this correctly, or is there a more "rails way" of doing this? What I'm really trying to accomplish here is having styles unique to a particular template only load with that single template. I think this may be an asset pipeline question, but I'm not sure, as I'm still new to Rails.

Seems like it was an issue with the styles living in the head. I had a relatively simple page, so I was able to move them to be inline styles, and the problem seems to be solved.

Related

How can I change a body tag ID based on the page title in rails?

Using Ruby on Rails (5) I want to use an if statement to change the ID of the body tag based on what view I am rendering.
Specifically I want to use a background image on my home page only, and not on any other. I want this to fill the screen, but if I put it on the page it's self it comes up with a border. So I want to attache it to the body tag in the application.html.erb view so the ID will tell CSS to load the background image. But I can't get the :title to tell ERB that it is there and make the statement true.
I am using provide on the view page as so:
<% provide(:title, "Home") %>
Then in the application.html.erb page I am trying to use an if statement to put in the body tag with or without the CSS ID for the background image based on the provided :title, like so:
<!DOCTYPE html>
<html>
<head>
<title><%= yield(:title) %></title>
...
</head>
<% if :title == "Home" %>
<body id="home-background">
<% else %>
<body>
<% end %>
But it doesn't seem to work. The title will 'yield' and display in the address bar, but not in the if statement. I have also tried to put the yield(:title) in a variable and rails didn't like that. This is my first solo rails project, and I know This should be possible, but I can't find how to do it correctly, any help would be appreciated.
i wont recommend you for the body tag...but you can use a wrapper just after the body for a background image...it can be like this:-
The only thing you will need is to create an instance variable(#title) to use below
###application.html.erb
<body>
<div class="<%= #title=="USER" ? 'user_wrapper' : 'default_wrapper' %>">
</div>
</body>
##css
.user_wrapper{
background: url(user_background.jpg) no-repeat center center fixed;
}
.default_wrapper{
background: url(default_background.jpg) no-repeat center center fixed;
}
HOPE IT HELPS.. :)

Ruby Layout Inheritance

I was wondering if there is any layout inheritance implementation in ruby.
In symfony, you can do this:
layoutmain.html
Give <head> and all that here
<body>
<h3>{{title}}</h3>
{{block view}}
<div class="row">
<div class="span3">
{{content}}
</div>
</div>
{{end block}}
</body>
layout2.html
{{inherits layoutman}}
{{block view}}
<div class="container">
Structure it differently
</div>
{{end block}}
So to speak, it let's you inherit the whole template and override parts for a different layout. So the scripts etc stay as they are in the main template, but you can change the view structure. So you can reuse bits of code in the first layout
I found some liquid inheritance project on github, but it looked outdated
I use the following approach to achieve "nesting" of layouts which is the form of layout inheritance that I've found to be most useful.
In the main application helper module app/helpers/application_helper.rb I define a helper method parent_layout:
module ApplicationHelper
def parent_layout(layout)
#view_flow.set(:layout, self.output_buffer)
self.output_buffer = render(:file => layout)
end
end
This helper is responsible for capturing the output of the current layout and then rendering the specified parent layout with the child layout inserted when the parent yields.
Then in my views I can set up the layout inheritance as follows. I start with my main application layout app/views/layouts/application.html.erb which is the child layout in this configuration:
<div class="content">
<h1><%= content_for?(:title) ? yield(:title) : 'Untitled' %></h1>
<div class="inner">
<%= yield %>
</div>
</div>
<%= parent_layout 'layouts/container' %>
The call to the helper method parent_layout specifies that application.html.erb is a child layout of container.html.erb. I then define the parent layout app/views/layouts/container.html.erb as follows:
<!DOCTYPE html>
<html>
<head>
<title>Sample</title>
</head>
<body>
<%= yield %>
</body>
</html>
The yield in container.html.erb yields to the "derived" (or child) layout application.html.erb, i.e. it inserts the output of rendering application.html.erb into the <body> of container.html.erb. Note that the parent_layout call needs to come at the end of the template since it captures the output of the layout up until the point at which it is invoked.
This is based on this article but updated to work in Rails 3.2 (and, hopefully, later). I haven't tried it in Rails 4, but you'll be able to get something similar working.
Ruby on Rails views have a feature called "partials". I partial is a view that generates a bit of html and can be included in other views. The partials can also accept arguments (local variables) that customize their behavior. The partials can include other partials.
This is probably a good place to start learning about that: http://guides.rubyonrails.org/layouts_and_rendering.html
I have never needed to do some kind of layout inheritance thing like you are describing but I could imagine doing it pretty easily with partials and passing around ruby variables that say which partial to use in which situation.

Rails - use code(css, js, html) from server on client side

I had a application rails built with bootstrap and simple form.
Here I have to show the UI patterns how they actually look like. That means I have to show the
patterns like menu bar, accordian patterns examples in my application. For that I am storing the pattern code html,css,js in database.
Here my requirement is I have to show the actual code pattern view from the stored record(css,js,html) without any css/js conflicts.
How can eneter the html,css,js code dynamically in a partial or page to show that
in a fancybox in rails.
Thanks for the help in advance.
just use html_safe or raw to render your content as a normal string on views. For instance:
in your controller:
#x = YOUR_CODE_FROM_DB
in your view:
<%= #x.html_safe %>
# <%= raw #x %> is also ok in this case
NOTICE: you can use html_safe on models, but raw is declared on a helper, so you can just use it on controllers and views.
-- edit --
more example:
on controller:
#hello = 'alert("hi");'
#body = 'body{ background: red; }'
on view:
<script type="text/javascript" charset="utf-8">
<%= raw #hello %>
</script>
<style type="text/css" media="all">
<%= #body.html_safe %>
</style>

Best way to include javascript in Rails via content_for

I have some pages in my Rails application that need one off bits of javascript to be included, ideally just before the </body> tag. There is no real need to have this javascript included on EVERY page since most don't use it. I've found a way to make this work, but I think the code is terrible.
How would you do the same thing or how would you refactor the existing code?
View simplified, sample code on gist.github.com:
https://gist.github.com/scottswezey/ffc7bf52041b976b710a
(Or see the same code below:)
application.html.erb (Layout):
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
...
<script>
$(function() {
<%= yield(:js) %>
});
</script>
</body>
</html>
some_view_file.html.erb (View):
<%
str = <<END_OF_STRING
$('.modal').modal()
END_OF_STRING
content_for :js do
str.html_safe
end
%>
Don't ever do it this way: JavaScript doesn't belong in HTML. Just put an appropriate <script> tag in the page, referring to an external JS file, something like this:
application.html.haml
!!!
%html
%head
= yield :javascript
%body
= yield
view file
- content_for :javascript do
= javascript_include_tag 'modal'
app/assets/modal.js
$(document).ready(function() {
$('.modal').modal();
}
This keeps everything nicely separated.
Is it possible to add a .js.erb partial with your JS and render it under the body?
edit: Check out this answer: https://stackoverflow.com/a/10113547/1283742

Grails "render" renders the template

In my Grails controller I'm responding to an AJAX call and using render to return the text:
def ajaxRandomPersonName = {
def person = get a random person ...
render "Name: ${person.name}"
}
The problem is that render renders the whole template. So instead of just rendering "Name: John" it renders all the icons, navigation, etc defined in the template. How do I get render to just render without the template?
I'm pretty much following Chapter 1 of "Grails in Action" (page 28) using Grails 1.1.1.
Follow up:
Returning false per Rhysyngsun's suggestion has no impact. I also tried setting the template to null but it still renders the template:
def ajaxRandomPersonName = {
def person = get a random person ...
render (template:null, text:"Name: ${person.name}")
}
render has its heart bent on rendering it through the template no matter what I do.
Follow up 2: Parallel discussion on grails-user mailing list.
Follow up 3: Sample code:
I paired down my code the bare minimum and it still exhibits the undesired template rendering.
controllers/PersonController.groovy:
class PersonController {
def index = { }
def home = { [message:"Hello"] }
def ajaxTest = {
println "ajaxTest called"
render text: "ajax message"
}
}
views/person/home.gsp (view page for home method)
<html>
<head>
<title>Home View</title>
<g:javascript library="prototype" />
</head>
<body>
<p>
<g:remoteLink action="ajaxTest" update="test1">ajax call</g:remoteLink>
</p>
<p>Message = ${message}</p>
<p id="test1">Blank</p>
</body>
</html>
views/layouts/person.gsp (layout template for person controller)
<html>
<head>
<title>Test App - <g:layoutTitle/></title>
<g:layoutHead/>
</head>
<body>
<h1>Test App</h1>
<g:layoutBody/>
</body>
</html>
I access person controller with the home view:
http://localhost:8080/test/person/home
the page renders as:
Test App
ajax call (hyperlink)
Message = Hello
Blank
"Test App" is from the template. When I click "ajax call" it makes an asynchronous call to PersonController's ajaxTest method (verified with println). All ajaxTest does is println and render static text. This resultant in the following:
Test App
ajax call
Message = Hello
Test App
ajax message
Note that the template is being rendered within "test1" <p> which results in the second "Test App".
I'm running Grails 1.1.1. Any ideas? The code seems straightforward. I downloaded the Grails source and looked at RenderDynamicMethod.java. It doesn't do any template rendering unless template is in the argument list, which it isn't. So my only guess is something up steam is rendering the template again.
Resolved: Adding contentType results in the template not being rendered:
render text: "Name: ${person.name}", contentType: "text/plain"
Make your client side javascript code handle a JSON respond and render your response with:
render [text:"Name: ${person.name}"] as
JSON
You might be getting burnt by the 'layout-by-convention' feature in Grails. If your layout name matches the controller name prefix, for example, Grails will apply the layout to every view managed by that controller. Unfortunately, it even applies to text and templates. There are currently a few JIRAs logged regarding this (see http://jira.grails.org/browse/GRAILS-7624 for example).
I got burnt by this today. I resolved it by simply renaming my layout gsp such that it doesn't match any controller name. My layout was initially named 'storefront.gsp' and I have a controller named StorefrontController. I renamed the layout to 'public.gsp'.
We've found that explicitly returning false from the action fixes this.
I believe doing render foo as JSON returns false implicitly.

Resources