form not processing as JS - ruby-on-rails

So I have the following rails form, and the corresponding controller action has respond_to :js, but rails keeps processing it as HTML. Not really sure how to proceed. Any ideas?
form_tag url_for(controller: 'posts', action: 'add_tag'), id: 'enter_tag', remote: true, style: 'display:none' do
text_field_tag :tag
end
UPDATE: removing 'display:none' fixes it (I was having the form fade in.) Why is this?

Chris, are you using Rails 3.1? If so, (I believe, i'm on 3.0.10 still) the jQuery UJS library is automatically includeed. If that's the case, it should be using a / datatype request, but I believe rails should notice it's an xhr request and send it to the JS response automatically.
A quick solution may be changing the url_for to url_for(controller: posts, action: 'add_tag', format: 'js') but I believe it should pick the JS response even without that. I don't like this approach though because I don't believe it would ever pick your HTML response for non-js Users.
Another fix may be to put format.js as your first response format in the controller (it may be HTML now), but I"m missing the reason as to why it's not recognizing it as an Ajax request to begin with?

Related

Upload file to server is going through normal request, while ajax is not working Ruby on Rails

i am currently trying to upload a file with an ajax request on rails. My controller code is (main action):
def changePage
#welcome = WelcomeController.new
respond_to do |format|
format.html
format.js
end
end
My application is single paged, and the pages are changed via ajax requests and everything is working (but i am doint it with link_to, while in this case i use form_for - i do not know if this can be the cause). So in the view (changePage.html.index) i am rendering a partial view (_main.html.slim) which has the following code:
= form_for(:uploaded_file, :remote => true, :url => {:action => 'changePage'}, :html =>
{:multipart=>true}, :authenticity_token => true) do |f|
div class="browse"
span
| Choose file..
= f.file_field :uploaded_file
div id="file-status"
| You have not selected any files yet.
= f.submit :value => "Upload"
So when the Upload button is triggered i end up with a normal request to the server, and not an ajax request (i have changePage.js.erb file). So if someone has some idea about why this is happening it would be nice. {:
Thanks in advance!
For ajax upload you can use gem remotipart.
I am using a javascript plugin File-Uploader . It's simple and works well . I hope it would help you ^_^
You cannot just upload file with an AJAX request, it's technically impossible. So, your options are:
Use normal upload with full page request to keep it simple.
Use ugly hacks e.g. hidden iframe to achieve AJAX-like upload.
Use third-party uploader (there are plenty of them).
I suggest either option #1 or #3, depending on your requirements. #1 if you just need a simple upload, #3 if you need advanced features e.g. multiple files upload, drag & drop upload, chunked upload (for large files) etc.

Rails link_to with remote: true processing html instead of js after page refresh

I have a search page in my app, where there is an ajax search form. The search form works properly, passing parameters to the model to filter the search, and the model returning a collection of results. Upon search submit, #results are rendered on the page. Each #result then has a link to an action on it, like:
<%=link_to "Message", message_user_path(:id => user.id), :remote => true%>
Where this action in the controller is:
respond_to :js, :html
def message
#user_id = params[:id]
#user = User.find_by_id(#user_id)
respond_to do |format|
format.html
format.js
end
end
and this responds with message.js.erb, which triggers a messaging panel to pop up with a message to the user. All of this is working correctly, checking the log I see the correct get request sent, and the correct format being processed:
Started GET "/users/3/message"
Processing by UsersController#message as JS
However, if I refresh the page and try to click the same link that was working before, I get the error Template is Missing. Checking the log, I see that now there are two requests sent, first an html then the same js request.
Started GET "/users/4/message"
Processing by StudentsController#message as HTML
...
Completed 406 Not Acceptable in 3ms (ActiveRecord: 1.0ms)
Started GET "/users/4/message"
Processing by StudentsController#message as JS
The html request throws the missing template error. Does anyone know why refreshing the page causes rails to attempt to respond with an html request to a remote link?
EDIT: routes.rb
resources :students do
member do
get 'message'
end
end
Does your app/assets/javascripts/application.js contain
//= require jquery
//= require jquery_ujs
?
And your erb contains <%= javascript_include_tag "application" %>?
I was just struggling with a problem like this for HOURS and the last of those two points fixed it; I saw the first point mentioned in some other questions so I'll repeat it here.
Hope that helps.
(Credit where credit's due)
What solver it for me was adding :format => "js"
So in your case:
<%=link_to "Message", message_user_path(:id => user.id, :format => "js"), :remote => true %>
In general, when you use link_to on a particular button or so, when you press the button, as js request is send to the controller, but also searches for the respective .js.erb file and so on.
My solution was to replace
format.json do
with
format.js do
you can troubleshoot the request by setting a breakpoint (i use pry) in the controller and then look at the variable
request.format
For newer versions of Rails, this should be fixed where using remote: true within the link_to code, as the original poster was doing, will only look for a .js format to respond with. As others have said, if you never need an html response, then you can remove that from your code all together; you won't even need a respond_to, respond_with, etc as Rails will auto respond with JS looking for the template you already have made. So your controller code would look like this:
def message
#user_id = params[:id]
#user = User.find_by_id(#user_id)
end
And the link would still be this:
<%=link_to "Message", message_user_path(:id => user.id), :remote => true %>
Or this would work as well (my preferred way of syntax):
<%=link_to "Message", message_user_path(id: user.id), remote: true %>
This code will call the controller action which will look for the template message.js.erb.
I know this question is old now, but for anyone looking for answers and using current Rails 6+ (I'm using 7.0.0alpha), and if you are getting this same type of issue where both HTML and JS templates are being requested; check that turbolinks is not what is causing the issue. Sometimes turbolinks can cause a request to be sent twice and it may be sending the first request as an HTML request.
My form with remote: true was inside another form and I didn't know it.
So make sure it isn't inside another form.

Rails 3: How to make an Ajax call?

I would like to have a link (is there a better option?) on my page which will make an Ajax request when clicked. (I would like to update a field in my database when the link is clicked.)
What is the simplest way to achieve this ?
Could you refer me to some tutorials ?
Really simple. In your view, have a link/button like so. Important bit being :remote => true
<%= link_to 'Update Thingy', update_thingy_path, :confirm => 'You sure you wanna update?', :remote => true %>
or
<%= button_to('Update Thingy', {:action => 'update_thingy', :thingyid => 314}, :method => :get, :remote => true) %>
Obviously, you have to get update_thingy_path to resolve to some action as normal. The difference is when you render you are going to be rendering some *.js.erb instead of *.html.erb. In that update_thingy.js.erb, you just put whatever javascript you want to run in the client. You might wanna notify the user that the update happened for example (in jQuery):
$('#notice').html("Thingy was update.")
Or if whatever javascript you're returning is really simple, in the controller you can do something like the following instead of having a whole js.erb for a one-liner.
render :js => "alert('Blah')"
You're really going to be using two technologies to accomplish this: javascript on the client-side, and rails on the server-side.
The general idea is that you want to:
(1) add your web methods on the server side with rails, and then
(2) use something like jQuery to get your client-side js calls up to the server to fire off the web methods.
Two writeups I found by googling for : rails3 ajax
http://www.stjhimy.com/posts/7-creating-a-100-ajax-crud-using-rails-3-and-unobtrusive-javascript
http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/
API Reference for using jQuery's ajax post() method:
http://api.jquery.com/jQuery.post/

Rails 3: Simple AJAXy Page updates?

I can't believe I've been looking four hours for this simple task, but I have.
In Rails 2.3, I could replace one section of a page with this simple code:
render :update do |page|
page.replace_html "div_id", :partial => "new_content",...
end
In Rails 3, Ryan Bates has me writing entire new javascript functions, switching from Prototype (rails default) to jQuery, and otherwise not enjoying life. The other tutes are no more straightforward.
What am I missing? How do we replace a <div> these days?
Thanks, guys. The official answer seems to be that, yes, the team felt simple is the enemy of good and made it more complicated.
The first key is to create a .js.erb file NAMED for the method CALLING the ajax update. So if the index method handles the update, put the raw javascript in index.js.erb. This goes in the views folder.
Second, the code that worked in index.js.erb was
m = $('list_users');
m.innerHTML = "<%= escape_javascript(render :partial => "reload_users") %>";
Then to make the call, add in the respond_to block of the controller method, add:
format.js
Finally, the calling view has:
<%= link_to "Update User List", #reload_users_path, :remote => true %>
By the way, supposedly all the old pages using page.replace will work if you install a plugin. The plugin download page suggests that it broke in the last releases of Rails 3 and has not been fixed. Also, various bloggers will come to your home and birch-switch you if you use it.
The whole RJS stuff makes the javascript inline and makes the dom very obtrusive. Also, by avoiding inline javascript you could open up other possible ways of optimizing you javascript by compressing and caching those files in browser. Thats the reason why RJS is getting out of scope from rails 3. A little bit of getting around with jQuery or Prototype for a day should get you on gears with these kind of small stuff and will help the project on long run.
Do you still have jQuery in there? I'd recommend it over Prototype any day...
If it's still there you can just use the following in your Javascript:
$.get("<%= url_for path/to/partial %>",
function(response) {
$("#div_id").html(response);
});
This gets the partial via AJAX and just dumps it into the div with id div_id.
Hope this helps!
I'm not even sure you need to make an AJAX call to load that partial. I believe that in a js.erb file, a call to render(:partial => object_or_path) will just return a string with all the html, which you can wrap in a jQuery object and append. Example:
$('#div_id').html($('<%= render :partial => #object %>'))
As far as I know, along the same line as the answer above, you can do something like this in your template:
<%= link_to "Update User List", #reload_users_path, :remote => true %>
And in controller, do this:
respond_to do |format|
format.js {
render :text => "alert('reloaded')"
}
end
This way you can have controller "execute" client side JS much the same as as render :update used to do. This is equivalent to doing the following in Rails 2:
render :update do |page|
page << "alert('reloaded')"
end
Is there any reason why this approach is not advisable?
Try this:
page.call "$('#div_id').html", render(:partial => 'new_content')

how can I hide params I transmit to a method (like form_for seems to do)?

I've been searching for hours now and haven't found anything that helps.
What I want to do:
I need to call the check_login-Method (as below), which needs parameters.
redirect_to check_login_users_url(
:user => {:name => input[1], :password => input [2] },
:stylesheet => 'scaffold',
:method => :get)
The point is that these params are sent in the method-call as in the "Redirected to"-line below.
Processing ApplicationController#execute(for 127.0.0.1 at 2009-12-19 00:28:40) [POST]
Parameters: {"command"=>{"line"=>"log dodo wg"}, "authenticity_token"=> <...token>}
Redirected to http://localhost:3000/benutzer/check_login?method=get&stylesheet=scaffold&user%5Bname%5D=dodo&user%5Bpassword%5D=wg
Completed in 9ms (DB: 0) | 302 Found [http://localhost/execute]
I want to prevent rails from putting the params into the url and pass them hidden instead.
When I send a form created with form_for, there's nothing in the url, so I assume it must be possible.
Please tell me how to do that.
Steps tried
I have tried different "html-verbs": get, put, post - no difference. Though the call of check_login is really short the url-with-params shows up in my Console
create an instance variable and pass it as param (strange, didn't work either)
watch form_for working – without results, got no clue
//edith:
Thanks for all your help so far. Perhaps I didn't specify my problem in enough detail.
I've got a text_field in which I enter short commands (experimentally). Its form calls execute in AppController, which in case of login-data performs redirect_to check_login. I don't need to access a webpage, I simply want to run the method. I liked the idea of putting it into :flash, but I'm wondering if there's a "neater" way to do pass the data hidden.
TL; DR Version: Use a form.
You're never going to be able to fully hide parameters, tools can be used to monitor requests and view the post data/parameters. You could however obfuscate it with an encrypted session. Also it appears that you're sending login info via a GET request, this is generally a bad practice.
That said...
What is going wrong for you is that you're not generating any post data with link_to :method => :post. link_to will use what ever parmas you give it to generate the url. Wheres forms will send all the params generated by the form as POST data to the url generated in the form_for call.
Upon receiving a POST request, Rails will merge parameters routing picks up from from the URL with the post data it receives into one params hash.
As in POST to
http://localhost:3000/benutzer/check_login?stylesheet=scaffold&user%5Bname%5D=dodo&user%5Bpassword%5D=wg
produces the same params hash in the receiving controller action as a POST to http://localhost:3000/benutzer/check_login with the following data:
stylesheet=scaffold&user[name]=dodo&user[pasword]=wg
There will be no distinction in the server log between the two requests.
If you look at what form_for is doing, it submits POST data built from the form inputs to the url generated by the arguments.
form_for #user, create_user_url(:stylesheet => "scaffold") do |f|
f.text_field :name
f.password_field, :password
end
This form will submit the form data to the url generated from the options. In this example the url is: http://localhost:3000/users/create?stylesheet=scaffold and the form data is:
user[name]=name_field_value_at_submit&user[password]=password_field_value_at_submit
link_to will not populate post data for you. You must either do it through a form or with javascript. The link_to documentation contains an example of doing this with javascript. Look for how the destroy with :onclick is handled.
If you really don't like buttons, you could use link_to_function to submit a form.
Replace
:method => :get)
with
:method => :post)
What's the difference between :get and :post? Read Methods GET and POST in HTML forms - what's the difference?
With form_for you create form which is then POSTed to server, that's why you don't see parameters in url - they're in http request body. But it is not possible to redirect user's browser from some action in controller to make another POST - if it would be possible, then I could redirect user to (for example) email change form of gmail or other forms. You can only redirect user to other site, which user's browser then GETs.
If you really don't want to show parameters in url, and both actions are in same application, then you can store those parameters in session or flash store, and retrieve in next request after redirect.
You can use Ajax request to send form data to action :
In some cases its not good to change :get into :post.
For instance in case of Controller's :index action its not good approach to use :post
So Use ajax call to submit form and update only dynamic content of the page.
In js.coffe script file
$ ->
$("#button-id").on "click", (ev) ->
$.ajax
type: "GET"
dataType: "html"
url: "/horoscope_dailies"
data:
date: date
success: (data) ->
$("#index_content").html data
error: (object, error) ->
console.log error
In your controller action
render partial: 'partial_name' if request.xhr?
In your view file:
%div{:id => 'partial_content'}
= render 'partial_name'

Resources