Fairly new to rails and can't seem to get this simple destroy action working. All it does is redirect to the mod panel index page and doesn't destroy the record. Do I need to call .destroy in the destroy method? or is there something I'm missing?
mod_approval controller
def index
#guide = Guide.friendly.find(params[:guide_id])
#check_category = CheckCategory.where(guide_id: #guide.id).all
#category = Guide.friendly.find(#guide.id).categories.new
end
def destroy
redirect_to guide_mod_panel_mod_approval_index_path(#guide)
end
config/routes.rb
match '/guides/:guide_id/mod-panel/approve/reject' => 'mod_approval#destroy', :via => :delete, as: :guide_mod_panel_approve_destroy
index.html.erb
<% #check_category.each do |category| %>
<%= link_to "Reject", guide_mod_panel_approve_destroy_path(#guide, category), method: :delete, data: {confirm: "You sure?"} %><br>
<% end %>
You need to fetch the record from the database, then you can call destroy on the object, you can do this
def destroy
guide = Guide.find(params[:guide_id])
category = guide.categories.find(params[:id])
category.destroy
redirect_to guide_mod_panel_mod_approval_index_path(guide)
end
Hope that helps!
You should have to destroy object before:
def destroy
#destroyed_object.destroy # or Model.destroy(params[:id])
redirect_to guide_mod_panel_mod_approval_index_path(#guide)
end
Related
EDIT: I managed to delete! i had to define teh instance variable #movies = Movie.find(params[:id]) to the delete method in the controller.
I still can't update though. I get "param is missing or the value is empty: movie"
I forgot to add my contrller! sorry!
I'm trying to replicate one of my in class exercises into another app, for practice.
The idea is to be able to add new movies into a database, and get the option to update their info, and delete them as well. I can add new content, but I can't update them or delete them.
Appreciate any inputs I can get.
Routes.rb
Rails.application.routes.draw do
root "movies#index"
get "/movies", to: "movies#index"
get "/movies/new", to: "movies#new", as: "new_movie"
get '/movies/:id', to: "movies#movie_page", as: "movie_page"
post "/movies", to: "movies#add"
get "/movies/:id/edit", to: "movies#edit", as: "movie_edit"
put "/movies/:id", to: "movies#update"
patch "/movies/:id", to: "movies#update", as: "update_movie"
delete "/movies/:id", to: "movies#delete", as: "delete_movie"
end
Controller
class MoviesController < ApplicationController
def index
#movies = Movie.all
end
def movie_page
#movies = Movie.find(params[:id])
end
def new
#movies = Movie.new
end
def add
#movies = Movie.create(movie_params)
redirect_to movies_path
end
def edit
#movies = Movie.find(params[:id])
end
def update
#movies.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
def delete
#movies = Movie.find(params[:id])
#movies.destroy
# flash[:notice] = "Shirt was deleted."
redirect_to root_path, notice: "Shirt was deleted."
end
def movie_params
params.require(:movie).permit(:title, :description, :year_released)
end
# def set_movie
# #movies = Movie.find(params[:id])
# end
end
Form partial
<%= form_for #movies do |m| %>
<p>
<%= m.label :title %><br>
<%= m.text_field :title %>
</p>
<p>
<%= m.label :description %><br>
<%= m.text_field :description %>
</p>
<p>
<%= m.label :year_released %><br>
<%= m.text_field :year_released %>
</p>
<p>
<%= m.submit %>
</p>
<% end %>
Movie page html (individual movies, labeled by IDs)**I can't update or Delete, no route matches Delete.
When I press Update - I get param is missing or the value is empty: movie
<h1><%= #movies.title %></h1>
<h2>Released on : <%= #movies.year_released %> </h2>
<p> <%= #movies.description %> </p>
<%= link_to "Update", movie_edit_path(#movies) %>
<%= link_to "Delete", movies_path, method: :delete %
Edit page *I cant access this link. the form is the problem
<h1>Edit <%= #movies.title %> Info </h1>
<%= render "form" %>
<%= link_to "Cancel Edit", movie_edit_path(#movies) %>
Many thanks guys
def update
#movie = Move.find(params[:id])
#movie.update(movie_params)
redirect_to movie_path(#movie)
end
on your routes. all you need is resources :movies
you are getting param is empty because you have to pass in the id of the movie to update.
The major issue is that you do not load the variable #movies from the DB before you use it.
def update
#movies.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
def update
#movies.find(params[:id])
#movie.update(movie_params)
redirect_to #movies, notice: "Shirt was updated."
end
Aside from that you have tons of duplication and quite a few idiosyncrasies.
Rails uses these naming conventions for actions:
index
show (not movie_page)
new
create (not add)
edit
update
destroy (not delete)
You should follow them unless you have a damn good reason not to.
class MoviesController < ApplicationController
# cuts the duplication
before_filter :set_movie, except: [:new, :index]
def index
#movies = Movie.all
end
# GET /movies/:id
def show
end
# GET /movies/new
def new
#movie = Movie.new
end
# POST /movies
def create
#movie = Movie.create(movie_params)
redirect_to movies_path
end
# GET /movies/edit
def edit
end
# PUT|PATCH /movies/:id
def update
#movie.update(movie_params)
redirect_to #movie, notice: "Shirt was updated."
end
# DELETE /movies/:id
def destroy
#movie.destroy
redirect_to action: :index
end
private
def movie_params
params.require(:movie).permit(:title, :description, :year_released)
end
def set_movie
# Use the singular form when naming a variable with a single record
# failure to do so may result in tarring and feathering
#movie = Movie.find(params[:id])
end
end
I am building a mock up of reddit. When on my show view that displays the link & title I submit I have included an option(link) to destroy the submission.
When I click on the destroy I get:
ActionController::ParameterMissing in LinksController#destroy
param not found: link
on line:
params.require(:link).permit(:url, :title)
This is my full Links controller:
class LinksController < ApplicationController
def index
#link = Link.all
end
def show
#link = Link.find(params[:id])
end
def new
#link = Link.new
end
def create
#link = Link.new(link_params)
if #link.save
redirect_to #link
else
render action: 'new'
end
end
def destroy
#link = Link.find()
if #link.destroy
redirect_to index: 'action'
else
render show: 'action'
end
end
private
def link_params
params.require(:link).permit(:url, :title)
end
end
This is my show view:
<h1> This is the show view </h1>
<%= #link.title %>
<%= #link.url %>
<%= link_to 'Edit', edit_link_path(#link) %>\
<%= link_to 'Destroy', (#link), method: :delete, data: { confirm: 'Are you sure?' } %>
I'm really confused, have tried multiple things but can't get it to work. How can i fix this?
Looks like you permit is missing :id and your destroy is missing params[:id] in the find clause.
Your problem is:
def destroy
#link = Link.find()
...
You need something like:
def destroy
#link = Link.find(params[:id])
What's happening is that your Destroy link is sending a DELETE request to some URL like /link/23 with 23 being params[:id]. You need to find the appropriate Link object by using Link.find(params[id]) before you destroy it (similar to how you would in show).
I'm currently trying to implement likes and unlikes rails app using thumbs_up. I followed the instructions on this page: Clarification on how to use "thumbs_up" voting gem with Rails 3
Users can like and unlike books. I have 2 buttons, like and unlike and I would like to hide one or the other from the user, depending on the users current like status. So I figured an if else would be appropriate like this:
<% if #user.voted_on?(#book) %>
<div class="unlike_button"><%= link_to("Unlike", unvote_book_path(book), method: :post) %></div>
<% else %>
<div class="like_button"><%= link_to("Like", vote_up_book_path(book), method: :post) %></div>
<% end %>
and in my route.rb file:
resources :books do
member do
post :vote_up
post :unvote
end
end
But when I run this I get the error message:
undefined method `voted_on?' for nil:NilClass
Is there anything I might be doing wrong?
Update
As Mischa suggested, I changed it to current_user.voted_on. Now I get this error message:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Below is a snippet of my Books controller
include UsersHelper
include SessionsHelper
before_filter :signed_in_user, only: [:index]
before_filter :admin_user, only: :destroy
def index
array = Book.search(params[:search])
#books = Kaminari.paginate_array(array).page(params[:page]).per(5)
end
def show
#book = Book.find(params[:id])
#respond_to do |format|
#format.js
#end
end
def destroy
Book.find(params[:id]).destroy
flash[:success] = "Book deleted."
redirect_to books_url
end
def vote_up
begin
current_user.vote_for(#book = Book.find(params[:id]))
flash[:success] = "Liked!."
redirect_to books_url
end
end
def unvote
begin
current_user.unvote_for(#book = Book.find(params[:id]))
flash[:success] = "Unliked!."
redirect_to books_url
end
end
You should change your method of link from post to put and
change your routes.rb to
resources :books
You can also update a data using a link by using this code:
<%= link_to "Like", book, :method => :put %>
or
<%= link_to "Unlike", book, :method => :put %>
and this goes with your controller in
assuming that you have a is_liked boolean field in your Post model
def update
#post = Post.find(params[:id])
if #post.is_liked?
#post.attributes = {
:is_liked => "f"
}
redirect_to posts_path, :flash => "Unliked"
else
#post.attributes = {
:is_liked => "t"
}
redirect_to posts_path, :flash => "Liked"
end
end
I have a user model and a question model.
In the user model:
has_many :questions
The question model:
belongs_to
in my questions/show.html.erb
<% if #question.user == current_user %>
<%= link_to 'Edit', edit_question_path(#question) %> | <%= link_to 'Destroy', #question, method: :delete, data: { confirm: 'Are you sure you want to delete this job?' } %>
<%= link_to 'Back', questions_path %>
<% else %>
<%= link_to 'Back', questions_path %>
<% end %>
How can only the user that authored the question edit and delete it?
Take a look at CanCan, the authorization gem by Ryan Bates of Railscasts. It's great for Rails authorization needs.
First, you'll create an Ability class that defines all of the abilities in the application.
class Ability
include CanCan::Ability
def initialize(user)
can :manage, Question, user_id: user.id
end
end
Then, you'll be able to easily integrate authorization into your controllers.
class QuestionsController < ApplicationController
def update
authorize! :manage, #question
...
end
def destroy
authorize! :manage, #question
...
end
end
And also customize your views.
<% if can? :manage, #question %>
<%= link_to 'Edit', edit_question_path(#question) %> | <%= link_to 'Destroy', #question, method: :delete, data: { confirm: 'Are you sure you want to delete this job?' } %>
<% end %>
All you need in your controller is:
def destroy
#question = current_user.questions.find(params[:id])
#question.destroy
render ... #anything you want to render
end
The previous code will ensure that an user can only delete his own questions. If the id of the question doesn't belongs to the user no question will be deleted and it would throw and ActiveRecord::RecordNotFound - Internal Server error. You can add a begin - rsecue block to catch this exception an handle it as you want.
def destroy
begin
#question = current_user.questions.find(params[:id])
#question.destroy
render or redirect_to ....
rescue Exception ActiveRecord::RecordNotFound
flash[:notice] = 'not allow to delete this question'
redirect_to ....
end
end
Other simple way is to add a before filter in your controller
before_filter :require_authorization, only: [:delete]
...
def destroy
#question = current_user.questions.find(params[:id])
#question.destroy
render or redirect_to ....
#With the before filter this code is only going to be executed if the question belongs to the user
end
...
private
def require_authorization
redirect_to :root unless current_user.questions.find_by_question_id(params[:id])
#Use the find_by to avoid the ActiveRecord::RecordNotFound and get a nil instead in case the question id doesn't belong to a question of the user
end
you can try changing your if to the following:
<% if current_user.questions.include?(#question) %>
Also you can take a look at :inverse_of
Then in your Edit and Delete actions in the controller you can again check for the right user before showing the edit form or deleting the question.
I just wanted to know if there is any method available to update a record of a table from a view? For example am I able to delete a record from the table using the code below?
<td><%= link_to 'Delete', my_path(user), :confirm => 'Are you sure?', :method =>:delete, :remote=>true %></td>
And in my controller I have:
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.js do
render(:update) { |page| page.reload }
end
end
end
The above code works perfectly. It deletes the record from the table and also reloads the page after clicking the destroy link. Now, my question is: can I do the same for updating a value in my record? If so, how can I do that?
Sure you can, you would simply change a few things:
The method in your controller would be update:
def update
#user = User.find(params[:id])
#user.update_attributes(params[:user])
respond_to do |format|
format.js do
render(:update) { |page| page.reload }
end
emd
end
Then you would change your link to something like the following:
<td><%= link_to "Update", my_path(user), :method => :put, :remote => true %></td>
Mind you, this is under the presumption that you are in a form_for #user tag.
<%= form_for #user do |f| %>
<%= f.text_field :name %>
# aforementioned link to update goes here
<% end %>
This is under the impression that you setup #user in the controller method (most likely def edit)
def edit
#user = User.find(params[:id])
end