How to render partial in lib ruby class using render_to_string - ruby-on-rails

I am writing a custom tag for Liquid and want to render a partial in the tag. I am assuming I have to use render_to_string but I can't seem to get it to work.
I've tried all sorts of things, including:
ActionController::Base.render_to_string(:partial => 'path/to/partial')
But nothing seems to work. There has to be some easy way to do this that I'm missing.
Thanks in advance.

The render_to_string method is an instance method:
ActionController::Base.new.send(:render_to_string,
:partial => 'path/to/partial')

Related

Rails views helper don't seems to work with render_to_string

I try to convert rails views into pdf with the gem wicked_pdf.
But when I do a render_to_string like this
ActionController::Base.new.render_to_string(template: "templates/pdf_meteo.html.erb", locals: {communaute_meteo_id: id}, layout: 'pdf')
Methods like user_path don't work and return undefined method error... (note that the page work properly if I render it in html)
If someone can help me !
You can include helpers by using the following method
ac = ActionController::Base.new
ac.view_context_class.include(ActionView::Helpers, ApplicationHelper)
ac.render_to_string(template: "templates/pdf_meteo.html.erb", locals: {communaute_meteo_id: id}, layout: 'pdf')
Unfortunately, using render_to_string will not give you access to Rails URL helpers. One workaround is to include them directly in the locals that you pass into the PDF template using something like url: Rails.application.routes.url_helpers:
ActionController::Base.new.render_to_string(
template: "templates/pdf_meteo.html.erb",
locals: {url: Rails.application.routes.url_helpers, communaute_meteo_id: id}
layout: 'pdf'
)
And then inside of your PDF template you would call them with:
url.user_path
Keep in mind that by default the _path URL helpers will be relative, and not absolute paths. You can instead use the _url version of the helpers and set the host for them in a few different ways. You can configure them globally for your entire app:
# config/environments/development.rb
Rails.application.routes.default_url_options[:host] = 'www.mysite.com'
or set them individually on each helper inside of your PDF template:
url.user_url(host: 'www.mysite.com')
Hope that gets you what you need!
Simplest way is to use regular rails rendering flow - with view file your_action_name.pdf.erb, trick is in overriding formats for partials:
<%= render partial:"some_partial", formats:[:html] %>
Also you can run render_to_string in context of your controller to have helpers (because ActionController::Base knows nothing about your app)

Can HAML do a "capture", kind of like a render_to_string in Ruby on Rails?

I heard that HAML has a capture function that can do something like Ruby on Rails's render_to_string, but can't find info on it. Actually, in View, we can use aString = render :partial ... and render actually works the same as render_to_string (as on Rail 2.2.2). But is there also an HAML way of doing it by capture?
Yes, you can capture the Haml buffer with capture_haml. You have to include Haml::Helpers in order to use it.
However, I am not sure if it works for capturing partials. From my understanding, I'd say that Haml is independent from render and thus, render_to_string or render :partial should also work for Haml.
At least, the following will work:
str = capture_haml do
haml_tag "p#feedback.success", "Your request has been successful."
end
str # => "<p id='feedback' class='success'>Your request has been successful.</p>"

Rails 3: Simple AJAXy Page updates?

