Uploading file yields 406 (Not Acceptable) error - ruby

I am trying to upload a file using sample code. I am not getting any compilation errors but a 406 Not Acceptable error message. What does this mean?
POST request:
Started POST "/files/upload" for 10.15.24.38 at 2012-06-22 21:18:11 -0400
Processing by FilesController#upload as HTML
Parameters: {"utf8"=>"รข", "authenticity_token"=>"wfpBi3Y8KgmqitXrh4fZ3xfun73mWOfXiTQ+J7bdfWU=", "user_id"=>"231",
"button"=>"", "upload"=>{"datafile"=>"ws_1920x1080.jpg"}}
View:
<%= form_tag files_upload_path, :remote => true, :method => :post, :multipart => true do %>
#The form has some other values too. I am keeping it short here.
<p>
<label for="upload_file">Select File</label> :
<%= file_field 'upload', 'datafile' %>
</p>
<% end %>
Controller:
def upload
#The controller has some other values too, that are not related to file upload.
if params[:datafile]
uploaded_io = params[:upload][:datafile]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'w') do |file|
file.write(uploaded_io.read)
end
end
if params[:user_id]
#do some extra stuff
end
respond_to do |format|
format.js
end
end
Error:
Completed 406 Not Acceptable in 2736ms (ActiveRecord: 3.2ms)

There isn't enough information to provide the answer but you're clearly missing :multipart => true in our form_for call as in:
<%= form_for #upload, :multipart => true do |f| %>
Your form code here
<% end %>
And the not acceptable error happens because you're asking for HTML rendering but there is probably not a respond_to piece answering to HTML.

You are not allowed (in direct way) to upload files through remote request. Take a look here: How can I upload files asynchronously?

I guess you cant upload a file using ajax just by specifying remote => true you need some sort of plugin or something like it to do it like
remotipart , plupload , uploadify or something like it .
so if you are not using any plugin then even if you specify remote => true the form would be sent as normal HTML request instead of XMLHttpRequest
Now since in your controller you have removed
format.html part as you are assuming that it would be an ajax request but in reality it is not (HTML request)
becoz Rails cannot find the appropriate format to respond back it is reporting 406 Not Acceptable
Do your self a favor log the request.xhr? method in your controller.
something like
logger.info "******************** #{request.xhr?} *********************"
If request.xhr? return nil that specify that request is not an ajax request

Related

Remote Form Renders as HTML instead of JS

