Undefined method 'each' for nil:NilClass, for #topics - ruby-on-rails

I am trying to display a content on a page. I have:
index.html.erb
<if !user_signed_in? %>
<%= link_to 'Download Topics', resumes_url, :class => 'btn btn-danger' %>
<%= form_tag topics_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search" %>
<% end %>
<% #topics.each do |topic| %>
<div class="topic">
<h3><%= topic.title %></h3>
<p><%= topic.id %></p>
<p class="text-justify" ><%= topic.body %></p>
<p><%= topic.date %></p>
<%= image_tag topic.image.url, class: "topic-show" if topic.image? %>
</div>
<% if current_user && current_user.admin? %>
<%= link_to "Edit", edit_topic_path(topic), :class => 'btn btn-default' %>
<%= link_to "Destroy", topic, :class => 'btn btn-default', method: :delete, data: {confirm: 'Are you sure?'} %>
<% end %>
<%= link_to "Show", topic_path(topic), :class => 'btn btn-default' %>
<% end %>
<div>
<%= will_paginate #topic, renderer: BootstrapPagination::Rails %>
</end>
topics_controller.rb, index action
class TopicsController < ApplicationController
before_action :authenticate_user!, except: [:show, :index, :update, :destroy]
def index
#topics = Topic.search(params[:search]).paginate(:page => params[:page], :per_page => 5
#topics = Topic.all
end
end
And I received an error
undefined method `'each'` for `nil:NilClass`
The error is thrown at <% #topics.each do |topic| %>.
I am unsure what to do. I have tried to add:
#topics = Topic.all
to topics#index, but that does not seem to resolve the issue.

This error just means that #topics is empty.
To troubleshoot this, you need to refresh the page while watching your console.
Examine the queries being ran when these lines run:
#topics = Topic.search(params[:search]).paginate(:page => params[:page], :per_page => 5
#topics = Topic.all
If you can't spot the issue in the console, copy the query into your database GUI and run the query, modify it till you get your expected results and edit the query.
I would assume that your issue might have to do with the params being passed.
You should add this before your queries to view what params you are picking up.
p 'my params'
p params[:search]
p params[:page]
PS. I suggest making your per_page a variable, it makes it easier when going through code to see all the hard coded values and change them when they are not in the middle of a code block.

Related

Rails 4 Filter Index lists with toggle

I have created a small ticketing system for my users. I have tickets as New, In Progress and Completed. I would like to be able to toggle on the page whether the completed are hidden or shown. What is the best way to do this? The param that holds these values is ticket.status.
In Controller:
def index
#tickets = Ticket.all
if params[:filter_by]
#tickets = Ticket.where(:category => params[:filter_by])
else
#tickets = Ticket.all
end
end
In Index view:
<div>
<div><%= link_to "Full Listing", tickets_path %></div>
<div><%= link_to "Admin", tickets_path(:filter_by => :Administrative), {:method => :get} %></div>
<div><%= link_to "Graphics", tickets_path(:filter_by => :Graphics), {:method => :get} %></div>
<div><%= link_to "IT", tickets_path(:filter_by => :IT), {:method => :get} %></div> |||
<div><%= link_to "New entry", new_ticket_path %></div> |||
<div>
<% if current_user.present? %>
<%= link_to " Sign Out", sessions_path, method: :delete %>
<% end %>
</div>
How about you take a look at Ransack, SimpleForm and SimpleFormRansack? That is how I build most of my own index filters.
https://github.com/activerecord-hackery/ransack
https://github.com/plataformatec/simple_form
https://github.com/kaspernj/simple_form_ransack
In your controller do something like this:
def index
ransack_params = params[:q] || {}
ransack_params[:status_eq_any] ||= ["New"]
#ransack = Ticket.ransack(params[:q])
#tickets = #ransack.result
end
In your view you could do something like this:
<%= simple_search_form_for #ransack do |f| %>
<%= f.input :category_eq_any, collection: ["Administrative", "Graphics", "IT"] %>
<%= f.input :status_eq_any, collection: ["New", "Completed"] %>
<%= f.button :submit %>
<% end %>
<% #tickets.each do |ticket| %>
...
<% end %>
You can also show links to predefined searches like this:
<%= link_to "Admin", tickets_path(q: {status_eq: "Administrative"}) %>