I can't believe I've been looking four hours for this simple task, but I have.
In Rails 2.3, I could replace one section of a page with this simple code:
render :update do |page|
page.replace_html "div_id", :partial => "new_content",...
end
In Rails 3, Ryan Bates has me writing entire new javascript functions, switching from Prototype (rails default) to jQuery, and otherwise not enjoying life. The other tutes are no more straightforward.
What am I missing? How do we replace a <div> these days?
Thanks, guys. The official answer seems to be that, yes, the team felt simple is the enemy of good and made it more complicated.
The first key is to create a .js.erb file NAMED for the method CALLING the ajax update. So if the index method handles the update, put the raw javascript in index.js.erb. This goes in the views folder.
Second, the code that worked in index.js.erb was
m = $('list_users');
m.innerHTML = "<%= escape_javascript(render :partial => "reload_users") %>";
Then to make the call, add in the respond_to block of the controller method, add:
format.js
Finally, the calling view has:
<%= link_to "Update User List", #reload_users_path, :remote => true %>
By the way, supposedly all the old pages using page.replace will work if you install a plugin. The plugin download page suggests that it broke in the last releases of Rails 3 and has not been fixed. Also, various bloggers will come to your home and birch-switch you if you use it.
The whole RJS stuff makes the javascript inline and makes the dom very obtrusive. Also, by avoiding inline javascript you could open up other possible ways of optimizing you javascript by compressing and caching those files in browser. Thats the reason why RJS is getting out of scope from rails 3. A little bit of getting around with jQuery or Prototype for a day should get you on gears with these kind of small stuff and will help the project on long run.
Do you still have jQuery in there? I'd recommend it over Prototype any day...
If it's still there you can just use the following in your Javascript:
$.get("<%= url_for path/to/partial %>",
function(response) {
$("#div_id").html(response);
});
This gets the partial via AJAX and just dumps it into the div with id div_id.
Hope this helps!
I'm not even sure you need to make an AJAX call to load that partial. I believe that in a js.erb file, a call to render(:partial => object_or_path) will just return a string with all the html, which you can wrap in a jQuery object and append. Example:
$('#div_id').html($('<%= render :partial => #object %>'))
As far as I know, along the same line as the answer above, you can do something like this in your template:
<%= link_to "Update User List", #reload_users_path, :remote => true %>
And in controller, do this:
respond_to do |format|
format.js {
render :text => "alert('reloaded')"
}
end
This way you can have controller "execute" client side JS much the same as as render :update used to do. This is equivalent to doing the following in Rails 2:
render :update do |page|
page << "alert('reloaded')"
end
Is there any reason why this approach is not advisable?
Try this:
page.call "$('#div_id').html", render(:partial => 'new_content')

How to render a Partial from a Model in Rails 2.3.5

I have a Rails 2.3.5 application and Im trying to render several Partials from within a Model (i know, i know -- im not supposed to). The reason im doing this is im integrating a Comet server (APE) into my Rails app and need to push updates out based on the Model's events (ex. after_create).
I have tried doing this:
ActionView::Base.new(Rails::Configuration.new.view_path).render(:partial => "pages/show", :locals => {:page => self})
Which allows me to render simple partials that don't user helpers, however if I try to user a link_to in my partial, i receive an error stating:
undefined method `url_for' for nil:NilClass
I've made sure that the object being passed into the "project_path(project)" is not nil. I've also tried including:
include ActionView::Helpers::UrlHelper
include ActionController::UrlWriter
in the Module that contains the method that makes the above "render" call.
Does anyone know how to work around this?
Thanks
We use the render_anywhere gem and have been happy with it.
From the README:
require 'render_anywhere'
class AnyClass
include RenderAnwhere
def build_html
html = render :template => 'normal/template/reference',
:layout => 'application'
html
end
end
Including these two modules should be enough. Maybe you forgot to set default_url_options[:host]? Without it you can use _path helpers, but not _url ones.
Include these modules and check out if it works in irb, maybe it will lead you to right solution.

render_to_string in lib class not working

I'm trying to use delayed_job to update a remote database via xml
In my lib folder I put a file with a class that should do a render_to_text with template.xml.builder, but I get:
undefined method `render_to_string' for #<SyncJob:0x7faf4e6c0480>...
What am I doing wrong?
ac = ActionController::Base.new()
ac.render_to_string(:partial => '/path/to/your/template', :locals => {:varable => somevarable})
I had problems with a undefined helper method then I used ApplicationController
ApplicationController.new.render_to_string
render_to_string is defined in ActionController::Base. Since the class/module is defined outside the scope of the Rails controllers the function is not available.
You are going to have to manually render the file. I don't know what you are using for your templates (ERB, Haml, etc.). But you are going to have load the template and parse it yourself.
So if ERB, something like this:
require 'erb'
x = 42
template = ERB.new <<-EOF
The value of x is: <%= x %>
EOF
puts template.result(binding)
You will have to open the template file and send the contents to ERB.new, but that an exercise left for you. Here are the docs for ERB.
That's the general idea.
Rails 5
render_to_string and others are now available as class methods on the controller. So you may do the following with whatever controller you prefer: ApplicationController.render_to_string
I specifically needed to assign a dynamic instance variable for the templates based on an object's class so my example looked like:
ApplicationController.render_to_string(
assigns: { :"#{lowercase_class}" => document_object },
inline: '' # or whatever templates you want to use
)
Great blog post by the developer who made the rails PR: https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions
You could turn your template.xml.builder into a partial (_template.xml.builder) and then render it by instantiating an ActionView::Base and calling render
av = ActionView::Base.new(Rails::Configuration.new.view_path)
av.extend ApplicationController.master_helper_module
xml = av.render :partial => 'something/template'
I haven't tried it with xml yet, but it works well with html partials.

Resources