Why is my template variable being ignored in ruby on rails? - ruby-on-rails

I would like to have some code in my rails template layout to be invoked like this:
render :mytemplate, layout: 'mylayout', modal_title: 'My Title'
where mylayout exists as views/layouts/mylayout.html.haml. Inside, I want to use the following code to accept the modal_title but have a default value if the variable was not passed or was null:
- modal_title = 'Title' if not defined? modal_title or modal_title.nil?
-#Yes, somewhere I will print like: = modal_title
What do I expect: modal_title having "My Title" in the first case.
What do I have: modal_title having "Title" (the default value), and when I debug, I see modal_title existed before with value nil.
Why is my variable being ignored?

Specify local variables using the locals option:
render :mytemplate, layout: 'mylayout', locals: {modal_title: 'My Title'}
You can also simplify the default value logic in your template with try:
= try(:modal_title) || 'My Title'
If the modal_title variable exists and is not nil it will be used, otherwise it will print 'My Title'

In your case the modal_title being passed will always be nil in the template since it isn't being passed correctly. Use locals or object to pass desired variables to your template. Usually writing something like
render :partial => 'myTemplate'
gets translated into
render :partial => 'MyTemplate', :locals => {:myTemplate => #myTemplate }
So either you can define an object that contains your default title 'My Title' or you can pass it with using locals explicitly
render partial => 'myTemplate', :locals => { :model_title => 'Your Title'}

Related

Output content from render_to_string using global variable

I am inside a Controller where I have a method that saves information inside global variables like the following
#var = "test"
Now when I want to render the view file I am using the following code
MyController.new.render_to_string(:template => 'folder/file.erb', :layout => false)
The issue I'm having is that inside the file.erb it cant access the variable #var for some reason. The code goes as follows:
<% #var.each do |v| %>
<% end if !#var.nil? %>
Which is returning null as it's content. How can I fix this?
I think you should pass it as a local:
MyController.new.render_to_string(:template => 'folder/file.erb', :layout => false, :locals => { :var => #var )
Then it will be accessible as a local variable var (without #).
If you want to do some Rails magic, you should point an action where your #var is defined:
MyController.new.render_to_string(:template => 'folder/file.erb', :layout => false, :action => 'your_action_name')
so Rails will be able to reuse your variable in the view

How to render a Rails view to a string I can use within a model method?

Let's say I have a view called /users/recipes.haml
- #user.recipes.each do |recipe|
%p= recipe.name
I need to build out this view as a simple string, to inject it into something. How can I do this from within a model?
Basically, how can I pass a few variables to a template, and capture the result as a simple string variable?
You can do following to render template and store into string:
ActionController::Base.new.render_to_string(:template => "/users/recipes.haml", :locals => {:#user => user})

rails render partial not working

this is my simple code
<%= render :partial => '/manage/regions/get_by_country', :locals => {:country_id => #last_search.country_id} %>
the #last_search.country_id has value (checked)
but while rendering the control seems that the country_id is null or empty
what i cant understand is that i use same syntax in another control and work us expected
i try also add hardcoded country_id
<%#id = 118%>
<%= render :partial => 'manage/regions/get_by_country', :locals => {:country_id => #id} %>
<%end%>
and not working
the control rendering but the country_id is null
OK i got the problem
the variable on the partial named #country_id
and i passed country_id (with no the '#')
i actually don't know why in one controller its work and on the other it doesn't work
but when i change the variable on the partial to country_id (with no the '#')
its work as expected
thanks

Passing local variable to a partial in rails 2.x

I have the following method in my controller:
def update_fees_collection_dates_voucher
#batch = Batch.find(params[:batch_id])
#dates = #batch.fee_collection_dates
render :update do |page|
page.replace_html "fees_collection_dates", :partial =>"fees_collection_dates_voucher"
end
end
the method calls the following partial in _fees_collection_dates_voucher.html.erb file:
<%= select :fees_submission, :dates_id, #dates.map { |e| [e.full_name, e.id]},{:prompt => "#{t('select_fee_collection_date')}"},{:onChange => "#{remote_function( :url => {:action => "load_fees_voucher"},:with => "'date='+value+'&batch_id='+#batch.id") }"} %>
The partial makes a remote call to the load_fees_voucher method when a selection list value is selected or changed. However, I'm unable to pass the information in the #batch instance variable (from my original method) to the remote method via the partial. If I change the #batch.id to a hard-coded value in the last line (under :with) the code runs fine but not in the current format. Is there a different procedure to access instance variables in partials ? Thanks!
You can use the same instance variable in the partials.
Try this,
<%= select :fees_submission, :dates_id, #dates.map { |e| [e.full_name, e.id]},{:prompt => "#{t('select_fee_collection_date')}"},{:onChange => "#{remote_function( :url => {:action => "load_fees_voucher"},:with => "'date='+value+'&batch_id='+#{#batch.id}") }"} %>

Rails: confused about syntax for passing locals to partials

Understanding Rails "magic" with regards to rendering partials (and passing locals into them).
Why does this work:
<%= render "rabbits/form" %>
And this work:
<%= render "rabbits/form", :parent => #warren, :flash => flash %>
but this does not work:
<%= render "rabbits/form", :locals => { :parent => #warren, :flash => flash } %>
But this does:
<%= render :partial =>"rabbits/form", :locals => { :parent => #warren, :flash => flash } %>
Also, how can I look up these nuances so I don't need to bother people on S.O.?
The short answer is the render method looks at the first argument you pass in. If you pass in a hash (which includes :partial => 'foo', :locals => {blah blah blah}) then it will pass in all of your arguments as a hash and parse them accordingly.
If you pass in a string as your first argument, it assumes the first argument is your partial name, and will pass the remainder as your locals. However, in that subsequent call, it actually assigns :locals => your_locals_argument, which in this case is the entire :locals => {locals hash}, instead of just {locals hash}; i.e. you end up with :locals => {:locals => {locals hash}}, rather than :locals => {locals hash}.
So my advice is just to always explicitly pass values the same way all the time, and you won't have problems. In order to learn about this, I went directly to the code itself (actionpack/lib/base.rb, render() method in Rails 2; Rails 3 is different). It's a good exercise.
Furthermore, don't worry about "bothering" people on SO. That's why this site exists. I even learned something from this.
if you need to specify :locals, you need to specify :partial or :template
<%= render :partial => "rabbits/form", :locals => {...} %>
should work
To be honost, I only know about these use cases, because I have been keeping up with Rails for the last couple of years and read the announcements that a new way of doing it has been added. I often make a mistake in it myself, but usually it's easily corrected.
It's one of those parts of Rails API that hasn't been thoroughly thought through, if you ask me. It just accumulated more and more syntactic sugar over the years, without deprecating any of the old behavior. The render method has diabetes.
To make it even worse, render behaves differently in controller and view. I also looks at the first argument's content to see if it's a file, template, action or partial. If it starts with a slash then it's a file, or something like that.
I am in favor of using the shorter notation whenever possible. Because the short notations do communicate the intent quite well. When reading it, it usually does what you think it does. Writing partials is not straight forward.
Here is the source of render method from http://api.rubyonrails.org/classes/ActionView/Rendering.html#method-i-render:
def render(options = {}, locals = {}, &block)
case options
# Here is your last case
when Hash
if block_given?
_render_partial(options.merge(:partial => options.delete(:layout)), &block)
elsif options.key?(:partial)
_render_partial(options)
else
template = _determine_template(options)
lookup_context.freeze_formats(template.formats, true)
_render_template(template, options[:layout], options)
end
when :update
update_page(&block)
else
# here the first three cases
_render_partial(:partial => options, :locals => locals)
end
end
Hope this help!

Resources