link_to in Rails 3.1 - ruby-on-rails

I'm converting an application from rails 2 to rails 3 and could somebody please help me regarding this small bit of code. The link_to is not working , could some one point me how to use link_to instead of the link_to_remote in rails 3.1 properly?
Rails 2 code
<%= link_to_remote package_item.getId(),
:url => { :controller => 'cmn/popup',
:action => "show_popup",
:frame_url => admin_url(
:ctrl => controller,
:app_action => 'package.item.edit',
:id => package_item.getId().to_s,
:remote => true
),
:frame_width => '570px',
:frame_height => '355px'
}
%>
Rails 3.1 code
<%= link_to package_item.getId(),
:url => { :controller => 'cmn/popup',
:action => "show_popup",
:frame_url => admin_url(
:ctrl => controller,
:app_action => 'package.item.edit',
:id => package_item.getId().to_s
),
:frame_width => '570px',
:frame_height => '355px',
:remote => true
}
%>
I replace all .rjs file with .js.erb. This is the URL I'm getting in Rails 3:
3
This is in Rails 2:
2
my controller
def show_popup
#content_data = {}
#content_data.merge!(params)
render(:template => 'cmn/popup/show_popup', :nolayout => 1)
end

Please look at the syntax of link_to in Rails 3:
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
You have all your parameters in a :url hash, but you don't need to name it :url, just pass in the options in a hash, like this:
<%= link_to package_item.getId(),
{
:controller => 'cmn/popup',
:action => "show_popup",
:frame_url => admin_url(
:ctrl => controller,
:app_action => 'package.item.edit',
:id => package_item.getId().to_s
),
:frame_width => '570px',
:frame_height => '355px'
},
:remote => true
%>
Remember to get :remote out of the url hash.
Let me know if this works.

It is the first time I see a string defining a path as a :controller param.
I mean de :controller => 'cmn/popup'. This is new to me, and it feels strange.
Are you sure this works and the request is being received by the correct controller and action?
Another thing i think it can be tricky is the render call on the controller. Just call
render :layout => false
or maybe dont call anything at all.
If the template has the same name than the action and it is placed in a directory named like the controller, rails knows what template needs to be rendered and the extension (js/html/xml) based on the request type. Maybe render :template => .... forces to render an html template.
The :nolayout option i think it is invalid. Anyway, if the request is for a javascript file, it never renders layout.

Related

Missing template error on when background processing