Rails: Pass ID of nested resource from button_to to controller / to toggle boolean in admin view

I am sitting here since the Dawn of Times trying to toggle a boolean in Rails for an admin to validate submissions.
I have a standard "Article" model, which has_many "Prosols" (which in turn belongs_to "Article").
A Prosol has a boolean "profeat1".
I am trying to toggle it thanks to a set of button_to (as follows).
I am looping through the articles prosols, showing them in a bootstrap template, and showing for each a button to validate or not.
The issue is that all buttons point to the first prosol. It seems that the prosol ID is not accurately passed to the controller.
No route matches {:action=>"unpro1", :article_id=>5, :controller=>"prosols", :id=>nil} missing required keys: [:id]
Here is the code.
article#show.html.erb - Adding lines from original Code
<% if admin_signed_in? %>
<% #article.prosols.in_groups_of(2) do |group| %>
<div class="container-fluid">
<% group.compact.each do |prosol| %>
<div class="col-md-6">
<div class="box3">
<h4><%= prosol.title %></h4> <br>
<%= prosol.body %> <br>
<% if prosol.profeat1 == false %>
<%= button_to "Do it", pro1_article_prosol_path(:article_id => #article.id, :id => #prosol.id), :class => 'btn btn-info'%>
<% else %>
<%= button_to "Undo it", unpro1_article_prosol_path(:article_id => #article.id, :id => #prosol.id), :class => 'btn btn-info'%>
<% end %>
</div>
</div>
<% end %>
</div>
<% end %>
<% end %>
prosols_controller.rb
def pro1
#article = Article.find(params[:article_id])
#prosol = #article.prosols.find(params[:id])
#prosol.update(profeat1: true)
redirect_to article_path(#article)
end
def unpro1
#article = Article.find(params[:article_id])
#prosol = #article.prosols.find(params[:id])
#prosol.update(profeat1: false)
redirect_to article_path(#article)
end
routes.rb
resources :articles do
resources :prosols do
post 'pro1', on: :member
post 'unpro1', on: :member
end
end
Right now I think the issue is with passing the nested resource (prosol) ID to controller.
If you see a better/different way of achieving the end result, I will warmly welcome your advice.
Again, my goal is to display all prosols for an article, with an admin button to validate or not.
I have thoroughly tried everything else on StackO so far but to no avail.
Awaiting the Savior... Thanks in advance.
EDIT : THIS IS THE SOLUTION - article#show.html.erb
<% if prosol.profeat1 == false %>
<%= button_to "Do it", pro1_article_prosol_path(:article_id => #article.id, :id => prosol.id), :class => 'btn btn-info'%>
<% else %>
<%= button_to "Undo it", unpro1_article_prosol_path(:article_id => #article.id, :id => prosol.id), :class => 'btn btn-info'%>
<% end %>
My initial error had 2 sources:
- pointing to the nested prosol with an # instead of no pointer, as it was already pointed to in the loop
- and bad leftovers in the Articles controller, as follows:
def show
#article = Article.find(params[:id])
#prosols = #article.prosols.all <--- wrong
#prosol = #article.prosols.build <--- wrong
end
Great. Now it's beer o'clock.
Shouldn't this:
<% if prosol.profeat1 == false %>
<%= button_to "Do it", pro1_article_prosol_path(:article_id => #article.id, prosol.id => prosol.id), :class => 'btn btn-info'%>
<% else %>
<%= button_to "Undo it", unpro1_article_prosol_path(:article_id => #article.id, prosol.id => prosol.id), :class => 'btn btn-info'%>
<% end %>
look like this?
<% if prosol.profeat1 == false %>
<%= button_to "Do it", pro1_article_prosol_path(:article_id => #article.id, :id => prosol.id), :class => 'btn btn-info'%>
<% else %>
<%= button_to "Undo it", unpro1_article_prosol_path(:article_id => #article.id, :id => prosol.id), :class => 'btn btn-info'%>
<% end %>
Or even better:
<% if prosol.profeat1 == false %>
<%= button_to "Do it", pro1_article_prosol_path(#article, prosol), :class => 'btn btn-info'%>
<% else %>
<%= button_to "Undo it", unpro1_article_prosol_path(#article, prosol), :class => 'btn btn-info'%>
<% end %>
The issue appears to be that you are using #prosol in your button, which has not been assigned and is therefore returning nil.
Your loop defined in your comment, sets prosol, which is not #prosol. Drop the '#' symbol and you should be fine.
-- edit--
As in id => prosol.id ...
<% if prosol.profeat1 == false %>
<%= button_to "Do it", ..., :id => prosol.id), :class => 'btn btn-info'%>
<% else %>
<%= button_to "Undo it", ..., :id => prosol.id), :class => 'btn btn-info'%>
<% end %>
Your error is showing id => nil because #prosil is a nil object.

How to add class in rails 2.3.5 to link_to

I have got following link_to tag But I don't know how to add html class attribute to it and explain me code edit_course_path(course) .. does. I am new to rails
<% #courses.each do |course| %>
<li class="list<%=cycle('odd', 'even')%>">
<div class="category-edit"><%= link_to "#{t('edit_text')}", edit_course_path(course) if permitted_to? :edit, :courses %></div>
<div class="category-delete"> <%= link_to(t('delete_text'), course_path(course), :method => 'delete', :confirm => "#{t('delete_confirm_msg')}") if permitted_to? :destroy, :courses %></div>
</li>
<% end %>
Generally like so:
<% for employee in #employees %>
<%= link_to 'Edit', edit_employee_path(employee) if permitted_to? :update, employee , :class => 'some-class'%>
<% end %>

Rails: will_paginate + simple search engine error: undefined method `total_pages'

on my users index page I am trying to have a search engine at the top so that you can search a user by email instead of scanning through the whole list. However, I am getting the error:
undefined method 'total_pages'
when I search any term.
Can anyone help? Thanks!
users/index.html.erb
<h1>All users</h1>
<%= form_tag users_path, :method => "get" do %>
<%= label_tag(:search, "Search for user by email:") %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
<% end %>
<%= will_paginate #users %>
<br>
<% #users.each do |user| %>
<div>
<%= link_to (image_tag user.profilepic? ? user.profilepic : "questionmark.png", :size => "50x50"), user_path(user) %>
<%= link_to user.name, user_path(user) %> (<%= user.email %>)
<% unless current_user.friends.include?(user) || current_user == user %>
<span class="floatright"><%= link_to "Add friend", user_friends_path(:user_id => current_user.id, :friend_id => user.id), :method => :post %></span>
<% end %>
<% if current_user.friends.include?(user) %>
<span class="floatright"><%= link_to "Remove friend", user_friends_path(:user_id => current_user.id, :friend_id => user.id), :method => :delete, :confirm => "Are you sure you want to remove #{user.name} from your friends?" %></span>
<% end %>
</div>
<% end %>
users controller
def index
if params[:search]
#users = User.search(params[:search])
else
#users = User.order("email").page(params[:page]).per_page(10)
end
end
user model
def self.search(search)
find(:all, :conditions => ['email LIKE ?', "%#{search}%"])
end
You're not calling a pagination method in #users = User.search(params[:search]). Try adding the .page(params[:page]).per_page(10) and see if that works.
UPDATE:
Sorry, I forgot .find returns an array and not a relation. Change your search method to this:
def self.search(search)
where('email LIKE ?', "%#{search}%")
end

link submit to another page

I have this form:
in header of my website:
<% form_tag request.path, :method => 'get' do %>
<p>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search User", :name => nil %>
</p>
<% end %>
controller:
def index
#title = "All users"
#users = User.paginate(:page => params[:page])
#users1 = User.simple_search(params[:query]).all
end
model:
acts_as_simply_searchable :columns => [:name, :email]
view
<%= will_paginate %>
<ul class="users">
<%= render #users1 %>
</ul>
<%= will_paginate %>
displays a user
I want to link the submit button to index.html.erb (i have assigned a path in routes.rb). So that the user can look at the search results
You don't do this at the submit button, but at the form_tag URL (the first parameter). It would be something like this:
<% form_tag users_path, :method => 'get' do %>
<p>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search User", :name => nil %>
</p>
<% end %>
Simply change request.path to the desired path.
I think you are missing the '=' sign and string interpolating the 'request.path'
This Worked for me:
<%= form_tag "#{request.path}", method: "get" %>
...the rest of your code ...
<% end %>

Resources