Kaminari & Rails pagination - undefined method `current_page' - ruby-on-rails

I searched and searched, but nothing solved my problem. Here's my controller:
def show
#topic = Topic.find(params[:id])
#topic.posts = #topic.posts.page(params[:page]).per(2) # 2 for debugging
end
That functions just fine, because the topic view is reduced to two posts. However, when I add this to show.html.erb:
<%= paginate #topic.posts %>
I'm given this error:
undefined method `current_page' for #<ActiveRecord::Relation:0x69041c9b2d58>

Try with:
def show
#topic = Topic.find(params[:id])
#posts = #topic.posts.page(params[:page]).per(2)
end
And then:
<%= paginate #posts %>

If you get pagination errors in Kaminari like
undefined method `total_pages'
or
undefined method `current_page'
it is likely because the AR scope you've passed into paginate has not had the page method called on it.
Make sure you always call page on the scopes you will be passing in to paginate!
This also holds true if you have an Array that you have decorated using Kaminari.paginate_array
Bad:
<% scope = Article.all # You forgot to call page :( %>
<%= paginate(scope) # Undefined methods... %>
Good:
<% scope = Article.all.page(params[:page]) %>
<%= paginate(scope) %>
Or with a non-AR array of your own...
Bad:
<% data = Kaminari.paginate_array(my_array) # You forgot to call page :( %>
<%= paginate(data) # Undefined methods... %>
Again, this is good:
<% data = Kaminari.paginate_array(my_array).page(params[:page]) %>
<%= paginate(data) %>

Some time ago, I had a little problem with kaminari that I solved by using different variable names for each action.
Let's say in the index action you call something like:
def index
#topic = Topic.all.page(params[:page])
end
The index view works fine with <%= paginate #topic %> however if you want to use the same variable name in any other action, it throu an error like that.
def list
# don't use #topic again. choose any other variable name here
#topic_list = Topic.where(...).page(params[:page])
end
This worked for me.
Please, give a shot.

Related

undefined method `each' for nil:NilClass - but only when rendering on homepage

I have a model Person and I want to list all 'people' on the home page of my website.
I created a partial _index.html.erb for this, so I could use this list everywhere on my website. On index.html.erb, I render this partial.
Now both http://localhost:3000/people/ and http://localhost:3000/people/index run fine. However, I also wanted to use the index partial on my home page. There, it gives the following error:
undefined method `each' for nil:NilClass
Some parts of my code:
people/_index.html.erb
<h2>The following people exist:</h2>
<table>
<tr>
<th>Name</th>
</tr>
<% #people.each do |p| %>
<tr>
<td><%= p.name %></td>
</tr>
<% end %>
</table>
people/index.html.erb
<%= render 'people/index' %>
pages/index.html.erb (This is my home page)
<h1>Homepage</h1>
<%= render 'people/new' %>
<%= render 'people/index' %>
routes.rb:
Rails.application.routes.draw do
root 'pages#index'
get 'pages/index'
get 'people/index'
resources :people
end
Part of people_controller.rb:
class PeopleController < ApplicationController
def index
#people = Person.all
end
def show
#person = Person.find(person_params)
end
...
Somehow, rendering people/new (also a partial) works perfectly fine if I comment out <%= render 'people/index' %>.
Searching for this error leads mainly to the solution "you didn't properly define #people in the controller". However, why does it then work fine on the /people/index page but not when rendering it on the homepage? Is it a routing issue?
I hope that my question is clear and that I posted enough code snippets, thanks in advance for your help!
Your PagesController, which is called when you hit the pages/index route when rendering the homepage, doesn't have #people defined, so #people ends up being nil, and the error occurs.
You need to add #people = People.all somewhere in your PagesController, since PeopleController doesn't actually get called when you access the homepage.
If you check your development.log you will see PeopleController does not get called when you access the homepage and the people/_index partial renders.
undefined method 'each' for nil:NilClass means that you are calling each on something you think is there, but isn't. In this case your calling #people.each, but #people is actually nil. So you see that error. In your controller set #people = People.all in the action/method that is actually fueling that page. So if you are on the show page, it would go in the show method. On the edit page, makes sure that code is in the edit method.

How to display the created_at in words in an article on Rails

