Output content from render_to_string using global variable - ruby-on-rails

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

Related

Why is my template variable being ignored in 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'}

Is it possible to pass parameters when using 'def_erb_method'?

My current code is this.
<%= render 'codes/code', {:code => code, :icon_photo => code.community.community_icon} %>
I tried to use 'def_erb_method', so I changed the code to this
<%#= raw render_code(code), {:code => code, :icon_photo => code.community.community_icon} %>
codes_helper.rb
module CodesHelper
extend ERB::DefMethod
def_erb_method('render_code(code)', "#{Rails.root}/app/views/codes/_code.html.erb")
end
However, I got this error back:(
undefined local variable or method `icon_photo'
I cannot pass the parameters when using 'def_erb_method'?

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}") }"} %>

How to “dynamically add options” to 'form_for'?

I am using Ruby on Rails 3.2.2. In order to implement a "dynamic generated" AJAX style file upload form I would like to "dynamically add options" to the FormHelper#form_for statement if some conditions are meet. That is, at this time I am using code as-like the following (note that I am using the merge method in order to add options to the form_for method):
<%
if #article.is_true? && (#article.is_black? || && #article.is_new?)
form_options = {:multipart => true, :target => "from_target_name"}
else
form_options = {}
end
%>
<%= form_for(#article, :remote => true, :html => {:id => "form_css_id"}.merge(form_options)) do |form| %>
...
<% end %>
However, I think that the above code is too much hijacked.
Is there a better way to accomplish what I am making? For example, can I access from view templates some (unknown to me) instance variable named as-like #form and "work" on that so to change related options as well as I would like? Or, should I state a helper method somewhere? How do you advice to proceed?
BTW: Since the upload process is handled by using a HTML iframe, I am using the remotipart gem in order to implement the AJAX style file upload form - I don't know if this information could help someone...
This looks like a good candidate for a helper method. In your view:
<%= form_for(#article, :remote => true, :html => article_form_options(#article, :id => "form_css_id")) do |form| %>
...
<% end %>
In app/helpers/articles_helper.rb
module ArticlesHelper
def article_form_options(article, defaults = {})
extras = if article.is_true? && (article.is_black? || article.is_new?)
{ :multipart => true, :target => 'form_target_name' }
else
{}
end
defaults.merge(extras)
end
end
Helpers are a good place to keep logic that's too complex for a view but still related to the view.

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