Question update:
I have figured out that importing JQuery (even without using it at all) is causing :remote => true to not work properly. I get the following error in the Chrome console:
Uncaught TypeError: Object [object Object] has no method 'dispatchEvent' (prototype.js:5653)
And when the link is clicked, it throws the same error again before redirecting.
Responder.erb.html
<ul>
<% #choices.each_with_index do |choice, index| %>
<li><%= link_to choice, { :action => "submit_response", :id => #id, :response => index }, :remote => true %></li>
<% end %>
</ul>
Example generated HTML:
<ul>
<li>True</li>
<li>False</li>
</ul>
Since Dave never formally answered this question, the answer is:
"If you're trying to run both jQuery and Prototype in the same app, the load order of the libraries matters, or you must use noConflict."
– Dᴀᴠᴇ Nᴇᴡᴛᴏɴ
Related
This is my first time trying to implement an Ajax call in rails 3, though I am using the .load function ( I still hope this is Ajax otherwise im understanding this incorrectly)
So i have a search form that returns results via a get request which renders on a different page, i would like the results to appear on the same page as the search form
<%= form_tag({:controller => 'search', :action => 'search'}, {:method => 'get'}) do |select| %>
<%= label_tag :search, "Enter Keywords Here" %>
<%= text_field_tag :search, params[:search] %>
(I have shortened the form)
<%= submit_tag "Search", :class => "searchbutton" %>
<% end %>
Jquery/Ajax call
$(document).ready(function() {
$('.searchbutton').click(function() {
$('#searchres').load('shared/searchresults');
});
});
View
<h3>Search Recipes here</h3>
<%= render 'shared/searchrecipes' %>
<div id ="searchres">
</div>
What am i doing wrong?
Due to this being an AJAX call, you need to add remote: true besides method: :get, getting an html parameter hash like this:
{:method => 'get', :remote => true}
When Rails finda remote call, it prevents the default automagically. Otherwise, you would need to modify you javascript like this:
$(document).ready(function() {
$('.searchbutton').click(function(evt) {
$('#searchres').load('shared/searchresults');
evt.preventDefault();
});
});
I've ran into a weird problem in Rails. When I try and submit a search query with the following form on my Uploads controller:
<%= form_tag ({:controller => "uploads", :action => 'find_uploads'}), :method => "get" do %>
<%=h text_field_tag :search, params[:search], :id => 'search_field' %>
<br />
<%= submit_tag "Search", :style=>"display:inline;" %>
<% end %>
I get redirected to the following url and error page:
/uploads/find_uploads?utf8=✓&search=bot&commit=Search
ActiveRecord::RecordNotFound in UploadsController#show
Couldn't find Upload with id=0
My find_uploads route: get 'uploads/find_uploads' => "uploads#find_uploads"
And when I did I rake routes this is what I got:
uploads_find_uploads GET /uploads/find_uploads(.:format) {:controller=>"uploads", :action=>"find_uploads"}
Everything seems to be in order... not sure why it's not working out as expected. For debugging purposes I dropped breakpoints in both my find_uploads and show actions and neither of them were reached so this error message must be lying to me as the UploadsController show action is never called!
This form is being rendered on my index page if it counts for anything.
I think it's taking find_uploads for an id.
Declare your routes like that:
resources :uploads do
collection do
get :find_uploads
end
end
ps: currently, when you do rake routes, /uploads/find_uploads is after /uploads/:id right?
I'm trying to show my errors (both flash and devise) in one of my layout files (_header.html.erb):
<div id="alerts">
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
<% end %>
<%= devise_error_messages! %>
</div>
but I'm getting an error: undefined local variable or method `resource', because the error message is no longer in the devise form. I tried the method suggested here: http://pupeno.com/2010/08/29/show-a-devise-log-in-form-in-another-page/ by pasting that code into the application_controller.rb file. No luck. Ideas?
oh. I forgot to mention... The pages work without error, but my tests are failing... Here's a failing test:
it 'succeeds with a valid email and password' do
user = Factory.create(:user)
visit sign_in_path
fill_in 'user_email', :with => user.email
fill_in 'user_password', :with => user.password
click_button 'Sign in'
page.should have_content("hi #{user.username}")
end
This is Rails3, fyi.
I was getting errors like this and solved using :partial and :locals when using the render method:
<%= render :partial => 'header', :locals => { :flash => flash } %>
See Rails 3: "undefined local variable or method" if I put content in a partial
turns out the code needed to be in the application_helper instead of the controller, but the code at pupeno.com works!
I am having a weird issue with Devise. I have lists with tasks on them. When you delete a task all of the sudden I get a template error having to do with the User.
It seems like the delete method causes the session to logout and therefore can't find the User when trying to load the template.
I have no idea why this is happening:
_task.html
<div class="tasks">
<%= div_for task do %>
<%= link_to 'Delete', task_path(task), :method => :delete, :class => "delete", :remote => true %> | <%= content_tag(:div, task.task, :class => "task-body") %>
<% end %>
</div>
destroy.js.erb
$("#task_<%= #task.id %>").fadeOut();
ERROR AFTER RELOADING PAGE, THIS IS FOR THE ACCOUNT, LOGOUT ETC in HEADER
No route matches {:action=>"show", :controller=>"users"}
Extracted source (around line #5):
2: <div id ="login">
3: <ul>
4: <li><%= link_to "Sign out", destroy_user_session_path %></li>
5: <li><%= link_to "Account", user_path(current_user) %></li>
6: <li><%= link_to "Things", user_things_path(current_user) %></li>
7:
8: </ul>
Thanks in advance!
After a little more searching I found the answer here on stackoverflow, so credit should go to justsee from this previous question
The request will not include the required CSRF data, and as of
Rails 3.0.4 the session is silently reset instead of throwing an
ActionController::InvalidAuthenticityToken error.
To fix this include the following in your layout:
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
I'm upgrading an app from Rails 2 to 3 and am reworking all of the remote functions to use Unobtrusive Javascript. Where I'm struggling is handling ajax callbacks in UJS.
There are a lot of resources I've found that show how to implement these callbacks with jQuery, but not much for prototype. Perhaps you can help me figure this out.
In Rails 2, I had this:
<% remote_form_for #foo, {:loading => "loading_function()", :complete => "complete_function()" } do |f| %>
...
<% end %>
In Rails 3, I have this:
<%= form_for #foo, :remote => true do |f| %>
....
<% end %>
From what I've figured out so far (which may be wrong), I need to attach my old loading/complete functions to the form so that they'll be fired by the handleRemote function in Rails.js. I'm just not sure how to go about that.
Again, I'm doing this in Prototype. So answers specific to that framework are appreciated.
The answer is the following:
<%= form_for #foo, :remote => true do |f| %>
...
<% end %>
...
<script type='text/javascript'>
$('edit_foo').observe('ajax:before', loading_function());
$('edit_foo').observe('ajax:complete complete_function());
</script>
Try this link. Yes, it is JQuery, but JQuery and Prototype do not differ the way how things work together. Here is a code fragment that adds a new task directly in the index page - and it uses Prototype:
views/tasks/_newform.html.erb:
<%= form_for(#task, :remote => true) do |f| %>
<div>
<%= f.label 'Add a new task: ' %>
<%= f.text_field :name %>
</div>
<div>
<%= f.submit %>
</div>
<% end %>
views/tasks/index.html.erb:
<div id='newform'>
<%= render :partial => "newform", :locals => { :#task => Task.new } %>
</div>
views/tasks/create.js.rjs:
page.insert_html :after, 'tablehead', :partial => #task
page.replace_html 'newform',:partial => "newform", :locals => { :#task => Task.new }
Edit: you need to add "format.js" to our create method of the task controller
For people with a similar issue, it may also help to look at the source code for the remote helpers in the Rails 2.3.x source code.
In my case, I wanted to figure out what to do with the ':update' parameter, as in:
remote_form_for(#obj, :update => "new_obj", :before => "some js code") do |f|
I had to find the update functionality in the remote_function code.
For my specific issue, it looks like it's impossible to get the equivalent of :update with Rails 3 UJS helpers. The rails.js in Rails 3 wraps :remote => true requests with the Ajax.Request(...), whereas the :update function in Rails 2 wraps Ajax requests with Ajax.Updater(...). For people looking to replace the :update feature from Rails 2, I see 2 options:
Switch to jquery-rails, so that you can access the response from the Ajax request, with code like this:
$("#elem").bind("ajax:complete", function(et, e){
$("#results").html(e.responseText);
});
Write your own Prototype based code to grab the form and submit it via ajax, using Ajax.Updater(...) instead of Ajax.Request. Do NOT use :remote => true, since this will attempt to use Ajax.Request.
Side note: I played around with the callback object provided in the ajax:complete event
$('new_obj').observe('ajax:complete', function(request){
console.info(request);
});
The request object doesn't appear to contain the response anywhere in it. It is pretty massive, though, so I could be wrong. Hopefully this will help someone else trying to upgrade from Rails 2 to 3, though.
There's a way to get the response from the Ajax.Request invocation, if you were using remote_form_for with :update option. So, you probably don't need to change it to use Ajax.Updater as a workaround. Basically, you use respone.memo.responseText, in your example it would be something like this:
$('new_obj').observe('ajax:complete', function(response){
console.info(response.memo.responseText);
// Probably you would use it like this:
$('new_obj').update(response.memo.responseText);
});