NoMethodError in Admin::Posts#index - ruby-on-rails

I am having problem with my post code please see this.
The error is saying
NoMethodError in Admin::Posts#index Showing
/home/muba/rblog/app/views/admin/posts/index.html.erb where line #2
raised:
undefined method `exists?' for nil:NilClass
post> index.html.erb is here:
<h2 class="page-header">Posts <%= link_to "Create New", new_admin_post_path, class:'btn btn-success pull-right' %></h2>
<% if #posts.exists? %>
<table class="table table-striped">
<tr>
<th>Post Title </th>
<th>Date Created</th>
<th>Post Category </th>
<th> Actions </th>
</tr>
<% #posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.created_at.to_time.strftime('%B %e at %l:%M %p') %></td>
<td><%= post.category.name %></td>
<td><%= link_to "Edit", edit_admin_post_path(post), class:'btn btn-primary' %> <%= link_to "Delete", admin_posts_path(post), class:'btn btn-danger', method: :delete, data: {confirm: 'Are you sure'} %></td>
</tr>
<% end %>
</table>
<%= will_paginate #posts %>
<% else %>
<p> There are no posts </p>
<% end %>
And The Posts Controller is:
class PostsController < ApplicationController
def new
#page_title = 'Add Post'
#post = Post.new
end
def create
#post = post.new(post_params)
if #post.save
flash[:notice] = 'Post Created'
redirect_to admin_posts_path
else
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
flash[:notice] = 'Post Updated'
redirect_to admin_posts_path
else
render 'new'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
flash[:notice] = 'Post Removed'
end
def index
#posts = Post.all
end
private
def category_params
params.require(:post).permit(:title, :category_id, :user_id, :tags, :image, :body)
end
Please give me a solution :(

Check #post like this:-
<% if #posts.present? %>
<% end %>

May be this works:
<% unless #posts.nil? %>
As per the documentation, exists? generally used for comparison, takes argument to check whether exist or not.

You can also try this :
<% if !#posts.nil? %>
<%= your code... %>
<% end %>
This will also help your cause .

Related

Index view of Rails model printing string with all model data

I just finished Rails' Getting Started guide and everything works perfectly except for this mysterious entry that's being printed in the Index view as shown below. I've been trying to find the cause to no avail, neither have I found no suitable terms to Google this issue.
Index.html.erb
<h1>Index</h1>
<%= link_to 'New Client', new_client_path %>
<table>
<tr>
<th>Name</th>
<th>Issued On</th>
<th>Notes</th>
<th>Finished?</th>
<th>Payments</th>
</tr>
<%= #clients.each do |client| %>
<tr>
<td><%= client.name %></td>
<td><%= client.date %></td>
<td><%= client.note %></td>
<td><%= client.finished %></td>
<td><%= client.payment %></td>
<td><%= link_to 'Show', client_path(client) %></td>
<td><%= link_to 'Edit', edit_client_path(client) %></td>
<td><%= link_to 'Destroy', client_path(client),
method: :delete,
data: { confirm: 'This client will be permanentally deleted, do you want to continue?' } %></td>
</tr>
<% end %>
</table>
Clients Controller
class ClientsController < ApplicationController
def index
#clients = Client.all
end
def show
#client = Client.find(params[:id])
end
def new
#client = Client.new
end
def edit
#client = Client.find(params[:id])
end
def create
#client = Client.new(client_params)
if #client.save
redirect_to #client
else
render 'new'
end
end
def update
#client = Client.find(params[:id])
if #client.update(client_params)
redirect_to #client
else
render 'edit'
end
end
def destroy
#client = Client.find(params[id])
#client.destroy
redirect_to clients_path
end
private
def client_params
params.require(:client).permit(:name, :date, :note, :finished, :payment)
end
end
Remove = from <%= #clients.each do |client| %>. It is outputting result of each which you don't need to print.
In ERB,
<%= %>
executes ruby code as well as outputs the result
For example: <%= client.name %>
<% %>
executes ruby code but doesn't output the result
For example: <% #clients.each do |client| %>....<% end %>

Rendering 'form' is giving me an ArgumentError

I am trying to create an activity feed, and trust me, it will take a while to create as I am new to ruby on rails. Sorry for a basic question.
However, I am trying to render '_form.html.erb' as I want the user to be able to create a 'story' and for it to be listed on the same page, like any activity feed. Could someone explain to me what the problem is?
My index.html.erb:
<p id="notice"><%= notice %></p>
<h1>This is a list of posts</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>User</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #stories.each do |story| %>
<tr>
<td><%= story.name %></td>
<td><%= story.description %></td>
<td><%= story.user.email %></td>
<td><%= link_to 'Show', story %></td>
<% if user_signed_in? %>
<td><%= link_to 'Edit', edit_story_path(story) %></td>
<td><%= link_to 'Destroy', story, method: :delete, data: { confirm: 'Are you sure?'} %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'New Story', new_story_path %>
<%= render 'form' %>
_form.html.erb:
<%= form_for #story do |f| %>
<%= render 'shared/errors', object: #story %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: 'form-control', required: true, cols: 3 %>
</div>
<%= f.submit 'Create Story', class: 'btn btn-primary' %>
<% end %>
Story Controller:
class StoriesController < ApplicationController
before_action only: [:destroy, :show, :edit, :update]
def index
#stories = Story.order('created_at DESC')
end
def new
#story = current_user.stories.build
end
def create
#story = current_user.stories.build(story_params)
if #story.save
flash[:success] = "Your beautiful story has been added!"
redirect_to root_path
else
render 'new'
end
end
def edit
#story = Story.find(params[:id])
end
def update
#story = Story.find(params[:id])
if #story.update_attributes(params.require(:story).permit(:name, :description))
flash[:success] = "More knowledge, more wisdom"
redirect_to root_path
else
render 'edit'
end
end
def destroy
#story = Story.find(params[:id])
if #story.destroy
flash[:success] = "I think you should have more confidence in your storytelling"
redirect_to root_path
else
flash[:error] = "Can't delete this story, sorry"
end
end
def show
#stories = Story.find(params[:id])
end
private
def story_params
params.require(:story).permit(:name, :description)
end
end
My error in terminal:
ActionView::Template::Error (First argument in form cannot contain nil or be empty):
1: <%= form_for #story do |f| %>
2: <%= render 'shared/errors', object: #story %>
3:
4: <div class="form-group">
You should add #store variable to index action.
def index
#stories = Story.order('created_at DESC')
#story = current_user.stories.build
end

Adding a user's ID to a teacher from a form in rails

I have the following as a table in my HTML for having a student select a teacher
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th></th>
</tr>
</thead>
<tbody>
<% #teachers.each do |teacher| %>
<tr>
<td><%= teacher.name %> </td>
<td><%= teacher.email %> </td>
<td><%= teacher.phone %> </td>
<%= form_for teacher do |f| %>
<td><%= f.submit yield(:button_text), class: "btn btn-primary" %></td>
<%= f.hidden_field :user_id, value: #user.id %>
<% end %>
</tr>
<% end %>
</tbody>
</table>
But when I click the "Select" button (which is yielded from :button_text), it doesn't assign the student to the teacher. The controller code for the update action within teachers_controller is
def update
#teacher = Teacher.find(params[:id])
if params[:user_id]
#user = User.find(params[:user_id])
if #teacher.users << #user
flash[:success] = "Profile updated"
redirect_to #user
else
render 'select'
end
else
if #teacher.update_attributes(teacher_params)
flash[:success] = "Teacher updated"
redirect_to #teacher
else
render 'edit'
end
end
end
I'm trying to make it so that if the hidden_field of the user's ID is present then the only attribute of teacher that is updated is their students, otherwise their attributes (shown in the table) are updated. What am I doing wrong?
What am I doing wrong?
You'll not be passing params[:user_id] from your form; it will be params[:teacher][:user_id]
def update
#teacher = Teacher.find(params[:id])
if params[:teacher][:user_id]
#user = User.find params[:teacher][:user_id]
if #teacher.users << #user
--
You'll be better putting this functionality into a separate method, as to not butcher your update action:
#config/routes.rb
resources :teachers do
match :users, via: [:patch, :delete] #-> url.com/teachers/:teacher_id/users
end
#app/views/teachers/index.html.erb
<% #teachers.each do |teacher| %>
<%= button_to "Add", teacher_users_path(teacher), method: :patch, params: { user_id: #user.id } %>
<% end %>
#app/controllers/teachers_controller.rb
class TeachersController < ApplicationController
def users
#teacher = Teacher.find params[:teacher_id]
if params[:user_id]
#user = User.find params[:user_id]
#teacher.users << #user if request.patch?
#teacher.users.delete #user if request.delete?
end
redirect_to teachers_path
end
end
ah, you only need one HTML form in your view. you can use a collection select, like so:
...
<tbody>
<tr>
<td>
<%= form_for teacher do |f| %>
<%= collection_select(:student, :teacher_id, Teacher.all, :id, "#{teacher.name} #{teacher.email} #{teacher.phone}", prompt: true)
</td>
<td>
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
</td>
</tr>
<% end %>
</tbody>
...
...then you'll get a params[:student][:teacher_id] posted to your controller. You might need to futz with the collection_select (or just use a regular select) a bit depending on what your models are like. Not totally sure about the hidden field or the if/else in your controller. However, using form_for and collection_select correctly should get you a long ways. Be sure to RTFM: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select

Noob error: No route matches [POST] "/users/1/edit"

Sooo... I'm a noob and I haven't found an answer that gets me through this yet. I've been struggling through this and I know it's a simple question, but I'm just not experienced enough to know how to solve this one.
I'm receiving the error:
No route matches [POST] "/users/1/edit"
Here are the routes for the issue: (simple, I know)
Rails.application.routes.draw do
resources :users
Here is the Controller:
class UsersController < ApplicationController
def new
#user=User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to users_path
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to #user
else
render 'edit'
end
end
def delete
#user = User.find(params[:id])
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to(:action => 'index')
end
def show
#user = User.find(params[:id])
end
def index
#users=User.all.order("created_at ASC")
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :username, :admin, :email, :birthday)
end
end
And, here is the view:
<DOCTYPE!! HTML>
<html>
<h1>Edit User</h1>
<%= #user.username %>
<%= link_to "Back to User Index", users_path %>
<%= form_for(:user, :url => {:action => 'edit'}) do |f| %>
<table summary="Edit user form fields">
<tr>
<th>First Name</th>
<td><%= f.text_field(:first_name) %></td>
</tr>
<tr>
<th>Last Name</th>
<td><%= f.text_field(:last_name) %></td>
</tr>
<tr>
<th>Username</th>
<td><%= f.text_field(:username) %></td>
</tr>
<tr>
<th>Password</th>
<td><%= f.text_field(:password) %></td>
</tr>
<tr>
<th>Birthday</th>
<td><%= f.date_field(:birthday) %></td>
</tr>
<tr>
<th>Is Admin?</th>
<td><%= f.text_field(:admin) %></td>
</tr>
</table>
<%= submit_tag("Update User") %>
<% end %>
</html>
I know this is probably not worth serious time for you to answer, but I haven't been able to figure it out. Please help, and let me know if you need more info. Thanks again in advance!
Change
<%= form_for(:user, :url => {:action => 'edit'}) do |f| %>
to
<%= form_for(#user) do |f| %>
In this instance, you don't need to specify the action to use. The default conventions in Rails will take care of this for you.
As you already got an answer, so as a suggestion you can also add method parameter as given here
<%= form_for #user, url: edit_user_path(#user), method: :get do |f| %>
...
<% end %>

Multiple submit buttons rails

I am trying to make multiple submit buttons for a form, but I keep getting this error:
Couldn't find User with id=edit_individual
Found in:
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
My controller page:
def edit_individual
if User.find_by_id (params[:user_ids])
if params[:Delete_multiple]
#users = User.find(params[:user_ids])
#users.each do |user|
user.destroy
end
redirect_to :back, notice: 'All selected users were successfuly deleted'
else
#users = User.find(params[:user_ids])
end
else
redirect_to :back, alert: 'No users were selected for editing'
end
end
def update_individual
#users = User.update(params[:users].keys, params[:users].values).reject { |p| p.errors.empty? }
if #users.empty?
redirect_to :back, notice: "Users updated"
else
render :action => "edit_individual"
end
end
My index page:
<%= form_tag edit_individual_users_path do %>
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th><%= sort_link #q, :firstName, "First name" %></th>
<th><%= sort_link #q, :lastName, "Last name" %></th>
<th><%= sort_link #q, :registrationNumber, "Registration number" %></th>
<th><%= sort_link #q, :email, "Email" %></th>
<th></th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<% if (user.archive == false) %>
<tr>
<td><%= check_box_tag "user_ids[]", user.id %></td>
<td><%= user.firstName %></td>
<td><%= user.lastName %></td>
<td><%= user.registrationNumber %></td>
<td><%= user.email %></td>
<td><%= link_to 'View', user, class: 'btn btn-info btn-mini', title: 'View users\'s information' %></td>
<td><%= link_to 'Edit', edit_user_path(user), class: 'btn btn-warning btn-mini', title: 'Edit users\'s information', method: 'get' %></td>
<td><%= link_to 'Delete', user, class: 'btn btn-danger btn-mini', title: 'Delete user', method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<% end %>
</tbody>
</table>
<p><%= select_tag :field, options_for_select([["All Fields", ""], ["First name", "firstName"], ["Last name", "price"], ["Registration number", "registrationNumber"], ["Email", "email"]]) %></p>
<p><%= submit_tag "Edit checked", name: 'Edit_multiple' %></p>
<p><%= submit_tag "Delete checked", name: 'Delete_multiple', data: { confirm: 'Are you sure you want to delete multiple users?' } %></p>
<% end %>
The edit_individual page:
<% form_tag update_individual_users_path, :method => :put do %>
<% for product in #products %>
<% fields_for "users[]", users do |f| %>
<h2><%=h user.name %></h2>
<%= render :partial "fields", :locals => { :f => f, :user => user } %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
The routes file:
resources :users do
get 'archive', on: :collection
post 'edit_individual', on: :collection
put 'update_individual', on: :collection
end
The delete part works fine. Also, the edit part actually edits the field, but displays that error (so it does not redirect back to the index page which makes it look bad).
Can anyone help me fix this? Spent a lot hours to have both edit and delete so it would be pretty bad if I had to delete the edit part.
EDIT 1: Also, If I am editing for example 3 users and click the submit button allowing only 2/3 to pass (due to validation), there is no error (I just get redirected back to edit_individual.html to finish the last user) and then if I have click submit again and everything passes, I get an error.
I have actually managed to find what was wrong.
The problem was with:
def update_individual
#users = User.update(params[:users].keys, params[:users].values).reject { |p| p.errors.empty? }
if #users.empty?
redirect_to :back, notice: "Users updated"
else
render :action => "edit_individual"
end
end
Instead of:
redirect_to :back
It should be:
redirect_to users_path
Or any other fixed path I suppose. Is there a way to keep "redirect_to :back", or do I have to create new methods for other views (within the same controller) that will use this?
it should not be run because you has not any params[:id]
if you user before_filter then
before_filter: set_user except: [:update_individual, :edit_individual]
def set_user
#user = User.find(params[:id])
end
and where you call update_individual in edit_individual

Resources