can view not extend "application/application.html.erb" in ruby on rails? - ruby-on-rails

As we all know, in ruby on rails, all views extends from application/application.html.erb, most of the time this is great, such as the application.html.erb as follow:
<html>
<head></head>
<body>
<%= render 'layouts/header' %>
<%= yield %>
</body>
</html>
I do not need the write the same code in every view again, but sometimes, just on view is special, this view is different from the view, such as I do not want to add <%= render 'layouts/header' %> in this view.
Maybe a parameter will just help me in this situation, but I want to know if any view is able to not extend from application/application.html.erb?

Views don't 'extend from' application.html.erb, they use it as a default layout. You can change it, of course, using layout method in controller (or layout option in render method), like this:
# this changes the default layout in every views of `AdminController` (and all other controllers that inherit from `AdminController`):
class AdminController < ApplicationController
layout :admin
# ...
end
# this changes the layout of specific action:
class SomethingController < ApplicationController
# ...
def some_action
# ...
render layout: :some_layout
end
end
Here's the reference:
http://guides.rubyonrails.org/layouts_and_rendering.html

Related

Shared resource for partial in Rails

Premise: I'm quite new to Rails. I'm trying to render a partial in the application layout that will have to display some Event objects. The partial will have to be displayed in every page of the application (it's basically a sidebar). I am aware that I should pass a local variable to the partial, like
<%= render partial: "shared/aside", locals: {events: #events} %>
But this will only work if I define #events in every single controller of the application. Is there a way of setting it globally?
It might be worth noting that events might not be the only resource needed to the partial.
You could do a before action in the application controller. The before action would go at the top of the file, the private method at the bottom
class ApplicationController < ActiveController::Base
# Place at top of file
before_action :set_events
...your other code...
# Place at bottom of file
private
def set_events
#events = Event.all
end

Rails Override Render

Is it possible to override Rails' render behavior for :html responses? I'd like to always render the same template (ignoring the magic view finding).
I'm writing a single page app, and this seems like it should be possible...basically if it's requested as :json it should render JSON, but if it's requested as :html it should pass the data on to the same view no matter what (where it will be rendered as JSON in the body).
Try to delete the yield part on your application.html.erb, then you will alway get the application.html.erb without any partials.
What if you define one single view and then after every action on every controller you render that view? Like this:
app/controllers/home_controller.rb
class HomeController < ApplicationController
def home
end
end
app/views/home/home.html.erb
<!-- Whatever html code and script tags here -->
app/controllers/another_controller.rb
class AnotherController < ApplicationController
def action
render "home/home"
end
end
You could even define an after_filter
Edit
I tried this and it works. The after filter doesn't seem to work though.
Why not pass the JSON data as an instance variable?
controller
#json_data = whatever_model.to_json
application.html.erb
<script>
<%= #json_data %>
</script>

Undefined method when creating a helper in Rails

I tried to create a helper module to be able to set the title of a page. Of course it's not working (reference) Is there something I must define in a controller for my helpers methods to be seen by my controllers??
Gitlink: works_controller.rb
def index
set_title("Morning Harwood")
#works = Work.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #works}
end
end
In application_helper.rb:
module ApplicationHelper
def set_title(title = "Default title")
content_for :title, title
end
end
In the layout work.html.erb:
<%= content_for?(:title) ? content_for(:title) : 'This is a default title' %>
Helpers in Rails are methods available in views (and controllers if you include them) that allow you to avoid code repetition in views.
An example of a helper from my code is a method that renders html for facebook login button. This button is in reality more than user sees, because it's a hidden form with some additional information, etc. For this reason I wanted to make a helper method out of it, so instead of copying 10 lines of code multiple times I can call a single method. This is more DRY.
Now, back to your example, you want to do two things
display page <title>,
add <h1> header at the top of the page.
I see now where linked answer wasn't clear enough. You indeed need helper, but you also need to call it! So
# application_helper.rb
def set_title(title = "Default title")
content_for :title, title
end
# some_controller.rb
helper :application
def index
set_title("Morning Harwood")
end
And then in layout's views you can use:
<title> <%= content_for?(:title) ? content_for(:title) : 'This is a default title' %><</title>
...
<h1><%= content_for?(:title) ? content_for(:title) : 'This is a default title' %></h1>

Render partial template base on condition in Ruby on Rails

I have 2-column layout. Some controller has left column, some not. What is the best way to render it depend on controller? Now, it look likes that:
<% if params[:controller] != 'page' %>
<div id="navigation" class="l"><%= render "layouts/left-menu" %></div>
<% end %>
It's bad, bad monkey code.
Edit: Changed my solution, OP wanted condition to depend on action and controller.
In your base helper, define a method like this:
# app/helpers/application_helper.rb
module ApplicationHelper
def has_left_menu?
#has_left_menu.nil? ?
true : # <= default, change to preference
#has_left_menu
end
end
In your application controller:
# app/controllers/application_controller.rb
class ApplicationController
def enable_left_menu!
#has_left_menu = true
end
def disable_left_menu!
#has_left_menu = false
end
end
In your view or layout, change your check to this:
<% if has_left_menu? %>
<div id="navigation" class="l"><%= render "layouts/left-menu" %></div>
<% end %>
Now you can disable/enable the left menu in before_filters or anywhere else in your action:
class UsersController < ApplicationController
# enable left menu for "index" action in this controller
before_filter :enable_left_menu!, :only => [:index]
# disable left menu for all actions in this controller
before_filter :disable_left_menu!
def index
# dynamic left menu status based on some logic
disable_left_menu! if params[:left_menu] == 'false'
end
end
In your controller you use layout like this
#PublicController is just an example
class PublicController < ApplicationController
layout "left-menu"
end
And in the views/layouts folder you put the left-menu.html.erb
with a stylesheet_link_tag to your spesific css file
<%= stylesheet_link_tag 'left-menu' %>
You can learn more at rails guides

Is it possible to use partials with the layout option inside of a controller?

When try I following code in a controller, the view renders without using the layout
def xyz
render :partial => 'platinum_home', :layout => 'platinum_layout'
end
But If I do the following inside the partial
<% render(:layout => "platinum_layout") do %>
blah blah blah
<% end %>
It works just fine, is the first example not possible using rails?
In your controller at the top add the following:
class SomeController < ApplicationController
layout "platinum_layout", :only => :xyz
Partial rendering in a controller is most commonly used together with Ajax calls that only update one or a few elements on a page without reloading. Rendering of partials from the controller makes it possible to use the same partial template in both the full-page rendering (by calling it from within the template) and when sub-page updates happen (from the controller action responding to Ajax calls). By default, the current layout is not used.
So to use current layout for your just used.
def xyz
render :partial => 'platinum_home', :layout => true
end

Resources