I was just playing around with Rails 3 beta and noticed that link_to_function is now gone. I presume there's an alternate method of achieving the same result (onclick event?) but I was wondering if there's a more Rails-3'y way of doing it. TIA.
Rails 3 seems to have done away with Prototype Helper in favour of a less obtrusive/JS library agnostic approach. The goal is to eliminate all inline javascript generated by Rails. Prototype Helper generated pretty much all of the javascript.
Now any of the non remote variants of helpers will generate the proper javascript for a remote call in your JS library of choice just by supplying the :remote => true option.
Unfortunately this doesn't hold true for the x to function methods. For the time being there are the prototype legacy helpers which are no longer a core part of Rails.
You could also use call as defined in ActionView::Helpers::PrototypeHelper::JavascriptGenerator::GeneratorMethods to supply javascript code to :onclick as an html_option for link_to, but that's not exactly pretty.
Examples:
Rails < 3 | Rails 3
link_to_remote "target", url | link_to "target", url, :remote => true
form_remote_for #post | form_for #post, :remote => true
etc....
Or something to that effect. I'm having trouble finding official documentation to back up my claims. So the release notes will have to do for now.
Before you can use it, you'll need to include the proper js source files. Ensure that you are loading prototype.js and rails.js, or the library and driver for JS framework of choice in their place.
Remember, Rails 3 is in beta now. But that doesn't mean it's done. I honestly have no idea how link_to_function will be replaced. It goes against the ideal of unobtrusive javascript.
To answer my own question, seems this works and is sufficient for what I need:
link_to "name", nil, :onlick => "alert('Hello, world!')"
link_to_remote can be done like this
link_to "target",:remote => true
and to do a ajax post/get you have
link_to "target", {:controller =>
controller, :action => method, }, :remote => true
In rails 2 it was like this
link_to_remote "target", :url =>
{:controller => controller, :action =>
method, }, :remote
=> true
Related
In my Rails app there are experiment instances and each experiment has attachments, which are represented as binary blobs in the database and can be quite big. This question is about efficiency in coding a link_to show the attachment.
Originally I had this:
<%= link_to #experiment.attachment.file_name, #experiment.attachment %>
However I was told that the Rails app would be more efficient in rendering the page with
<%= link_to #experiment.attachment.file_name, {:controller => :attachments, :action => :show, :id => #experiment.attachment_id}, {:method => :get} if ! #experiment.attachment_id.nil? %>
The justification is that the first version fetches the attachment from the database, and the second one does not, making it is better, albeit longer and uglier. Is this true?
Both versions accomplish the same thing in directing the user to the show page for an attachment and I was under the impression the first is the default way to do a link_to a record show page.
Is there a way to shorthand the second piece of code to make it less terrible with code in the view?
Try using a rails route helper, use rake routes to view all your routes and then you can get something like this (don't forget to apped _path to route):
experiment_attachment_path(#experiment.attachment)
I would express this using the route path rather than using the ActiveRecord instance to load so the view can use its to_param method (which is what it is doing under the hood).
<%= link_to #experiment.attachment.file_name, attachment_path(#experiment.attachment_id) %>
Im in the process of converting my rails code which developed in version 2 to rails 3. Earlier I used link_to_remote function to create a link.In that I displayed the page on a div field using ':update' option.
<%= link_to_remote #processes_tree[x]["name"],:update => "toprightdiv", :url => { :action => "editproduct", :id => #processes_tree[x]["id"]}%>
Now In rails the link_to_remote is not available ,So I used link_to.But in it the :update option is not available.So I am not able to show the page in the div field.When ever I click the link a new page getting displayed for the link.Is there any alternative way available i n rails3.Please help me to solve the issue.
This is a very general question regarding unobtrusive javascript in rails (googling that phrase would get all you need to know).
Generally you need to use link_to and set :remote to true. Then do the update by handling the response in a .js view or equivalent.
You may also benefit from this screencast demonstrating the rationale for the change:
http://railscasts.com/episodes/205-unobtrusive-javascript
The :update option isn't supported by the new link_to :remote => true.
You will either have to
use the legacy plugin
write the JS/AJAX yourself instead of using :remote => true
use render :update { |page| p.replace_html ... }
I can't figure out how to upgrade this code from Rails 2 to Rails 3:
<% remote_form_for(item, :update => 'div_id') do |f| %>
...
I tried this:
<%= form_for :item, :remote => true, :url => { :controller => "items", :action => "create" }, :update => 'div_id' do |f| %>
...
It creates the new item but it fails in updating the content within <div id="div_id"></div> tags. It seems Rails 3 no longer supports the ":update" option for a remote form_for. Any suggestion?
You could use RJS, but that's being deprecated too (and for good reason). The simplified, best-practices way to handle this in Rails 3+ is as follows (assuming jQuery):
# your_view.html.erb
<div id="receiver-id"></div>
<%= form_for :some_model, :remote => true, :id => 'form-id' do |f| %>
...
<% end %>
# application.js (or any other .js loaded on the page)
$(function(){
$('#form-id').bind('ajax:success', function(xhr, data, status){
$('#receiver-id').html(data);
});
});
The ajax:success hook gets called by the jquery-ujs (aka jquery-rails, aka rails-ujs) remote link/form handler. See for yourself. There are lots of other callbacks/hooks available for you to use, too. If you wanted to make this even more flexible, you could use live instead of bind, and bind to a class that dictates where the ouput goes (e.g. "sidebar") and then all remote links/forms with the sidebar class would have their HTML response go to div#sidebar.
The most straightforward way to do this would be to write a javascript view template, e.g. create.js.erb which would look something like this:
$('#div_id').html("<%= escape_javascript(render(#item)) %>");
(depending on your setup, of course, I'm assuming an #item variable and an associated _item partial)
Edit:
coreyward is right. This is the RJS way which is more of the old fashioned Rails 2.x "Rails way". It's probably more familiar, but has issues. Your specific case is one of them, actually, as typically you might bind to an HTML element to update using the record's id (e.g. div #item_1), and in the create case there is no id available beforehand, complicating matters.
Binding via clientside JS eliminates this issue. RJS works in something of a vacuum, making assumptions about the state of the client's HTML and having no access to it.
I know the question is old but I when migrating to Rails 3 I found a pretty good way of doing this, so I thought I would post it here in case anyone else is in a similar solution.
In layouts/update_page.js.erb I put this file:
$j('#<%=#update_div_id||"list_div"%>').html('<%= escape_javascript render(:partial => (#partial_div||"index"), :locals => #local_hash) %>');
This is mainly used for searches that use remote, so in the index action in the controller, I just added the following code.
respond_to do |format|
format.html
format.js {render 'layouts/update_page'}
end
Since remote is being used, it will always try to use javascript first, so it will render the update_page.js.erb file from above. For us, we almost always use the div#list_div on our index pages, so we update that by the default, however if you need to update something different, you can pass in #update_div_id, and if you need to render a different page, you can pass in #partial_div.
To clarify, for a lot of things, it is probably better practice to use the callbacks, but I found this to be a much easier way, when we had to migrate over nearly 100 of these calls.
A quick and easy answer I'm sure.
I'm upgrading a Rails project from version 2 to version 3 and replacing a load of the link_to_remote with link_to's as per the Rails 3 update. Even something as simple as :
<%= link_to "Check Time",
{:action=>:get_time}, :remote=>true, :update=>'current_time' %>
<div id='current_time'></div>
doesn't seem to work. The request (using get method) is going through ok and the rendered html is :
Check Time
Routes.rb entry :
get "monitoring/get_time"
As I say I'm sure this is a very obvious issue on my part!
The :update option isn't supported by the new link_to :remote => true.
You will either have to
use the legacy plugin
write the JS/AJAX yourself instead of using :remote => true
use render :update { |page| p.replace_html ... }
The :update parameter is gone. You need to handle the DOM update yourself using Unobtrusive JavaScript. Also, make sure you actually included the csrf_meta_tag helper in your layout.
I wrote an article about using unobtrusive JavaScript in Rails 3.
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/