Delete action not working in Rails - Parameter Missing - ruby-on-rails

I'm trying to add a delete action to my app, and I'm getting an odd error that I"m having trouble tracking down. It seems like the create action is being triggered even though I've assigned the button to the delete action. Based on the URL when I click on the delete button, it seems like it might be using GET, which I'm pretty sure isn't correct.
Any help is much appreciated!
Here's the error I'm getting when I click on a delete button in the index view.
class DogsController < ApplicationController
def create
Dog.create(dog_params)
#dogs = Dog.all
redirect_to dogs_path
end
def new
#dog = Dog.new
end
def edit
end
def delete
#dog = Dog.find params[:id]
#dog.destroy
redirect_to dogs_path
end
def show
#dog = Dog.find params[:id]
end
def index
#dogs = Dog.all
end
private
def dog_params
params.require(:dog).permit(:name, :breed)
end
end
And here's the code for the index view:
<h1>List of Dogs</h1>
<table>
<thead>
<tr>
<td>Name</td>
<td>Breed</td>
<td>Details</td>
</tr>
</thead>
<% #dogs.each do |d| %>
<tr>
<td><%= d.name %></td>
<td><%= d.breed %></td>
<td><%= d.id %></td>
<td><%= link_to 'Details', dog_path(d.id) %></td>
<td><%= link_to 'Edit', edit_dog_path(d.id) %></td>
<td><%= button_to 'Delete', :method => :delete %></td>
</tr>
<% end %>
</table>

Rails will be looking for destroy not delete in your controller.
Change def delete to def destroy
Aha also noticed you're not specifying what you want to delete:
<%= button_to 'Delete', d, :method => :delete %>
Also in your create you're getting all Dogs then redirecting which is a waste, remove the #dogs = Dog.all query.
#dogs = Dog.all
redirect_to dogs_path

button_to must pass in a parameter like this
button_to 'Delete', dog, method: :delete

Related

creating a button to update a database entry in ruby

I have created a database of ideas with a votes field. I want users to be able to press a button to increase the vote count of an idea and then refresh the screen. I have created a method called increment_vote, but cannot seem to find how to save the new vote value in my database. This is my part of my index.html.erb code:
<% #ideas.each do |idea| %>
<tr>
<td><%= idea.content %></td>
<td><%= increment_vote(idea) %></td>
<td><%= link_to 'Vote', ideas_path(:mode => "Vote"), :class => "button", :method => :get %></td>
</tr>
If I call the increment vote method from the link to vote code, I get an "undefined method `to_model' for true:TrueClass. Did you mean to_yaml" error.
This is my method code in the ideas.controller:
helper_method :increment_vote
def increment_vote(idea)
idea.votes +=1
idea.save
end
This is currently causing the error, but it is increasing the vote of the first idea in the table.
Can anyone please help?
You can't call increment_vote method from view, you need to create controller action for it and call it when the user clicks the link
# views/ideas/index.html.erb
<% #ideas.each do |idea| %>
<tr>
<td><%= idea.content %></td>
<td><%= link_to 'Vote', upvote_idea_path(idea), class: "button", method: :post %></td>
</tr>
<% end %>
# routes.rb
resources :ideas do
post :upvote, on: :member
end
# ideas_controller.rb
def upvote
Idea.find(params[:id]).upvote
redirect_to :index
end
# models/idea.rb
def upvote
update(votes: votes + 1)
end

How to sort and display by title in Ruby on Rails?

