In my controller I have this method that retuns to me the list of specific books controller/books_controller
def postings
#books = Book.postings(current_user.id).order("created_at ASC")
render :partial =>'postings'
end
I have a partial in views/books/_postings.html.erb
<div class="container">
<h4>My Partial Postings</h4>
<% #books.each do |book| %>
<div class="row">
<div class="col-sm-2"><img src="<%= book.image_path %>" alt="..." class="img-responsive"/></div>
<div class="col-sm-10">
<h4 class="nomargin"><%= book.title %></h4>
<p><%= book.description %></p>
<p>Quantity: <%= book.quantity %></p>
<p>Available for: <%= book.sale_type %></p>
</div>
</div>
<hr>
<% end %>
</div>
In my routes :
resources :books do
collection do
get 'postings'
end
end
on running rake routes :
postings_books GET /books/postings(.:format) books#postings
When I use localhost:3000/books/postings I get the desired partial showing list of books .But when I want to call this partial from some other view eg from localhost:3000/dashboard/index:
<div class="tab-pane" id="postings">
<%= render 'books/postings', :collection => #books %>
</div>
I get the following error:
Showing /home/swati/867/WorkSpace2/assignment_3/app/views/books/_postings.html.erb where line #4 raised:
undefined method `each' for nil:NilClass
Extracted source (around line #4):
<div class="container">
<h4>My Partial Postings</h4>
<% #books.each do |book| %>
<div class="row">
<div class="col-sm-2"><img src="<%= book.image_path %>" alt="..." class="img-responsive"/></div>
<div class="col-sm-10">
I understand that render is just rendering the partial without calling my method postings in books_controller and my partial has no access to #books , which is nil. How can aprroach this ?
When you access dashboard/index you are actually calling index method of dashboards_controller. If you would like to render the books/postings partial there, you need to add the list of books (#books) in that controller too.
More info here: http://guides.rubyonrails.org/action_controller_overview.html
Related
i've been working on new app it's like IMDB and i added category model which it works fine with the association but i'm having problem in Displaying movies by category in category controller:
def show
#category = Category.find(params[:id])
#category_movies = #category.movies
end
in the category show page:
<h align = "center"><%= "Category: " + #category.name %></h1>
<%= render 'movies/movies', obj:#category_movies %>
and in index i did:
<div class= "row">
<% #movies.each do |movie|%>
<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<%= link_to (image_tag movie.image.url(:medium), class: 'image'), movie %>
</div>
</div>
<% end %>
</div>
so i got an error undefined method `each' for nil:NilClass
any ideas
in your partial, you use #movies but in the controller, you are calling it #category_movies - you will need to use the same variable name, or use local variables.
eg with local variables:
<%= render 'movies/movies', :movies => #category_movies %>
# and in the partial
<% movies.each do |movie|%>
Note: not tested for bugs and typos...
Instance variable #category_movies must be the same in the controller and in the views :)
#movies is not declared so it's nil !
On my views I use 1 form that includes a block that renders comments. I do not want to run it when creating a new record. So, I tried conditions like so...
<% unless #annotation_id.nil? %>
<hr>
<div class="row">
<div class="col-md-8">
<h4>Comments</h4>
<%= render #annotation.comments %>
</div>
<div class="col-md-4">
<%= render 'comments/form' %>
</div>
</div>
<% end %>
This however results in never displaying the block - also when the annotation record exists. What am I doing wrong?
You don't show that you have actually set #annotation_id to something.
A simpler way might be to use the .new_record? method instead, like:
<% unless #annotation.new_record? %>
...
<% end %>
use if #annotation.persisted? or unless #annotation.new_record?
Adding a "latest post" section to blog
This is my original code to show all my posts and it works great.
<% #post.each do |post| %>
<div class="col-md-4 col-sm-6 portfolio-item">
<a href="#portfolioModal6" class="portfolio-link" data-toggle="modal">
<div class="portfolio-caption">
<h4><%= link_to post.title, post %></h4>
<p class="text-muted"><%= post.created_at.strftime("%B, %d, %Y") %></p>
</div>
</a>
</div>
<% end %>
However, I also want to add a large div that shows my latest post. So I copy/paste the code above and changed the line <% #post.each do |post| %>to the following:
<% #post = Post.last do |post| %>
There was no errors, but nothing showed up either. The reason I added this code is because I saw in a tutorial where the teacher went into rails c and typed #post = Post.last and could see the last post created. However, when I go into terminal and type it, I get the error:
No command '#post' found, did you mean:
Command 'mpost' from package 'texlive-binaries' (main)
Command 'rpost' from package 'suck' (universe)
#post: command not found
You shouldn't type it on your terminal, but in the rails console. On your terminal, type rails console, when that loads up, you can then do:
post = Post.last
In order to only render for the last post, you wouldn't need the block, as such:
<% post = Post.last %>
<div class="col-md-4 col-sm-6 portfolio-item">
<a href="#portfolioModal6" class="portfolio-link" data-toggle="modal">
<div class="portfolio-caption">
<h4><%= link_to post.title, post %></h4>
<p class="text-muted"><%= post.created_at.strftime("%B, %d, %Y") %></p>
</div>
</a>
</div>
By the way, it's not best practice to handle domain objects in your view. You could have this as an instance variable in your controller, as a Facade object if you have multiple objects.
Extending #oreoluwa's answer with a little more rails conventions:
Your post object:
class Post < ActiverRecord::Base
scope :ordered, -> { order(created_at: :desc) } # or use your own column to order
end
Your Controller (where your view is where the last post should be rendered). You should not make queries in your views to keep better a better control.
class ExamplesController < ApplicationController
def show
#latest_post = Post.ordered.first
end
end
Your View
<div class="col-md-4 col-sm-6 portfolio-item">
<a href="#portfolioModal6" class="portfolio-link" data-toggle="modal">
<div class="portfolio-caption">
<h4><%= link_to #latest_post.title, #latest_post %></h4>
<p class="text-muted"><%= #latest_post.created_at.strftime("%B, %d, %Y") %></p>
</div>
</a>
</div>
I am using a bootstrapping framework, that has the following snippet, which I use a lot:
<div class="panel panel-default">
<div class="panel-heading">...</div>
<div class="panel-body">
...
</div>
</div>
(The snippet will be actually bigger, but I want to start small)
So I thought I would build a partial and use it, something like this:
Partial
<div class="panel panel-default">
<div class="panel-heading"><%= title %></div>
<div class="panel-body">
<%= yield %>
</div>
</div>
Use example
<%= render partial: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
But this apparently is not working. I get the following error:
'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path.
Am I doing something wrong here? Did I understood partials wrong?
In order for yield to work I think you need to use render :layout instead of/in addition to :partial:
<%= render layout: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
Have a read of the PartialRenderer examples for more information
Iterating over 'posts' I want to create a row div which will contain two post divs:
<div id="row">
<div id="post"> ... </div>
<div id="post"> ... </div>
</div>
<div id="row">
<div id="post"> ... </div>
<div id="post"> ... </div>
</div>
If I try this:
- #posts.each_with_index do |post,index|
- if index %2 == 0
.row
.post
- else
.post
...then I get:
<div class="row">
<div class="post"></div>
</div>
<div class="post"></div>
<div class="row">
<div class="post"></div>
</div>
<div class="post"></div>
I can see why this happens but I can't figure out how to do it correctly. Any ideas?
UPDATE:
When accessing object attributes as per apneadiving's suggesion, I receive errors when the last slice contains only a single post. For example, the following...
- #posts.each_slice(2) do |post1, post2|
.row
.post= post1.title
.post= post2.title
returns the error "undefined method `title' for nil:NilClass" when there are an odd number of posts. To get around this I have used this:
- #posts.each_slice(2) do |post1, post2|
.row
.post= post1.title
.post= post2.title unless post2.nil?
I'd take my posts 2 by 2, I can't see how to do otherwise with haml:
- #posts.each_slice(2) do |post1, post2|
.row
.post= post1
.post= post2
For tasks like this i prefer to use erb templates, that adds more flexibility, use it and you will see that your problem will solve so easy. Structuring of haml imposes some restrictions on the tasks implementation.
<% #posts.each_with_index do |post, index| %>
<% if index %2 == 0 %>
<div class="row">
<% end %>
<div class="post></div>
<% if index %2 != 0 %>
</div>
<% end %>
<% end %>