Partial not receiving all variables from :locals - ruby-on-rails

In my controller I have:
- #items.each do |item|
= render :partial => 'item', :locals => { :item => item, :draggable => true }
And in the item partial I have:
%span{:id => "item_#{item.id}", :class => 'item'}
= item.name
- if defined?(draggable)
= draggable_element "item_#{item.id}", :revert => true
This is not working, however, because defined?(draggable) returns false. The draggable_element is never rendered.
I know that item is passed through :locals because the rest of the partial renders. If I change the partial to read:
- if defined?(item)
= draggable_element "item_#{item.id}", :revert => true
Then the draggable_element is rendered.
Any idea why :draggable is not getting passed to the partial?

Use local_assigns[:draggable] instead of defined?(draggable).
From the Rails API "Testing using defined? var will not work. This is an implementation restriction."

I've solved this problem in the past by throwing this into the top of the partial.
<% draggable ||= nil %>
That allows me to do
<% if draggable %>
So long as I don't try to make the distinction between draggable being nil and never being passed.

Related

How do you render multiple partials in a layout multiple times in a view?

I have a page with many modules that have variable parts to them such as a header, sub-heading, footer, body, and id. I started by creating a layout and rendering the layout with local variables and a main block to fill the template.
Layout:
.container{:id => local_assigns[:id].present? ? id : nil}
.header
= title
= subtitle
.body
= yield
.footer
= footer
View:
= render :layout => "shared/example", :locals => {:title => 'Heading', :subtitle => 'Sub heading', :footer => 'closing part'} do
body of the template
That works great, but now I'd like to pass blocks in for the subtitle and footer keeping in mind that there will be multiple instances of this layout in a page. So far the only way I've been able to solve this is by using the capture_haml helper
View with Haml as local variable:
- exampleSubtitle = capture_haml do
%h3 subtitle
%button action
= render :layout => "shared/example", :locals => {:title => 'Heading', :subtitle => exampleSubtitle, :footer => 'closing part'} do
body of the template
This example is a little stripped down to clarify the question. In practice, I worry about the :locals hash growing to an "ugly for Haml" size and would like to prevent that if possible.
Is there any way to define contextual content blocks to keep things cleaner?
Wishful thinking view:
= render :layout => "shared/example", :locals => {:title => 'Heading'} do
- content_for :subtitle do
%h3 subtitle
%button action
- content_for :footer do
%a{href => "#top"} top
body of the template
Wishful layout:
.container{:id => local_assigns[:id].present? ? id : nil}
.header
= title
- if content_for?(:subtitle)
= yield :subtitle
.body
= yield
- if content_for?(:footer)
.footer
= yield :footer

Rails Javascript if else condition using variable from Controller

