How to use the default layout for nested controller? - ruby-on-rails

Pretty new to rails and I was building my routes to get a nested controller like this:
resources :companies do
member do
get 'operating_hour'
end
resources :services do
member do
get 'services'
end
end
end
Now, my layout for my applications is like this:
<body>
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
<% if main_side_view? %>
<%= render 'layouts/main_side' %>
<% elsif company_side_view %>
<%= render 'layouts/company_side' %>
<% else %>
<h1><%= yield(:title) %></h1>
<%= yield %>
<% end %>
<%= render 'layouts/footer' %>
</div>
All is working fine with my layout except all that is generated by the nested ('service') controller. When I go to a link of the nested controller my layout is not there!
Any help?

I think you do it in a wrong way. You should create several layouts :
First, layouts/application.html.erb
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
<h1><%= yield(:title) %></h1>
<%= yield %>
<%= render 'layouts/footer' %>
</div>
Second, layouts/companies.html.erb
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
Your code for companies
</div>
See the guide : http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts
You can create a shared view for flash messages.

Related

Issue With "Do In Groups of" In Ruby on Rails

I have the following code to display posts in groups of 3 across the page:
<% if #feed_items.any? %>
<% #feed_items.in_groups_of(3).each do |feeds| %>
<div class="row">
<% feeds.each do |feed| %>
<div class="col-md-4">
<ol class="posts">
<%= render feed %>
</ol>
</div>
<% end %>
</div>
<% end %>
<% end %>
It works fine if there are a number of posts that is evenly divisible by 3, however anything not (like 10 posts for example) generates the error "'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path."
Essentially I just want to display my posts so they look like:
Post 1 Post 2 Post 3
Post 4 Post 5
Is there a way to do this with my current code or can someone suggest a non Ruby way of doing this, for example SCSS.
Thanks!
Use Array#compact to remove the nil values:
<% if #feed_items.any? %>
<% #feed_items.in_groups_of(3).each do |feeds| %>
<div class="row">
<% feeds.compact.each do |feed| %>
<div class="col-md-4">
<ol class="posts">
<%= render feed %>
</ol>
</div>
<% end %>
</div>
<% end %>
<% end %>

Rails: How to Render Conditional Based Upon 'pages/home.html.erb'

In the tbody section of application.html.erb I wanted to render for the current_user two sidebars if he is on the home page and just one sidebar for every other page.
<body>
<% if current_user.present? %>
<% if 'pages/home.html.erb' %> # Not Working As a Conditional
<div class="container">
<div class="col-md-3">
<%= render 'layouts/valuations' %>
</div>
<div class="col-md-6">
<% flash.each do |name, msg| %>
<%= content_tag(:div, msg, class: "alert alert-info") %>
<% end %>
<div id="modal-holder"></div>
<%= yield %>
</div>
<div class="col-md-3">
<%= render 'layouts/sidebar' %>
</div>
</div>
<% else %>
<div class="container-fluid">
<div class="container">
<div class="col-md-9">
<% flash.each do |name, msg| %>
<%= content_tag(:div, msg, class: "alert alert-info") %>
<% end %>
<div id="modal-holder"></div>
<%= yield %>
</div>
<div class="col-md-3">
<%= render 'layouts/sidebar' %>
</div>
</div>
</div>
<% end %>
<% else %>
<div class="container">
<% flash.each do |name, msg| %>
<%= content_tag(:div, msg, class: "alert alert-info") %>
<% end %>
</div>
<%= yield %>
<% end %>
</body>
Firstly, you're looking for current_page?:
<% if current_page?(controller: "pages", action: "home") %>
...
<% end %>
This is notoriously rickety though (what happens if you change your pages controller?).
What you'll be better doing is what beartech suggested, setting a variable which you can ping in your layout:
#app/controllers/pages_controller.rb
class PagesController < ApplicationController
def home
#home = true
end
end
#app/views/layouts/application.html.erb
<if #home %>
...
<% end %>
I would match this with the use of partials:
#app/views/layouts/application.html.erb
<%= render "shared/sidebar" if #home %>
<%= render "shared/flash" %>
This gives you the ability to split your code into more manageable chunks. We do it here:
In your :index action for your home page you can set a variable like:
def index
#home_page = true
...
And then you can just do something like:
<body>
<% if current_user.present? %>
<% if #home_page %>
<div class="container">
<div class="col-md-3">
<%= render 'layouts/valuations' %>
</div>

Undefined method each with nested resources