I have been try examples the past couple of days with no luck.
I have a table named Article with columns such as bullet, powder, and calibertitle. I set up a form in which I can enter in particular details such as bullet brand, powder brand, caliber name, etc.
I am using SQLite.
How can I search for a particular word in a title and only display the title and corresponding info if the title has that word?
I can list all data but I am not sure how to sort through it. I would also like to do something like listing data in alphabetical order.
Also, if I created another controller, is it possible for me to list/display the same columns under the new controller?
/views/articles/index.html.erb
<h1>Load Data</h1>
<table>
<tr>
<th>Bullet</th>
<th>Powder</th>
<th>Caliber</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.bullet %></td>
<td><%= article.powder %></td>
<td><%= article.calibertitle %></td>
<td><%= link_to '[View]', article_path(article) %></td>
<td><%= link_to '[Edit]', edit_article_path(article) %></td>
<td><%= link_to '[Delete]', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<%= link_to 'Back', controller: 'welcome' %>
<p>
</table>
articles_controller.rb
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
end
/models/article.rb
class Article < ApplicationRecord
validates :calibertitle, presence: true,
length: { minimum: 3 }
end
In your controller assuming you have a column named calibertitle:
def index
#articles = Article.all.order(:calibertitle)
end
To get a Articles with a specific value in a field: Article.where(calibertitle: '308')
You can try this in rails console just to verify. You can also do .reverse_order(:field) if you need it sorted in... reverse.

Rails: wrong number of arguments (0 for 1)