View
<%= link_to "Link", {:action => "AjaxView",:col => "colname"},
:update => "Ajaxcall", :remote => true %>
Controller
def AjaxView
#vars= Var.find(:all,:conditions => { :varName=> "one" },:select=>(params[:col]))
respond_to do |format|
format.js { render :layout=>false }
end
end
AjaxView.js.erb
if ( (<%= col %>) == "colName") {
$("#3").text("<%= escape_javascript(render(:partial => "var") %>");
}
else
{
$("#2").text("<%= escape_javascript(render(:partial => "var") %>");
}
Issue here is this Variable "col" doesn't get its exact value in AjaxView.js.erb file, and my If else condition doesn't get executed. What am i missing here ?
The local variable col isn't assigned in AjaxView.js.erb. I think you meant to write it as params[:col].
Also the double quotes around var should be single quotes, to play nice with the surrounding double quotes.
{:action => "AjaxView",:col => "colname"}
This is not how you build a url for link_to.
What's the route to access the AjaxView method?
It should be something like: link_to "Link", AjaxView_resources_path(:col => "colname").
And in your controller, you need to set an instance variable #col = params[:col] to be able to use it in your view.
ps: your should name your method ajax_view instead of AjaxView.
if ( #col.to_s == "colName") {
$("#3").text("<%= escape_javascript(render(:partial => "var") %>");
}
elsif ( #col.to_s == "colName1")
{
$("#2").text("<%= escape_javascript(render(:partial => "var") %>");
}

Stagger the rendering of multiple partials using Rails

I've got the following situation:
1. Using a javascript function to begin an AJAX call
$(".toggle").click(function() {
var currentId = $(this).attr('id');
$(this).find(".loadingDiv").show();
$(this).find(".matchingsDiv").load("<%= matches_companies_url %>?id=" + currentId, null, function(){
$('.loadingDiv').hide();
});
return false;
});
2. Rendering matches.js.erb
<% #matchings.each_with_index do |match, index| %>
<%= (render :partial => 'companies/matching', :locals => {:match => match, :project => #project}) %>
<% end %>
The above code works. Here's a little question: how can I stagger the rendering of each matching?
i.e. Can I make the first matching render immediately, the next matching after 200ms, the third after 400ms, and so on?

html is being escaped in link_to

I'm trying to implement a link, when clicked marks you as present for a meeting. This link is a method in a helper:
def link_to_remote_registration(event_id)
down_image = "down_blanco.png"
up_image = "up_blanco.png"
unless registration.nil?
if registration.present == 1
up_image = "up_filled.png"
elsif registration.present == 0
down_image = "down_filled.png"
end
end
link_to_remote_registration = String.new
loading_and_complete = "Element.show('indicator_event_"+event_id.to_s+"'); Element.hide('vote_"+event_id.to_s+"')".html_safe
complete = "Element.hide('indicator_event_"+event_id.to_s+"'); Element.show('vote_"+event_id.to_s+"')".html_safe
link_to_remote_registration =
link_to(image_tag(up_image , :id => 'will_not_attend_event_'+ event_id.to_s , border => 0),
:url => new_registration_path(:present => 1, :event_id => event_id, :escape => false),
:remote => true,
:method => :put,
:loading => loading_and_complete,
:complete => complete)
return link_to_remote_registration
end
The problem is that when I render the link in my view some of the html gets escaped making the link not work.
<a href="/calendar?complete=Element.hide%28%27indicator_event_1%27%29%3B+Element.show%28%27vote_1%27%29&loading=Element.show%28%27indicator_event_1%27%29%3B+Element.hide%28%27vote_1%27%29&method=put&remote=true&url=%2Fregistrations%2Fnew%3Fevent_id%3D1%26present%3D1">
<img id="will_not_attend_event_1" border="0" src="/images/up_blanco.png?1198181114" alt="Up_blanco">
</a>
Which I think is not a valid url. I wonder why this happens - i call the html escape on the complete and loading string.
Regards
Since you're passing the html from from a helper, Rails sanitizes it to protect from XSS. You can override it by returning:
link_to_remote_registration.html_safe
http://railscasts.com/episodes/204-xss-protection-in-rails-3
You could also use raw() instead of disabling XSS system-wide.
raw(image_tag(up_image , :id => 'will_not_attend_event_'+ event_id.to_s , border => 0))

Rails form params changing in controller

I have a form:
<%= form_for(:report_main, :url => {:action => 'exporttoxiccreate'}) do |f| %>
<%= collection_select(:waste, :code, Waste.find_all_by_istoxic(false), :id, :code, :include_blank => '') %>
<%= f.check_box(:q_pripadnost) %>
<%= f.text_field(:amount) %>
<% end %>
and this code in controller:
def exporttoxiccreate
#report = ReportMain.new
#reportexport = ReportExport.new
#reportparam = params[:report_main]
#report.waste_id = #reportparam.waste.code
#report.amount = #reportparam.amount
if #report.save
#reportexport.report_main_id = #report.id
else
redirect_to(:action => 'exporttoxicnew')
end
#reportexport.q_pripadnost = #reportparam.q_pripadnost
if #reportexport.save
redirect_to(:action => 'show', :id => #reportexport.id)
else
redirect_to(:action => 'exporttoxicnew')
end
end
I want to save in two tables, in two objects data from this form, and I need to separate params to manipulate with. I tried with this:
#reportexport.q_pripadnost = #reportparam.q_pripadnost
I want to set q_pripadnost field in #reportexport with some value from param.
Where I make mistake?
When you get params from a form in Rails, it comes in the form of a hash. For example:
params[:report_main][:waste]
params[:report_main][:amount]
So when you call #reportparam = params[:report_main], you are setting #reportparam to a hash, but then you are trying to use it later like an object. For example, instead of #reportparam.q_pripadnost, use #reportparam[:q_pripadnost].
You can take a closer look at your variable by temporarily changing your action to show a text version of the variable, for example:
def exporttoxiccreate
#reportparam = params[:report_main]
render :text => #reportparam.to_yaml
end

Resources