I'm trying to follow Ryan Bates Polymorphic association tutorial in order to put some comments to my site.
The thing is I have nested resources:
#Nesting Resources
resources :users do
resources :photos do
resources :comments
resources :tags
end
end
So I'm getting an error in my view (photos/show)
undefined method `each' for nil:NilClass
I suppose the problem is in my controller, with comments, that is not defined correctly, but since I have nested resources, I don't know how to do it.
Photos Controller
def show
#photo = Photo.friendly.find(params[:id])
#user = #photo.user
#commentable = #photo
#comments = #commentable.comments
#comment = Comment.new
end
New Comment Partial
<h2>Comments</h2>
<% if #comments.any? %>
<%= render "comments/comments" %>
<% else %>
TodavĂ­a no hay comentarios
<% if user_signed_in? %>
<%= render "comments/form" %>
<% end %>
<% end %>
Form partial (comments/form)
<%= form_for [#commentable, #comment] do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h2>Please correct the following errors.</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_area :content, rows: 8 %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Comments partial (comments/comments)
<div id="comments">
<% #comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
</div>
Your error says undefined method each for nil:NilClass. As you can guess you are calling each on a nil object. Here your #comments is nil and hence giving your trouble.
In your view try something like this:
<div id="comments">
<% if #comments %>
<% #comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
<% end %>
</div>
Edit:
So if you look at your code you have #comments till here:
<% if #comments.any? %>
<%= render "comments/comments" %>
<% else %>
#do stuff
<% end %>
it's after you call your partial that your #comment is lost so try this:
<% if #comments.any? %>
<%= render "comments/comments", comments: #comment %>
<% else %>
#do stuff
<% end %>
and then in your view use
<div id="comments">
<% comments.each do |comment| %>
<div class="comment">
<%= simple_format comment.content %>
</div>
<% end %>
</div>

Control Structure in Rails Partial

I'm building a Rails app up from the Sample App featured in Michael Hartl's book. In order to display error messages on user signup, I'm using a partial in the shared directory - app/views/shared/_error_messages.html.erb:
<%if #fact %>
<% #data = #fact %>
<% elsif #user %>
<% #data = #user %>
<% end %>
<% if #data.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(#data.errors.count, "error") %>.
</div>
<ul>
<% #data.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Originally, this partial just started with something like:
<% if #user.errors.any? %>
However, since I've decided to re-use this partial to show errors on other pages, I'm having to use different objects (#user, #fact) depending on which page I'm using it on. This is easily solved by adding that IF statement at the top,
<%if #fact %>
<% #data = #fact %>
<% elsif #user %>
<% #data = #user %>
<% end %>
-but this feels icky. Is there a controller somewhere I should be putting this kind of logic for shared partials?
You can pass local variables to partial instead:
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
And in your template, for example:
<%= render 'shared/error_messages', object: #user %>
Marek's answer is probably the best. However, here is an alternative which though not scalable, is closer to what you have done.
Just replace:
<%if #fact %>
<% #data = #fact %>
<% elsif #user %>
<% #data = #user %>
<% end %>
with:
<% #data = #fact||#user %>
You could use render to point to the partial from your controllers for users and fact. Check out the API documentation on rendering partials.

Railstutorial: Putting flash messages in partial yields error "undefined method `each' for nil:NilClass"? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Flash Messages in Partials (Rails 3)
I am doing Michael Hartl's Railstutorial and listing 7.26 adds flash messages to the application layout:
<!DOCTYPE html>
<html>
.
.
.
<body>
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>"><%= value %></div>
<% end %>
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
.
.
.
</body>
</html>
This works fine.
However, I tried to clean up this code by creating a _flash.html.erb in my partial folder...
<% flash.each do |key,value| %>
<%= content_tag(:div, value, class: "alert alert-#{key}") %>
<!-- <div class="alert alert-<%= key %>"><%= value %></div> -->
<% end %>
...and than using...
<%= render 'partials/flash' %>
...in my application layout all my Rspec tests start failing with the following message for each test:
Failure/Error: before { visit signup_path }
ActionView::Template::Error:
undefined method `each' for nil:NilClass
The key issue seems to be that flash is nil because wrapping my _flash partial in an if statement like this...
<% unless flash.empty? %>
<% flash.each do |key,value| %>
<%= content_tag(:div, value, class: "alert alert-#{key}") %>
<!-- <div class="alert alert-<%= key %>"><%= value %></div> -->
<% end %>
<% end %>
... yields the same error message about NilClass as above and wrapping it in an if statement like this...
<% if flash %>
<% flash.each do |key,value| %>
<%= content_tag(:div, value, class: "alert alert-#{key}") %>
<!-- <div class="alert alert-<%= key %>"><%= value %></div> -->
<% end %>
<% end %>
... breaks the flash messages from working (because 'if flash' is always false).
I have two related questions:
Why/how exactly does using the partials/flash solution change the behavior of a rails app?
How to change my partials/flash so it will work?
Thanks!
Set locals with a hash of params/values to pass to the partial
<%= render :partial => "partials/flash", :locals => {:flash => flash} %>

Resources