I keep getting an error saying I'm not passing an ID when I'm trying to destroy a Feature, but I'm doing this using a set_feature before_action!
Full error:
wrong number of arguments (0 for 1)
Extracted source (around line #63):
private
# Use callbacks to share common setup or constraints between actions.
def set_feature(params)
#feature = Feature.find(params[:id])
end
Rails.root: C:/Users/Nick/Amnesia_Rails/Master
Application Trace | Framework Trace | Full Trace
app/controllers/apps/elements/features_controller.rb:63:in `set_feature'
Request
Parameters:
{"_method"=>"delete",
"authenticity_token"=>"0Z/SxhhEO6OA6eiShd+1PZI0DQ9QK1I7G8wqoInz+vM=",
"element_id"=>"3",
"id"=>"5"}
The show views:
<% #app.elements.each do |element| %>
<tr>
<td><b><%= element.name %></b></td>
<td><b><%= element.description %></b></td>
<td><b><%= link_to "Remove", [#app, element], method: :delete, confirm: "Are you sure?" %></b></td>
</tr>
<% element.features.each do |feature| %>
<tr>
<td><%= feature.name %></td>
<td><%= feature.description %></td>
<td><%= link_to "Delete", [element, feature], method: :delete %></td>
</tr>
<% end %>
<tr>
<td><%= link_to 'Add a Feature', new_element_feature_path(element) %></td>
</tr>
</tr>
<% end %>
The destroy and private methods:
def destroy
#feature = Feature.find(params[:id])
#feature.destroy
#element = Element.find(params[:element_id])
redirect_to(#element.app)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_feature(params)
#feature = Feature.find(params[:id])
end
Any help would be appreciated! I'm quite lost!
I think 0 for 1 is pretty clear for you.
def set_feature(params)
end
That's wrong. (params) is your 1. If you aren't passing something to it, that's 0. And you're not.
Just make your before_action this:
def set_feature
#feature = Feature.find(params[:id])
end
The before_action isn't going to pipe in the params magically.
I think you should be able to access "params" without having it as an parameter of set_feature.

My controller is -persistently- sending wrong params[:id] in Rails?!

I'm new to Ruby on Rails & to web programming.
In my application I have two models; Directorate which has_many :users, and User which belongs_to :directorate.
When creating a new user, I use <%= f.collection_select(:directorate_id,Directorate.all, :id, :name) %> in the new.html.erb form to assign the new user to specific directorate. However, I want to build a user-friendly interface for the dba that lists all directorates; and listing all users beside each directorate, with a link to assign any user to a specific directorate.
What I did is the following:
In Directorate model, I defined the following function:
def assign_user!(user)
user.update_attributes(directorate_id: #directorate)
end
and in the directorates controller, I defined the following action:
def assign_user
#directorate = params[:directorate]
assign_user! params[:user]
redirect_to directorates_url
end
Now, directorates/index.html.erb contains the following:
<h1>Listing directorates</h1>
<table>
<tr>
<th>Name</th>
<th>Info</th>
</tr>
<% #directorates.each do |directorate| %>
<tr>
<td><%= directorate.name %></td>
<td><%= directorate.info %></td>
<td><%= link_to 'Show', directorate %></td>
<td><%= link_to 'Edit', edit_directorate_path(directorate) %></td>
<td><%= link_to 'Destroy', directorate, confirm: 'Are you sure?', method: :delete %></td>
<%= #directorate = directorate%>
<%= render 'users_form' %>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Directorate', new_directorate_path %>
and, -users_form.html.erb contains the following form (which is supposed to list all users beside each directorate, with a link to assign any user to a certain directorate):
<h1>Listing Users</h1>
<table>
<tr>
<th>User Name</th>
</tr>
<% #users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= link_to 'Assign to Current Directorate', {controller: 'directorates', action: 'assign_user', directorate: #directorate, user: user}, :method => :put %></td>
</tr>
<% end %>
</table>
<br />
Here is the problem, when listing directorates & click on the 'Assign to Current Directorate' I receive the following error:
http://127.0.0.1:3000/directorates/assign_user?directorate=4&user=5
ActiveRecord::RecordNotFound in DirectoratesController#update
Couldn't find Directorate with id=assign_user
Rails.root: /home/ehab/sites/IAMS
Application Trace | Framework Trace | Full Trace
app/controllers/directorates_controller.rb:61:in `update'
Request
Parameters:
{"_method"=>"put",
"authenticity_token"=>"L5tz3hv2IW0meE79qUq0/tjfGKwDlpC23hOeAWtmTvk=",
"directorate"=>"4",
"user"=>"5",
"id"=>"assign_user"}
It's clear that the params is submitting "id"=>"assign_user" which I don't want, what i want is "id"=>"directorate.id" (4 in the above example). What shall I do to fix this issue?!
first of all your routes should say that assign_user is a member method on a certain directorate object:
resources :directorates do
member do
put :assign_user
end
end
second you say you define assign_user! in Directorate model and assign_user in DirectoratesController but both methods imply that they share same object state like instance variable #directorate which is not true
your controller method assign_user should look vaguely like
def assign_user
#directorate = Directorate.find params[:id]
#user = User.find params[:user_id]
#directorate.assign_user! #user
end
and model method should look like
def assign_user!(user)
user.update_attributes(directorate_id: self.id)
end
and even that i would switch around to instead of telling Directorate to change user's attributes you would tell User to assign itself to whatever controller wants.
and the final bit is your link that assigns user to directorate:
link_to 'Assign to Current Directorate',
assign_user_directorates_path(#directorate, :user_id => user)
0 lines of code above were tested for even syntactical correctness, DO NOT copy-paste, read and understand

Help with rails link_to and post methods

I need help assigning students to batches.. they are in a many to many relation.
<tbody>
<% Batch.all.each do |b|%>
<tr>
<td><%= b.course.name%></td>
<td><%= b.name %></td>
<td><%= b.section_name%></td>
<td><%= link_to "Add", student_batch_students_path(#student, :batch_id=> b.id), :method=> :post%></td>
</tr>
<%end%>
</tbody>
In my controller
def create
#batch_student = BatchStudent.new(params[:batch_student])
#batch_student.save
end
My routes
resources :students do
resources :batch_students
end
resources :batches
But on my database it creates it with student_id and batch_id as null
You are updating exist batch, but not creating, so you should make PUT request to update action
<td><%= link_to "Add", student_batch_students_path(#student, :batch_id => b.id), :method=> :post %></td>
def create
#student = Student.find(params[:id])
#batch = Batch.find(params[:batch_id])
#batch_student = BatchStudent.new(:params[:batch_student])
#batch_student.student = #student
#batch_student.batch = #batch
#batch_student.save
end
The params hash doesn't contain a :batch_student hash because you are not submitting from a form. The params has should look something like {"student_id" => 1, "batch_id" => 1, "method" => "post"}.
So, modify your create action as follows:
def create
#batch_student = BatchStudent.new(params)
#batch_student.save
end
# or, a shorter version
def create
#batch_student = BatchStudent.create(params)
end
The advantage of using new is you can do a if #batch_student.save to check for errors.
I hope this helps.
The parameters and the http method should be together {:batch_id=> b.id, :method=> :post}
<%= link_to "Add", student_batch_students_path(#student), {:batch_id=> b.id, :method=> :post} %>

Resources