I am using background processing with the resque gem and bioruby, and the processing is correctly functioning. I am however getting a "missing template" error. It seems the action is trying to load a template.
Missing template cosmics/start_batch, application/start_batch with {:locale=>[:en],
:formats=>[:html], :handlers=>[:erb, :builder, :coffee]}.
I do not want a template loaded: the background process retrieves data from an external source and then updates a database table (this is all working).
The code is triggered by a button:
<%= link_to 'Process', start_batch_path, :class =>"btn btn-primary" %>
config/routes.rb
match '/cosmics/start_batch', :to => 'cosmics#start_batch', :as => 'start_batch'
resources :batches do
resources :batch_details
end
cosmics_controller.rb
def start_batch
#batch = Batch.create!(:status => 'created',:status_timestamp => Time.now)
#cosmics = Cosmic.find(:all, :conditions => {:selected => true}).each do |cosmic|
#batch_detail = BatchDetail.create!(:batch_id => #batch.id, :cosmic_mut_id => cosmic.cosmic_mut_id)
#batch_detail.save
cosmic.selected = false
cosmic.save
end
Resque.enqueue(UcscQuery,#batch.id)
end
workers/ucsc_query.rb (Reqsue worker class)
class UcscQuery
require 'bio-ucsc'
include Bio
#queue = :ucsc_queue
def self.perform(batch_id)
Ucsc::Hg19.connect
#batch_detail = BatchDetail.find(:all, :conditions => {:batch_id => batch_id}).each do |batch_detail|
ucsc_cosmic = Ucsc::Hg19::Cosmic.find_by_name(batch_detail.cosmic_mut_id)
if ucsc_cosmic
batch_detail.bin = ucsc_cosmic.bin
batch_detail.chrom = ucsc_cosmic.chrom
batch_detail.chrom_start = ucsc_cosmic.chromStart
batch_detail.chrom_end = ucsc_cosmic.chromEnd
batch_detail.status = 'processed'
batch_detail.save
end
end
Batch.update(batch_id, :status => 'located')
end
end
How can I prevent Rails from trying to load a cosmics/start_batch template? Any refactoring tips would also be appreciated.
If there is no render nor redirect instruction in a controller method, Rails looks for a view with the same name of the method. To change this behavior, add render :nothing => true at the end of the start_batch method.
With this, when the user will click on the Process link, it will render a blank page. That's certainly not what you want. You can use :remote => true option in the link_to so the user will stay on the current page:
<%= link_to 'Process', start_batch_path, {:remote => true}, {id: 'process_btn', :class => "btn btn-primary"} %>
Finally, use javascript to show the user that "something" happened when he clicked on the button. Example:
$('#process_btn').on('click', function() { alert('Batch process started'); };
You can simply type:
render :nothing => true
in your action. I would also advice changing your link to remote
<%= link_to 'Process', start_batch_path, :class =>"btn btn-primary", :remote => true %>
Otherwise you'll see blank page after clicking on it.

Handlebars / Mustache with Rails url_for

I'm trying to use a named route with {{id}} as one of the params, allowing the rendered content to be consumed by Handlebars. url_for is escaping the param so the resulting url contains %7B%7Bid%7D%7D. I've tried adding :escape => false to the call, but it has no effect.
routes.rb
resources :rants, :except => [:show] do
post '/votes/:vote', :controller => 'votes', :action => 'create', :as => 'vote'
end
index.haml
%script{:id => 'vote_template', :type => 'text/x-handlebars-template'}
.votes
= link_to 'up', rant_vote_path(:rant_id => '{{id}}', :vote => 'up')
%span {{votes}}
= link_to 'down', rant_vote_path(:rant_id => '{{id}}', :vote => 'down')
application.js
var vote_template = Handlebars.compile($('#vote_template').html());
output
<script id="vote_template" type="text/x-handlebars-template">
<div class='votes'>
up
<span>{{votes}}</span>
down
</div>
</script>
I've simplified the example for the sake of readability but question remains the same; is there any way to use a named route with {{ }} as a param? I understand I can just do link_to 'up', '/rants/{{id}}/votes/up' so please don't supply that as an answer.
The trouble is the mustache characters are not valid in URLs and are being escaped. I'd recommend creating a wrapper.
def handlebar_path(helper, arguments={})
send("#{helper}_path", arguments).gsub(/%7B%7B(.+)%7D%7D/) do
"{{#{$1}}}"
end
end
handlebar_path :rant_vote, :rant_id => '{{id}}', :vote => 'up'
I ended up just overriding url_for to handle a custom param:
module TemplateHelper
def url_for(*args)
options = args.extract_options!
return super unless options.present?
handle = options.delete(:handlebars)
url = super(*(args.push(options)))
handle ? url.gsub(/%7B%7B(.+)%7D%7D/){|m| "{{#{$1}}}"} : url
end
end
So now, calling named_url(:id => '{{id}}', :handlebars => true) works as you'd expect.

how to implement an toggle functionality for update link

currently i have an link as mentioned in below format
<%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => #issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
i would like to apply toggle functionality on update could anyone please help me.
There are numerous possibilities to achieve a toggle button. You may choose to change the JavaScript function your button executes, or the function may toggle the Rails action to call. I personally would go for a Rails action that knows how to toggle itself:
def toggle_action
#model = Model.find param[:id]
if #model.active?
#model.active = false
render :js => "alert('Active!');"
else
#model.active = true
render :js => "alert('Inactive!');"
end
end

Why isn't url_for rendering this like I think it should?

I have this in my controller:
#statics = [{'home' => 'about'},
{'home' => 'termsandconditions'},
{'home' => 'information'},
{'news' => 'archives'}]
and in my view:
#statics.each do |controller, action|
xml.loc url_for(:only_path => false, :controller => controller, :action => action)
xml.lastmod w3c_date(Time.now)
xml.changefreq "weekly"
xml.priority 0.8
end
the URLs aren't what I would expect, e.g.
http://localhost:3000/homeinformation
instead of
http://localhost:3000/information
However, I just did this manually, I get the right URL:
url_for(:only_path => false, :controller => 'brownies', :action => 'index') #works!
What am I missing here?
#statics is an array with one hash entry, so you'll need your each block to take just a single parameter and split it up inside the block.

link_to_remote wants to render a template - how not to? rails

I want to delete my task ajax-style if some conditions are met. I do that with the help of link_to_remote. The thing is that link_to_remote wants to render a template and i dont want it to.
In my view ( _task_sth.html.erb):
<%= link_to_remote "Delete task", :url => {:controller => 'tasks', :action => 'delete_task', :task_pers_id => sorted_user_task.id}, :complete => "$('#{delete_task_domid}').hide();" %>
In my controller (tasks_controller.rb):
def delete_task
task_pers = TaskPersonalization.find(params[:task_pers_id])
horse_task = task_pers.task
task_pers.destroy
if horse_task.task_personalizations.empty?
horse_task.destroy
end
end
The task gets deleted but i get an error saying: Missing template tasks/delete_task.erb in view path app/views.
How can i make it not search for a template?
I tried with adding :method => :delete at the end of link_to_remote and changing my action name to destroy. I also added render :nothing => true. I also played with routes a bit. But still i allways get the same error.
The question is how can i make it not search for a template because i dont want it to render anything?
Would be very gratefull for any answers, Roq.
Have you got the same error when adding render :nothing => true? That's strange.
Rails is trying to search for a template because there's no render in your action. So to avoid it, you need to explicitly call the method:
def delete_task
task_pers = TaskPersonalization.find(params[:task_pers_id])
horse_task = task_pers.task
task_pers.destroy
if horse_task.task_personalizations.empty?
horse_task.destroy
end
render :nothing => true, :status => 200
end

Resources