Okay so I'm building a really simple list with items app, pretty much exactly the same as your standard to-do list application. I've managed to ajax-ify the creation of new 'points' within a list (point belongs_to :list and list has_many :points) but I'm having trouble with the 'destroy' action.
When I click on the destroy link in the browser, nothing visibly occurs, and I get the error Error: Syntax error, unrecognized expression: /lists/10/points/125 obviously with different values depending on the id of the list and point.
If I refresh the page or look at the db, it's clear that the entry has indeed been deleted. Without ajax, my destroy action works just fine. I feel like I must be missing something obvious, any ideas?
fyi the 'pro' attribute is just a boolean associated with every point.
points_controller.rb
def destroy
#point = #list.points.find(params[:id])
#point.destroy
respond_to do |format|
format.html { redirect_to list_url(#list) }
format.js
end
end
lists/show.html.erb
<% #list.points.each do |point| %>
<% if point.pro == true and point.valid? == true %>
<li class="weight-<%= point.weight %>"><%= point.content %>
<%= link_to "×".html_safe, [#list, point],
:remote => true,
:method => :delete,
:class=> "close",
:data => {:dismiss => 'alert'} %>
</li>
And it doesn't seem to matter what I put in views/points/destroy.js.erb, because the code doesn't seem to be getting executed.
Update
I figured it out, I had to change the path in the delete link to list_point_url(#list, point). The other problem was that my invalid javascript was causing a server error, so I didn't realize what the problem was (turns out #<%= dom_id(#point) %> needed to be wrapped in quotes).
Thanks all!
Maybe check if the delete link routes to the destroy controller action, because list_point_path doesn't really seem like a delete route.
Edit
Sorry for the lake of knowledge but I'm not sure what [#list, point] will produce as a route. This is what I have for a view of my own, just for your reference:
link_to "Delete", admin_photo_path(photo), :method => :delete, :confirm => "Delete this image?", :class => "btn-trash"
My admin_photo_path is a singular path that route to a single Photo instance; not a collection.
Edit
Simple way could be sending delete to the point object, maybe this could help?
link_to "×".html_safe, point,
:remote => true,
:method => :delete,
:class=> "close",
:data => {:dismiss => 'alert'}
Related
I am developing a rails application for a client. In a nutshell, it is for monitoring the progression of PhD uni students. One of the main functional requirements was for the user to be able to fill out reports online. The issue I am having is with one of the forms.
I am allowing the number of questions per form to be completely unrestricted, so I am using dynamic symbols to store the answers to the questions, and pass those answers to the controller in a hash. Here is a snippet of the code from the form, and the controller method:
<% #questions.each do |q| %>
<div class="field">
<!--Question Label -->
<%= s.send(:label, "Question #{q.question_number}") %>
<!--Link to delete question -->
(<%= link_to 'Remove', {:controller => "report_details", :action => "delete_question", :question_to_delete => q.id}, data: { confirm: 'Are you sure?' }, :class => 'form-link', :method => "post" %>)
<!--Question text box -->
<%= s.send(:text_area, "qu_hash[question#{q.question_number}]", :rows => 3, :cols => 60, :value => q.question) %>
<!--New Question Button -->
<%= link_to '>> Insert Question Here <<', {:controller => "report_details", :action => "add_question", :position_to_add => q.id}, :method => "post" %>
</div>
<% end %>
My issue is with with the line below I think. I will explain why below, but here is my controller method (accessed by submitting the form).
def save
questions = params[:report_detail][:qu_hash]
ReportDetailQuestion.where(:report_detail_id => #report_detail.id).each do |q|
q.update_attributes(:question => questions["question#{q.question_number}".to_sym])
end
redirect_to #report, notice: 'Report was successfully updated.'
end
The error I am getting is this:
undefined method `[]' for nil:NilClass
questions = params[:report_detail][:qu_hash]
ReportDetailQuestion.where(:report_detail_id => #report_detail.id).each do |q|
#Error occurs on the below line
q.update_attributes(:question => questions["question#{q.question_number}".to_sym])
end
The hash is not a part of the database, it is being used to update entries in the table of report questions (seperate to the report table). This error is being caused because the hash is not being submitted from the form (on the error screen - where it shows the params passed to the controller, the hash is not present).
Also, I am unsure how to permit this hash through the "white list" of the object, so if someone could help with that it would also be helpful (for now I am just permitting everything, so that won't be the issue. The field just isn't being submitted for some reason).
If you need more information let me know!
Cheers
For this problem I will advise you to use nested forms which is more suitable for this case mainly for user experience. For that, you need to create a question model first.
you can follow this railscast which explains well how to do...
Not sure it is what you are looking for...
I have setup a admin namespace in order to access models in the admin area: /admin/pages
However i have the following problem
i cant get the delete function to work under Admin::PageController for example or any of my models.
Does anyone know how to do this.
I have the following:
Admin::PageController I have the following
def destroy
#page = Page.find(params[:id])
#page.destroy
respond_to do |format|
format.html { redirect_to admin_pages_url }
format.json { head :ok }
end
end
Then on my page index file where i want a link to delete the record i have the following: (/admin/pages)
<%=link_to admin_page_path(page), :class => 'ico del' do %>
<%='Delete'%>
<% end %>
Does not seem to work. Anyone know how to get this to work?
you have missed :method option in link_to call
link_to 'Delete', admin_page_path, :confirm => 'Are you sure?', :method => :delete
or
<%=link_to admin_page_path(page), :class => 'ico del',:method => :delete do %>
<%='Delete'%>
<% end %>
The link_to helper defaults to a GET request unless you specify additional attributes to tell it how you want it to be handled.
In this case, you need to set some extra arguments:
<%=link_to "Delete", admin_page_path(page), :class => "ico del", :remote => true, :method => :delete %>
What actually happens in the background is the Rails UJS (unobtrusive javascript adapter) captures the click event and sends the request via AJAX. So you should see it hit your server with a POST (but it passes in _method => delete as well) to delete the object.
I'm also assuming you have your routes set up correctly. Something like:
namespace :admin do
resources :pages
end
I've got the following form:
<%= form_for(#subscription = #task.subscriptions.build(:user_id => subscribers.id)) do |f| %>
<%= f.check_box :subscribed, :class => 'submittable' %>
<%= f.label :subscribed, subscribers.full_name %>
<%= f.hidden_field :user_id, :value => subscribers.id %>
<%= f.hidden_field :task_id, :value => #task.id %>
<% end %>
The 'submittable' class on the checkbox causes the form to be submitted (via jQuery) on update.
:susbcribed is returned via a method in model that returns whether a user is subscribed or not - it cannot be modified directly.
The controller is available here: http://pastebin.com/zZy6KcXz - it is the standard scaffold.
When I click the checkbox, the subcription is successfully created, but I cannot work out how to get it to delete the subscription when unticked.
cjm, in follow up to jimworm's answer, the controller's destroy method is called when you DELETE (HTTP verb, it's actually a POST with a _method=DELETE field passed since some browsers don't support the DELETE verb.
as he said:
<%= link_to 'Delete', #model, :confirm=> 'Are you sure?', :method=> :delete %>
The route is the same as your show or GET /models/1 but the verb DELETE is used instead,
DELETE /models/1
which is actually
POST /models/1 with a hidden field _method=DELETE passed in order to support all browsers.
As he also mentioned, Rails automatically figures out which action to use when using form_for by checking to see if the #model is a new_record? (no id yet) or an existing one. It will then pick
POST /models for create
or
PUT /models/1 for update
It's a form_for #subscription, so it'll probably be submitting to the create or update actions, which don't destroy models. You could hack the action or the model to make it destroy on create(!)/update. Probably the action... updating the model for this hack gives me the heeby-jeebies.
The Rails way™ to the DELETE method and get to the destroy route is a link like this:
<%= link_to 'Delete', #model, :confirm=> 'Are you sure?', :method=> :delete %>
Watch out for IE9 though. If you let your redirects go to another "deleteable" it'll potentially go up the chain and delete your entire database. http://techno-weenie.net/2011/8/19/ie9-deletes-stuff/
The correct redirect after successful POST, PUT and DELETE is:
redirect_to path, :status => 303
I'm trying to put together a form_tag that edits several Shift objects. I have the form built properly, and it's passing on the correct parameters. I have verified that the parameters work with updating the objects correctly in the console. However, when I click the submit button, I get the error:
ActiveRecord::RecordNotFound in ShiftsController#update_individual
Couldn't find Shift without an ID
My route for the controller it is calling looks like this looks like this:
map.resources :shifts, :collection => { :update_individual => :put }
The method in ShiftsController is this:
def update_individual
Shift.update(params[:shifts].keys, params[:shifts].values)
flash[:notice] = "Schedule saved"
end
The relevant form parts are these:
<% form_tag( update_individual_shifts_path ) do %>
... (fields for...)
<%= submit_tag "Save" %>
<% end %>
Why is this not working? If I browse to the url: "http://localhost:3000/shifts/update_individual/5" (or any number that corresponds to an existing shift), I get the proper error about having no parameters set, but when I pass parameters without an ID of some sort, it errors out.
How do I make it stop looking for an ID at the end of the URL?
I think that you need to tell the form tag helper you want to use PUT instead of POST
<% form_tag( update_individual_shifts_path, :method => :put) do %>
... fields ....
<%= submit_tag "Save" %>
<% end %>
Amazingly, it turns out that I was able to fix this by a combination of renaming the method and passing a dummy variable. Changes were to the lines:
form.html.erb:
<% form_tag( poop_individual_shifts_path ) do %>
routes.rb:
map.poop_individual_shifts "poop_shifts", :controller => 'shifts', :action => "poop_individual", :method => "put", :id => 4
map.resources :shifts
There I pass it an ID of 4 every time, it doesn't matter, it's not actually doing anything with the shift object it goes and grabs, it's just ... I don't know, a hack, I guess.
shifts_controller.rb:
def poop_individual
First of all, I'm new at Ruby on Rails, so if there's a better practice than what I'm doing, please let me know.
What I'd like to do is to have multiple ajax submit buttons to perform different actions for a list of items with check boxes. So, when I select as many check boxes as I want, then I can choose what to do with them.
I could partially solve this using ajax as follows:
remote_form_for :profile, :url => {:controller => 'announcements', :action => 'deactivate'}, :html => { :method => :put} do |f|
f.submit 'Publish', :confirm => 'Are you sure?'
#Then the list
This works great. What I'd like to do now is to add another "submit" or button, so I can perform several actions, so I guess the :url statement at the remote_form_for will be replaced for something like that per each button. For example:
Publish button: perform some action in some controller.
Deactivate button: perform another action.
Mark as Read: perform another action.
Is it clear?
add as many "submits" as you like. All submits have the 'name' in the input tag set to 'commit' and the value set to the label. So you can check by looking in the params submitted:
remote_form_for :profile, :url => {:controller => 'announcements', :action => 'deactivate'}, :html => { :method => :put} do |f|
f.submit 'Publish', :confirm => 'Are you sure?'
f.submit 'Something Else"
# Then the list
in the controller
def deactivate
case params[:commit]
when 'Publish' then do something
when 'Something Else' then do something else
end
end
Finally, I could solve it by myself.
It's well known there's a bug for multiple submit buttons on ajax forms. I used the hidden workaround as explained here.
Thanks,
Brian