Multiple submit buttons rails - ruby-on-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

Related

Cancancan gem usage in rails application

I have a rails application which manages all the registered users. All crud operations can be done on the details of the registered users. I now need to restrict the application in such a way that only the admin user should be allowed to view all the registered users. Any user without the admin privilege should be able to view, edit, and delete his/her post only. I have used devise gem for authentication and plans to use cancancan gem for authorization. I have only a single model class called Users which contains a text attribute (to store "Admin" or "Nonadmin"). Here is my controller code:
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
if current_user.role == "Admin"
#users = User.all
else
#user = User.find(current_user.id)
end
redirect_to new_user_registration_path if current_user.nil?
respond_to do |format|
format.html
end
end
def show
if (User.all.pluck(:id).include?params[:id].to_i) == false
flash[:notice] = "You cannot perform such an action"
else
#user = User.find(params[:id])
end
respond_to do |format|
format.html
end
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def user_params
params.require(:user).permit(:first_name, :last_name, :age, :biography, :email)
end
def edit
if (User.all.pluck(:id).include?params[:id].to_i) == false
flash[:notice] = "You cannot perform such an action"
else
#user = User.find(params[:id])
end
respond_to do |format|
format.html
end
end
def update
params.inspect
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to :action => 'show', :id => #user
else
render :action => 'edit'
end
end
def delete
User.find(params[:id]).destroy
redirect_to :action => 'index'
end
end
My user table has the following fields: id,email,first_name,last_name,biography,email,role. It also contains all the devise-related fields.Below is my User model :
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
after_initialize :default_values
private
def default_values
self.role ||= "Non-admin"
end
end
I have hardcoded my admin credentials in seeds.rb as shown below:
if User.find_by(:role => 'Admin').nil?
User.create([{email:"admin_user#usermanagementsystem.com",password: "topsecret",first_name:"admin",last_name:"ums", biography: "i serve as admin at the ums", age:20, role: "Admin"}])
end
View files:
Index.html.erb:-
<table id="albums" cellspacing="0">
<thead>
<tr>
<th> NAME </th>
<th> EMAIL </th>
<% if current_user.role == "Admin" %>
<th> EDIT </th>
<th> SHOW </th>
<th> DESTROY </th>
<% end %>
<th colspan="15"></th>
</tr>
</thead>
<% if current_user.role == "Admin" %>
<% #users.each do |user| %>
<tr>
<td><%= user.first_name %></td>
<td><%= user.email %></td>
<td><%= link_to 'Edit', users_edit_path(id: user.id), class: "small button"%></td>
<td><%= link_to 'Show', users_show_path(id: user.id), class: "small button"%></td>
<td><%= link_to 'Destroy', users_delete_path(id: user.id), method: :delete, data: { confirm: 'Are you sure?' } , class: "small button"%></td>
</tr>
<% end %>
<% else %>
<tr>
<td><%= #user.first_name %></td>
<td><%= #user.email %></td>
<td><%= link_to 'Edit', users_edit_path(id: #user.id), class: "small button" %></td>
<td><%= link_to 'Destroy', users_delete_path(id: #user.id), method: :delete, data: { confirm: 'Are you sure?' } , class: "small button"%></td>
</tr>
<%end %>
</table>
<%#= link_to 'Change password', edit_user_registration_path, class: "small button" %>
edit.html.erb:-
<% if #user.nil? == false %>
<%= form_for #user , :as => :user, :url => users_update_path(#user), :method => :PUT do |f| %>
<%= f.label :first_name %>:
<%= f.text_field :first_name %><br>
<%= f.label :last_name %>:
<%= f.text_field :last_name %><br>
<%= f.label :age %>:
<%= f.number_field :age %><br>
<%= f.label :biography %>:
<%= f.text_field :biography %><br>
<%= f.label :email %>:
<%= f.text_field :email %><br>
<%= f.submit :class => 'small button' %>
<% end %>
<%else%>
<h3> Such a user record does not exist. Please click on a specific user </p>
<%end%>
show.html.erb
<br>
<br>
<% if #user.nil? == false %>
<h3>User details</h3>
<table id="albums" cellspacing="0">
<thead>
<tr>
<th>FIRSTNAME</th>
<th>LASTNAME</th>
<th>EMAIL</th>
<th>BIOGRAPHY</th>
<th>AGE</th>
<th colspan="20"></th>
</tr>
</thead>
<tr>
<td> <%= #user.first_name %> </td>
<td> <%= #user.last_name %> </td>
<td> <%= #user.email %> </td>
<td> <%= #user.biography %> </td>
<td> <%= #user.age %> </td>
</tr>
</table>
<%= link_to ' Edit ', users_edit_path(id: #user.id) , class: "small button"%>
<%= link_to 'Delete ', users_delete_path(id: #user.id), method: :delete, data: { confirm: 'Are you sure?' }, class: "small button" %>
<%else%>
<h3> Such a user record does not exist. Please click on a specific user </p>
<%= link_to "Logout", destroy_user_session_path, method: :delete, class: "small button" %>
</footer>
<%end%>
Can anyone help me out in using cancancan gem to restrict any user other than admin from viewing, editing, updating and deleting his own posts. Admin should be able to do these operations on everyone's records.
Please help me improve if you find me doing something wrong with the controller code too. Thanks in advance.
Added the following code to the initialize function of ability.rb and got it working correctly.
if user.role == "Admin"
can :manage, :all
else
can [:index], User, id: user.id
can [:show],User, id: user.id
can [:edit],User, id: user.id
can [:update], User,id: user.id
can [:delete],User, id: user.id
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

NoMethodError in Admin::Posts#index

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 .

Why my form won't submit correctly?

I have User model and Comment model using acts_as_commentable_with_threading
I'm trying to put the comment function on each User's show page with partial.
But When I try to submit a form, it shows routing error.
Why is this?
Error
Routing Error
No route matches [POST] "/user/john/add_comment"
models/user.rb
acts_as_commentable
views/users/show.html.erb
<%= render 'comment', :user => #user %>
views/users/_comment.html.erb
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Body</th>
<th>Subject</th>
<th>Posted by</th>
<th>Delete</th>
</tr>
<% #user.comment_threads.each do |comment| %>
<tr>
<td><%= comment.id %></td>
<td><%= comment.title %></td>
<td><%= comment.body %></td>
<td><%= comment.subject %></td>
<td><%= comment.user.user_profile.nickname if comment.user.user_profile %></td>
<td><%= button_to 'destroy', comment, confirm: 'Are you sure?', :disable_with => 'deleting...', method: :delete %></td>
</tr>
<% end %>
</table>
<%= form_for #user, :html => { :class => 'form-horizontal' } do |f| %>
<div class="field">
<%= f.label :body %><br />
<%= f.text_field :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
routes.rb
get "user/:id/add_comment" => 'users#add_comment', :as => :add_comment_user
get "user/:id/delete_comment" => 'users#delete_comment', :as => :delete_comment_user
users_controller.rb
def add_comment
#user = User.find_by_username(params[:id])
#user_who_commented = current_user
#comment = Comment.build_from( #user, #user_who_commented.id, params[:users][:body] )
#comment.save
redirect_to :controller => 'users', :action => 'show', :id => params[:users][:id]
flash[:notice] = "comment added!"
end
Because your route is for a GET, and the form is a POST.
It needs to be a post route. Also you are posting to user/:name/add_comment, you should post the the user id. You can use the name but this would need to be unique across all users.
This line is also wrong.
#user = User.find_by_username(params[:id])
You can either pass in the params[:username] of find_by_id

Need help with implementing Railscast 198 in Rails 3

I have been trying to implement Ryan Bates Railscast 198 into rails 3 for like 4 days... at least at night if you know what I mean. Anyway, here is the code I have right now:
User controller actions (Devise setup to show the different states of approved):
def index
if params[:approved] == "false"
#users = User.find_all_by_approved(false)
elsif
#users = User.find_all_by_approved(true)
else
#users = User.all
end
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to root_path flash[:notice] = "User was successfully updated." }
else
format.html { render :action => "edit" }
end
end
end
def edit_individual
#users = User.find(params[:user_ids])
end
def update_individual
#users = User.update(params[:users].keys, params[:users].values).reject { |p| p.errors.empty? }
if #users.empty?
flash[:notice] = "Users updated"
redirect_to users_url
else
render :action => "edit_individual"
end
end
end
My User#index
<h1> Users</h1>
<%= link_to "All Users", :action => "index" %> |
<%= link_to "Users awaiting approval", :action => "index", :approved => "false"%>
|
<%= link_to "Approved Users", :action => "index", :approved => "true" %>
<%= form_tag edit_individual_users_path, :method => :put do %>
<table>
<tr>
<th>Email Address</th>
<th>Approved</th>
<th></th>
</tr>
<% for user in #users %>
<tr>
<td> <%= user.email %></td>
<td><%= check_box_tag user.id %></td>
<td> <%= link_to "Edit", edit_user_path(user) %></td>
</tr>
<% end %>
<p><%= submit_tag "Edit Checked" %></p>
</table>
<% end %>
And the User#edit_individual
<%= form_tag update_individual_users_path, :method => :put do %>
<% for user in #users %>
<%= fields_for "users[]", user do |f| %>
<h2><%=h user.name %></h2>
<p><%= check_box_tag user.id %></p>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>
routes.rb
devise_for :users
resources :users do
collection do
post :edit_individual
put :update_individual
end
end
end
So I handled the basic by googling: fields_for needs an "=" stuff like that. #index shows fine but if I check a checkbox and then hit the edit checked button I get the following error:
ActiveRecord::RecordNotFound in UsersController#update
Couldn't find User with id=edit_individual
Any ideas??? thanks so much
Please check your routes.rb and controller code, as it's quite a bit off from the code on Railscast 198's page: http://railscasts.com/episodes/198-edit-multiple-individually
It's best to just copy it in if you're new to rails and adjust for using users instead of products. Then go through it to try to understand what it does.

Resources