I have a simple form:
<%= form_for [current_user, #bookcase], :id => "shelf_update_form", :remote => true, :html => { :multipart => true} do |f| %>
<input id="bookcase_image" class="file" type="file" name="bookcase[image]" size="13">
<% end %>
That automatically uploads when a file has been selected:
$("#shelf_update_form").change(function() {
$("#shelf_update_form").submit();
});
I want the update action to render js view, but by default it renders html instead. I try forcing it to render js like so:
respond_to do |format|
format.js
end
But then I get this error:
NetworkError: 406 Not Acceptable
Even then, my log reports:
Processing by BookcasesController#update as HTML
How can I get it to process as JS instead?
UPDATE:
The view:
triggerAjaxHistory("<%= #href %>", false);
I get the same results with a more generic view, too:
alert("I work now!")
In the controller, do
respond_to do |format|
format.js if request.xhr?
end
Is your view named as .js.erb?
Can you check using firebug in your browser what exactly you are getting as the response? Turn on net logging and look at the response.
Also do you have the following in your layout?
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
Can you put in logger.info whatever_message commands to make sure you the controller action executes and you go into the correct view?
What happens if you specify the js format specifically in the controller as
class UserController < ApplicationController
respond_to :js, :only => :update, :layout => 'false`
What happens if you specify the format in form_for as :format => :js
Is your form nested within another form?

Problem using link_to with remote option in rails 3

I'm working on rails 3 with link_to remote option.
This is my code structure.
View/punch/report.html.erb :
<%= link_to 'Punch report', punchreport_punch_index_path, :remote => true%>
<div id="punchform"> </div>
View/punch/punchreport.js.erb :
$("#punchform").html("<%= escape_javascript(render(:partial => "reportform"))%>");
and created a form inside
View/punch/_reportform.html.erb
and controller :
controller/punch_controller.rb
def report
end
def punchreport
respond_to do |format|
format.html { render report_punch_index_path }
format.js
end
end
note : punchreport_punch_index_path : /punch/punchreport
report_punch_index_path : /punch/report
I don get the ajax request working. instead of that, it redirects the page.
Any help
Thanks in advance
Sounds like your :remote => true is not being handled by an unobstrusive javascript event handler...
Do you have something called jquery-rails in your project? it should set a handler on "data-remote" attribute. Can you find it and post back what you have there?

Problem rendering an Ajax partial with link_to specifying a controller action

I have a div (id="content") on a "proposition" show page into which I want to render different partials depending on which tab at the top of the div is selected.
I'm trying to render a partial (substantive_content) with AJAX using the following link_to:
<%= link_to "Connected", :url => {:controller => "propositions",
:action => "substantive_content"}, :remote => true %>
I've got two problems:
On clicking the link, a GET request
is sent to
PropositionsController#show, and
not (I presume) to the "substantive
content" action. This just refreshes the page and doesn't do anything remotely. The correct partial isn't displayed.
I'm not sure how then to render a
partial into the "content" div.
At the moment I have this in the PropositionsController:
def substantive_content
respond_to do |format|
format.js{ render :update do |rightbar|
rightbar.replace_html 'content', 'Hello World!'
end}
end
end
... but am not sure where to go from here. Am I even going about this in the right way? I'm very new to rails, javascript, etc.
Any help with either of these problems would be fantastic. Thanks!
In your routes.rb file you should have an entry for the substantive_content action. It might look something like this:
match "substantive_content" => "propositions#substantive_content", :as => substantive_content
Then in your view the link should look something like this:
<%= link_to "Connected", substantive_content_path, :remote => true %>
I would render a js.erb file when the js request comes to the substantive_content action. The action would look soemthing like this:
def substantive_content
respond_to do |format|
format.js
end
end
Then create a substantive_content.js.erb file in your views/propositions directory. In that file you can use jquery to update the content div:
$('#content').html("<%= render :partial => 'your_partial_name_here' %>");
Without knowing more about the actual application you're working on, its hard to say if this is the best way to accomplish what you want. I generally try to stay as "RESTful" as possible with my apps so I'm reluctant to create actions aren't part of the normal index, new, create, show, etc. set. That's not to say that it isn't neccesary in this case, but it's something to think about.

Rails 3.1 ajax:success handling

So Im playing with CoffeeScript, Rails 3.1 all the good stuff. I have a resource with all the usual routes index, show, create, edit, update, destroy.
The index view has a form that uses :remote => true like so:
<%= form_for #todo, :remote => true do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In the controller for create I have the following:
def create
#todo = Todo.new(params[:todo])
respond_to do |format|
if #todo.save
format.html { redirect_to #todo, notice: 'Todo was successfully created.' }
format.json { render json: #todo, status: :created, location: #todo }
format.js {render json: #todo }
else
format.html { render action: "new" }
format.json { render json: #todo.errors, status: :unprocessable_entity }
end
end
end
Im trying to not use .js.erb views as I would rather handle the JSON returned and do all the fancy appends to the todo list and so on. (It just feels cleaner to me).
In my todos.js.coffee I have used the following:
$(document).ready ->
$("#new_todo")
.bind "ajax:success", (event, data) ->
alert("Ajax SUCCESS!!!")
(Yeah just tyting to open an alert box does not work) I tried loads but just cannot trigger this event. The request does complete successfully and the new todo is added.
Any help with this would be appreciated. Thanks
Started to pour over the rails.js and wondered if any of the ajax: callbacks were being raise.
Turned out they were well the beforeSend and error... hang on... error? How could this be? The creation of the new todo happens successfully, the response is the JSON I expect. But on stepping through the callback code I notice an Invalid label error.
Quick google later brings me to this post http://blog.seqmedia.com/?p=484
Turns out the JSON is being returned as a string, Firbug got that and parsed it correctly so I could check the response. However rails.js and js in general didnt know how to handle the string and threw the above error (rather silently I may say).
The solution was in the respond_to
format.js {render json: #todo, content_type: 'text/json' }
A bit thanks to Trevor Burnham (like the book BTW) for his help and Amy from sequence media whose blog post ultimately gave me the solution.
What is #new_todo? Does an element with that ID exist? Verify that $('#new_todo').length > 0 in your code, and that it's the right element to bind your event handler to.
What is ajax:success? The jQuery API defines an ajaxSuccess event (see the Ajax Events docs), but I've never seen the version with the colon before.

Rails3 routing error with ajax

UPDATED CODE at the bottom
I am creating a story voting app via Simply Rails 2 book. I am getting this error when I click the button to vote up a story:
No route matches "/stories/4-pure-css-icons-showcase"
My routing file looks like this:
Shovell::Application.routes.draw do
get "votes/create"
root :to => "stories#index"
resources :stories do
resources :votes
end
end
votes_controller.rb:
class VotesController < ApplicationController
def create
#story = Story.find(params[:story_id])
#story.votes.create
end
end
create.rsj :
page.replace_html 'vote_score', "Score: #{#story.votes.size}"
page[:vote_score].visual_effect :highlight
show.html.erb:
<h2>
<span id="vote_score">
Score: <%= #story.votes.size %>
</span>
<%= #story.name %>
</h2>
<p>
<%= link_to #story.link, #story.link %>
</p>
<div id="vote_form">
<%= form_tag :url => story_votes_path(#story), :remote => true do %>
<%= submit_tag 'shove it' %>
<% end %>
</div>
story.rb :
class Story < ActiveRecord::Base
validates_presence_of :name, :link
has_many :votes
def to_param
"#{id}-#{name.gsub(/\W/, '-').downcase}"
end
end
I've been working through a number of other errors before this having to do with deprecated code and so forth, so I feel somewhat lost at the moment. It seems like it should just be a routing a issue, but since I've been working through AJAX errors that also have to do with the vote function I wanted to post those files just in case it was more than routing.
It says no route matches "/stories/4-pure-css-icons-showcase" but when I visit "/stories" (my root) and click on the link to take me to "/stories/4-pure-css-icons-showcase" it works fine, however after clicking on the vote button I get this error. As you could probably tell after reading the code, it is suppose to update the vote count and do a :highlight via ajax.
UPDATE:
Changed code (all changes are per Sam's advice):
routes:
Shovell::Application.routes.draw do
resources :votes
root :to => "stories#index"
resources :stories do
resources :votes
end
show.html.erb:
<div id="vote_form">
<%= form_tag :url => new_story_vote_path(#story), :remote => true do %>
<%= submit_tag 'shove it' %>
<% end %>
</div>
votes_controller.rb
class VotesController < ApplicationController
def create
#story = Story.find(params[:story_id])
#story.votes.create
respond_to do |format|
format.html
format.js
end
end
The problem is still exactly the same, but I think (read: hope) we are making progress!
The scenario: My index (/stories) page randomly displays a story from the database, when you click the link it takes you to the story's internal page (ex. /stories/2-sitepoint-forums) on this page it displays the number of votes the story has and has a button to vote for it. When you click the vote button it is suppose to use ajax to update the #story.vote.size and use a :highlight visual effect. However, the problem is that when you click the vote button the page changes to a "Routing Error" page which displays:
No route matches "/stories/2-sitepoint-forums"
Its weird to me because you can in fact be routed to that address and you are from the link on the first page...
Here is the error in the console:
Started POST "/stories/2-sitepoint-forums?url=%2Fstories%2F2-sitepoint-forums%2F
votes%2F2-sitepoint-forums&remote=true" for 127.0.0.1 at 2010-11-08 16:30:17 -08
00
ActionController::RoutingError (No route matches "/stories/2-sitepoint-forums"):
Rendered C:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.0.rc2/lib/action_dis
patch/middleware/templates/rescues/routing_error.erb within rescues/layout (1.0m
s)
Im not sure if this is any more telling, but I thought I'd add it incase.
New:
I have not been able to solve this problem as of yet. Because I still don't feel like I completely understand the issue I have decided to move over to the Ruby on Rails 3 Tutorial Book online and see if I can't figure it out while working through it. Since I was planning to do it next anyway (I have plans to combine both apps later) it appears now is the time.
<%= form_tag :url => new_story_vote_path(#story), :remote => true do %>
<%= submit_tag 'shove it' %>
<% end %>
That should send it to the create action.
def create
#story = Story.find(params[:story_id])
#story.votes.create
respond_to do |format|
format.html
format.js
end
end
And that should take care of your ajax.
take this get "votes/create" out of your routes
and add this
map.resources :votes
I'm not familiar with using form_tag and :remote (as I normally just write jQuery for stuff like this) but a couple of things definitely pop out at me with what you're doing here that may help you resolve the issue.
First of all, I think you can rework the way you set up a vote and thus the way you set up the form for the vote. In the stories controller, for the show action, I'd set up the vote right away:
#vote = Vote.new(:story_id => #story.id)
This lets you set up your form as so:
= form_for(#vote), :remote => true do |f|
= hidden_field f.story_id
= submit_tag "Vote"
This is both a cleaner way of doing things, in my opinion, but also may fix the general issue you are dealing with, because you are now passing data with the form (the hidden field) in your POST request. Rails will behave unexpectedly if you perform AJAX POST requests that do not actually submit data.
In other words, your original form is likely running as an AJAX POST request but it would have worked better as an AJAX GET request, since it is not actually submitting data, it is simply "hitting" an URL.
I am not sure if you found the answer to your problem yet, but I wanted to post for others that may be looking for an answer similar to yours.
The code:
<%= form_tag :url => new_story_vote_path(#story), :remote => true do %>
<%= submit_tag 'shove it' %>
<% end %>
will result in /stories/:story_id/votes/new url with a :post request. It won't work because the new route is a :get method request. If you wanted to go to the new method, you'll need to tell the form to use the get http method.
<%= form_tag :url => new_story_vote_path(#story), :remote => true, :html => { :method => :get } do %>
<%= submit_tag 'shove it' %>
<% end %>
However, I think that you are wanting to route to the create method in your controller. I would do something like:
<%= form_tag :url => story_votes_path(#story), :remote => true do %>
<%= submit_tag 'shove it' %>
<% end %>
This should route correctly to the create method in your VotesController.

Resources