I'm new into coding and even more new with Rails.
I'm trying to create a simple blog application, I've the articles list on the index with their title, content and created at (I used time_ago_in_words for this) however, when I try to use it inside the show view of an article it returns me an error.
With <%= #article.created_at(time_ago_in_words) %> it returns
wrong number of arguments (0 for 1..2) on the line
<span class="meta">Posted by Author <%= #article.created_at(time_ago_in_words) %></span>
With <%= #article.time_ago_in_words(article.created_at) %> it returns
undefined local variable or method `article' for #<#:0xb4ba430c> on the line
<span class="meta">Posted by Author <%= #article.time_ago_in_words(article.created_at) %></span>
My articles controller
class ArticlesController < ApplicationController
def index
#articles = Article.all.order("created_at DESC")
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
end
So I would like to know what is the properly way to display the created_at date but in words, because if I use <%= #article.created_at %> it works fine but the date it returns something like 2015-08-17 15:49:11 UTC which doesn't seems good.
Any help is highly appreciated.
The correct syntax is <%= time_ago_in_words(#article.created_at) %>

undefined method `each' for nil:NilClass when rendering from a different view

Every time I try to render something that is located from a different view, I get a NoMethodError: undefined method `each' for nil:NilClass.
It happens when I put the following code in the view I want to render stuff on:
views/uploads/myuploads.html.erb
<%= render template: 'guitar_sounds/index' %>
And it tells me that the error seems to be in a particular block of code where the template is located:
views/guitar_sounds/index.html.erb
<% #guitar_sounds.each do |sound| %> <!-- Error here -->
<%= render "guitar_sound", sound:sound %>
<% end %>
However, when I load that page view on its own, I get no errors.
Can someone help me?
Loading a partial does not automatically hit a controller method. By that, it sounds like the only controller method being run is uploads#myuploads, but your #guitar_sounds variable is being defined in guitar_sounds#index. I'd simply define the #guitar_sounds variable in your UploadsController
UploadsController < ApplicationController
def myuploads
# here is where #guitar_sounds needs to be defined
#guitar_sounds = GuitarSound.all
end
end
Let's say you needed #guitar_sounds in lots of methods, you could define it in a before_action
UploadsController < ApplicationController
before_action :set_guitar_sounds
def myuploads
# normal controller code
end
private
def set_guitar_sounds
#guitar_sounds = GuitarSound.all
end
end
Now #guitar_sounds will be set for every method in the UploadsController
Your template guitar_sounds/index expects #guitar_sounds to be defined, and be able to iterate over its items.
If you reuse the template without assigning any values to #guitar_sounds, by default it will be nil, thus you can see the error.
Hope it clarifies a bit the problem!
guitar_sounds/index expects #guitar_sounds to be defined, aka, not nil, so it can iterate over its items.
You should, instead, use local variables.
<%= render template: 'guitar_sounds/index', guitar_sounds: #guitar_sounds %> #or other # variable
And at your view:
<% guitar_sounds.each do |sound| %>
<%= render "guitar_sound", sound:sound %>
<% end %>
Now guitar_sounds (note the missing #) is a local variable that you pass to the render function!
EDIT: Check rails documentation about this: Passing Local Variables to partials/templates.

Accessing first row in an object

<% question = #questions.try(:first) %>
<h1><%= question.title %></h1>
I'm trying to use the above code to grab the first question from a Questions model, and then display it's title in HTML. However, I'm throwing the error undefined method 'title' for nil:NilClass
Autogenerated RoR files use the question.title line... why isn't it working here?
question.title raises error as undefined method 'title' for nil:NilClass that means question is set as nil. You set question using
<% question = #questions.try(:first) %>
It means either #questions is nil or there #questions.first returns nil.
Make sure that you set #questions instance variable in the Controller's action which renders this particular view.
def action_name
#questions = Question.all
end
Also, if you just want to show only the first question record in your view and you are not going to use #questions anywhere then just set
def action_name
#question = Question.first
end
and use it in the view directly as:
<h1><%= #question.try(:title) %></h1>
It looks like #question is nil. Have you assigned #question in your controller action. Can you show your code in your controller action?

undefined method 'each' Ruby on Rails

Apologies in advance, I am a newbie trying to get my head around rails.
My View at the bottom works when I use:
def show
#posts = Post.all
end
However in my controller I now have:
def show
#posts = Post.find_by_category_id params[:id];
end
In my view I have
<%= #posts.each do |post| %>
<%= post.title %>
<% end %>
Some please explain why I get this error. What should I use. category_id is a foreign key on the Post table.
Look at http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find_by
Finds the first record matching the specified conditions
find_by_ will return only one post, not a collection. So you are not able to use each.
try
def show
#posts = Post.all.find_by_category_id params[:id];
end

Resources