I'm trying to figure out how to allow a user to click on a link or button on the index page to clear out all of the objects from the app's database, and then redirect to a newly cleared index page. So, with the example model Article, I expect it should have something to do with an Article.destroy_all method, and I'm expecting it would be a simple solution, but I've tried some variations and am just not sure of how to actually implement it.
So it would be another action in your controller. If we're dealing with Articles then the controller would be:
class ArticlesController < ApplicationController
def indef
#articles = Article.all
end
def destroy_them_all
Article.destroy_all
redirect_to articles_path
end
end
And in the view where you want the user to click on a button to destroy all articles:
<%= link_to 'Destroy them all', destroy_them_all_path, method: :delete, confirm: 'Are you crazy?' %>
Don't forget to add a named route in your routes file:
match '/articles/destroy_them_all', to: 'Articles#destroy_them_all', via: :delete
That should work. Though you might have to check rake routes to make sure I got the destroy_them_all_path correct.
try this:
Article controller:
def destroy_all
#Articles = Article.all
#Articles.each do |a|
a.destroy
end
redirect_to articless_path, notice: "Delted"
end
routes:
post "articles/destroy_all"
view:
<%= form_tag ({ :controller => 'articles', :action => 'destroy_all' }) do%>
<%= submit_tag 'destroy all'%>
<% end %>
Related
I am totally new to rails and struggle with the easiest stuff. I have the following problem:
When I try to destroy a search (from my model search) it does not work and I get redirected to "/search.48 (the search with id 48). It gives me the notice "We're sorry, but something went wrong." and in the console it says something with POST. Neither the search is deleted nor the redirect_to search_path is working. What am I doing wrong?
This is my controller:
def show
#searches = current_user.searches
end
def destroy
#search = Search.find(params[:id])
#search.destroy
flash[:success] = "Search deleted"
redirect_to search_path
end
This is my view show:
<% #searches.each do |search| %>
<%= search.title %>
<%= search.description %>
<%= button_to "delete", search, method: :destroy %>
My routes.rb:
get 'search' => 'searches#show'
resources :searches
And I also included <%= javascript_include_tag 'application' %> in the application.html.erb as well as //= require jquery and //= require jquery_ujs in the application.js file.
So I really can't find my mistake. Can someone help me?
In your view file, the code for the button should look like:
<%= button_to "delete", search, method: :delete %>
Note the method is :delete, not :destroy. It's a little confusing, because 'delete' is the REST verb, but 'destroy' is the controller action name.
have you tried:
<%= button_to "Delete", { action: "delete", id: search.id },
method: :delete %>
in you view. Also it appears you are redirecting to search_path but I am guessing you want searches_path.
I got it! In my router I wrote get 'search' => 'searches#show' and somehow my controller was confused with the search_path. Since I renamed it to get 'mysearches' => 'searches#show' and mysearches_path it works perfectly
I am a beginner in ROR development. I have navigation and I want search box on every page and when I enter some keyword, it should do like query across table's field. I tried using some online tutorials but could not do it.
My table name : tutorials
here is my search form on navigation bar
<li><%= link_to 'Login', :controller => 'access', :action => 'login' %></li>
<li><%= link_to 'Sign Up', :controller => 'users', :action => 'new' %></li>
<li><%= link_to 'Logout', :controller => 'access', :action => 'logout' %></li>
<div align="right">
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
</div>
Here is my controller
class SearchController < ApplicationController
def show
#tutorial = Tutorial.find(params[:q])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #tutorial }
end
end
end
Here is my model
class Search < ActiveRecord::Base
def #tutorial.search(search)
if search
find(:all, :conditions => ['tutorial_name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
end
I am not sure how to do this. Please help
It's often true that a bad name indicates wrong thinking. I believe your name Search for the model is in this category. It should probably be called Tutorial, no? Search is something you do to a model, not the model itself.
If this guesswork is correct and the model is now called Tutorial and it has a field called name that is a string, then your model will be
class Tutorial < ActiveRecord::Base
def self.search(pattern)
if pattern.blank? # blank? covers both nil and empty string
all
else
where('name LIKE ?', "%#{pattern}%")
end
end
end
This makes the model "smart" on how to search through tutorial names: Tutorial.search('foo') will now return all tutorial records that have foo in their names.
So we can create a controller that uses this new functionality:
class SearchController < ApplicationController
def show
#tutorials = Tutorial.search(params[:q])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #tutorial }
end
end
end
The corresponding view must display the tutorials. Yours doesn't. The simplest way to do this is write a partial that renders exactly one tutorial. Say it's called _tutorial.html.erb.
Then in the view for Search, you need to add
<%= render :partial => #tutorials %>
to actually display the search results.
Addition
I'll build a little example.
# Make a new rails app called learning_system
rails new learning_system
# Make a new scaffold for a Tutorial model.
rails g scaffold Tutorial name:string description:text
# Now edit app/models/tutorial.rb to add the def above.
# Build tables for the model.
rake db:migrate
rails s # start the web server
# Now hit http://0.0.0.0:3000/tutorials with a browser to create some records.
<cntrl-C> to kill the web server
mkdir app/views/shared
gedit app/views/shared/_search_box.html.erb
# Edit this file to contain just the <%= form_tag you have above.
# Now add a header at the top of any view you like, e.g.
# at the top of app/views/tutorials/index.html.erb as below
# (or you could use the layout to put it on all pages):
<h1>Listing tutorials</h1>
<%= render :partial => 'shared/search_box' %>
# Make a controller and view template for searches
rails g controller search show
# Edit config/routes.rb to the route you want: get "search" => 'search#show'
# Verify routes:
rake routes
search GET /search/:id(.:format) search#show
tutorials GET /tutorials(.:format) tutorials#index
POST /tutorials(.:format) tutorials#create
new_tutorial GET /tutorials/new(.:format) tutorials#new
edit_tutorial GET /tutorials/:id/edit(.:format) tutorials#edit
tutorial GET /tutorials/:id(.:format) tutorials#show
PUT /tutorials/:id(.:format) tutorials#update
DELETE /tutorials/:id(.:format) tutorials#destroy
# Edit app/controllers/search_controller.rb as above.
# Create app/views/tutorial/_tutorial.html.erb with following content:
<tr>
<td><%= tutorial.name %></td>
<td><%= tutorial.description %></td>
</tr>
# Edit app/views/search/show.html.erb to have following content:
<h1>Show Search Results</h1>
<table>
<%= render :partial => #tutorials %>
</table>
Now try a little test. Fill in a search criterion and press the Search button.
On Rails 6 you can use for search action implementation in the controller.rb:
def search
keyword = params[:q] #you can get this params from the value of the search form input
#posts = Post.where("title LIKE ?", "%#{keyword}%")
end
I am trying to add a delete functionality to my model. This is what I've come up with, but even though I don't need to render the page to delete something, Rails renders and couldn't find the file for "delete.html.erb"
I am using Ruby 2.0dev and Rails 4.0
My delete link:
<%= link_to "Delete", reservation_delete_path(item), :class => "btn btn-small btn-danger", method: :delete, data: {confirm: 'Are you sure?'} %></td>
My routes file:
match 'reservations/delete/:id' => 'reservations#delete', via: :delete, :as => 'reservation_delete'
My Controller:
def delete
#current = Reservations.find(params[:id])
if current_user
if #current.user_id == current_user.id
#current.destroy!
redirect_to reservations_path
else
redirect_to reservations_path
end
else
redirect_to reservations_path
end
end
There is no need to duplicate the redirect 3 times for each condition. You can simplify your delete method:
def delete
#current = Reservations.find(params[:id])
if current_user && #current.user_id == current_user.id
#current.destroy!
end
redirect_to reservations_path
end
In your question, if current_user isn't available, you have no redirect, and so an implicit render is being run.
Your setup is not idiomatic, and there's code you didn't include, so anything could be going wrong. For example, that can't be your whole routes file; there's nothing specifying an index/show/edit/whatever page where your delete button would be. Another example: your action is named delete instead of destroy. Anyway I can show you an example that works and is much more canonical:
models/reservation.rb:
class Reservation < ActiveRecord::Base
end
controllers/reservations_controller.rb:
class ReservationsController < ApplicationController
def index
#reservations = Reservation.all
end
def destroy
#reservation = Reservation.find(params[:id])
#reservation.destroy
redirect_to reservations_url
end
end
views/reservations/index.html.erb:
<% #reservations.each do |reservation| %>
<%= link_to 'Destroy', reservation, method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
(this will literally only show links for deleting corresponding reservations... you'll have to stick <%= reservation.name %> or whatever in there if you want to see more info)
config/routes.rb:
Howdy::Application.routes.draw do
resources :reservations, only: [:index, :destroy]
root 'reservations#index'
end
(my app name is howdy)
You have some user auth going on, so add that accordingly. If you're inheriting from a controller that does special user-auth stuff before even hitting the action, that might be why it's trying to render delete.html.erb
Looks like you're missing a return with those redirects, which is actually causing Rails to both execute the redirect and try to render the view.
return redirect_to reservations_path
Two things:
The delete (destroy) action is part of resources when you specify it in the routes file. To do this the "rails" way, you might consider having your routes file look more like:
resources: :reservations, only: [:delete]
... then having the delete link be more like:
<%= link_to 'Delete', delete_reservation_path(item), :class => 'btn btn-small btn-danger', method: :delete, data: {confirm: 'Are you sure?'} %>
... and then in your controller you can:
def destroy
#current = Reservations.find(params[:id])
if current_user
if #current.user_id == current_user.id
#current.destroy!
redirect_to reservations_path
else
redirect_to reservations_path
end
else
redirect_to reservations_path
end
end
... or you could actually create an rjs template for the delete action to do some fancy javascript work, or you could simply render the view for the index action (faster load the redirecting).
My recommendation when you start putting up && gates is to check to see if there is an existing solution. In this case you're probably looking for the functionality that is available in the CanCan gem.
CanCan
basically you load_and_authorize your users before the controller action and check them through an Ability model. You also get view helpers like
if can? :destroy, reservation
... do awesome stuff here ...
This will be a far better solution over the long run.
I'm trying to destroy links that belong to a category model (through my browser). I can successfully delete a link that has an id of 1 and category_id of 1, but when I try to delete a link that has any other id I get hit with:
ActiveRecord::RecordNotFound in LinksController#destroy
Couldn't find Link with id=1 [WHERE "links"."category_id" = 1]
Very frustrating, because I'm not trying to delete a link that has an id of 1! But I see in the request parameters that it's always trying to delete a link with "category_id"=>"1",
"id"=>"1"}, no matter what link I click on. Looking at the links in my development database confirms they exist and have ids that are not 1...
Here's the code for LinksController#destroy:
class LinksController < ApplicationController
def destroy
#category = Category.find(params[:id])
#link = #category.links.find(params[:id])
#link.destroy
redirect_to category_url(#category)
end
Here's the code for the view where I'm trying to delete these pesky links:
<h1><%= #category.category %></h1>
<p><%= #category.description %></p>
<ul>
<% #category.links.each do |link| %>
<li>
<%= link_to link.title, link.url %> |
<%= link_to "delete", category_link_path(#category), :method => :delete %>
</li>
<% end %>
Edit: Added parameters
{"_method"=>"delete",
"authenticity_token"=>"[removed]",
"category_id"=>"1",
"id"=>"1"}
Edit: Added config/routes.rb:
LinkManager::Application.routes.draw do
resources :categories do
resources :links, only: [:create, :destroy]
end
root :to => 'categories#index'
What am I overlooking? Is there anything I can try?
Your call to category_link_path is ommitting something. Perhaps it should look like this?
<%= link_to "delete", category_link_path(#category, link), :method => :delete %>
It looks like you're fulfilling the category_id part of the route by passing in #category, but you also need to provide link as the id.
Then you need to fix your destroy action as such:
def destroy
#category = Category.find(params[:category_id])
#link = #category.links.find(params[:id])
#link.destroy
redirect_to category_url(#category)
end
On your category_link_path you should be passing your category as well as your link. something like
category_link_path(#category, link)
Also, on your controller, to find your category it should look like Category.find(params[:category_id]
I'm making resourceful routes for youtube videos. So, a person just pastes the youtube embed link in the form. In the controller I have a normal set of resourceful actions:
class VideosController < ApplicationController
def index
#videos = Video.all
end
def new
#video = Video.new
end
def create
Video.create(params[:video])
redirect_to :action => :index
end
def destroy
Video.destroy(params[:id])
redirect_to :action => :index
end
end
And in the view I'm just displaying it: (in Haml)
- #page_title = 'Video'
#videos
%ul
= list_of(#videos) do |video|
%h1= video.title
!= video.link
= link_to "Delete", video_path(video), :method => :delete
= link_to "Add new video", new_video_path
%p#top
= link_to 'Go to top ↑', '#'
For the one who don't use Haml, != escapes the string. video.link holds the YouTube embed code
The problem is that, when I create a new video, and when it redirects me back to the index page, the newly created video isn't displayed (the other ones are normally displayed). Only after I refresh the page, it's normally displayed.
I saw in the web inspector that the src attribute is missing from the iframe (so that's why the video isn't displayed). But when I look in the page source, everything is normal there. So, thinking it may be Javascript's fault, I tried disabling it. But nothing changed.
I don't think you want to escape it using haml... I think you want to call
video.link.html_safe
Note: if the user is pasting in the link, this is very unsafe.
Update --- If you have the javascript develop console open, you'll see this error pop up:
**Refused to execute a JavaScript script. Source code of script found within request.**
Check this answer for why it's refusing to due XSS Here's a method that is both safe and works. You'll paste in the youtube ID in the text field: ibWYROwadYs
index.erb
<% if session[:youtube].present? %>
<iframe width="480" height="360" src="http://www.youtube.com/embed/<%=session[:youtube]%>" frameborder="0" allowfullscreen></iframe>
<% end %>
<%= form_tag load_path do %>
<%= text_field_tag :youtube_id %>
<%= submit_tag "Submit" %>
<% end %>
<%= link_to "Clear", clear_path, :method => :delete %>
home_controller.rb
class HomeController < ApplicationController
def index
end
def smth
session[:youtube] = params[:youtube_id]
redirect_to :action => :index
end
def clear
session.clear
redirect_to :action => :index
end
end