Rendering a partial in assets
-
27-10-2019 - |
题
I'm using Ruby on Rails 3.1 and I'm wondering how I could render a partial in a javascript asset.
What I'm aiming at:
# in /app/assets/javascript/cart.js.coffee.erb
$('a.add_sth').click -> $('.random_container').append('<%= render partial: 'way/to/partial' %>')
This causes a NoMethodError:
undefined method `render' for #<#<Class:0x007fc54584c6e8>:0x007fc5474cd470>
If I write <%= 2+3 %>
instead it works fine, btw.
I think the problem is that the asset pipeline is independent from the default ActionView and that's why render()
is unknown there. Anyway, is there a way to get that partial's content rendered?
解决方案
Bad news, render is not available Look: same question on GitHub
其他提示
Remember that assets are meant for static data, like CSS, JS or images that will not dynamically change its contents, so they can be better cached and/or exported to a CDN.
Since you are allowed to run ERB with ruby code, it should always return the same value (since it will be executed only when compiling the asset).
That's why I guess render is not available inside assets (although it could be properly used to render static data).
Easy solution here: move your JS file to a view, there you will be able to use any view helper.
This worked for me. (for HAML)
= Haml::Engine.new(File.read(File.join(Rails.root, 'app/views/xxxxx','_form.html.haml'))).render(Object.new, :hello => "Hello World")
And, needed to add dependency in the beginning of file to be updated like: In this case, the depended file is needed to be in the asset.
//= depend_on xxxxx/_form.html.haml
In rails 4.2
I found this post https://github.com/sstephenson/sprockets/issues/90 which suggests using <% require_asset 'path/to/file' %>
This worked for me.
I had similar issue, so I wrote this render
method, that can be used inside assets to render ERB partial template:
# in lib/my_app/erb_helpers.rb
module MyApp
module ERBHelpers
class << self
def render(partial_path, binding)
dir_name, _, partial_name = partial_path.rpartition(File::SEPARATOR)
file_name = "_#{partial_name}.html.erb"
Erubis::Eruby.new(File.read(File.join(Rails.root, 'app', 'views', dir_name, file_name)).gsub("'", %q(\\\'))).result(binding)
end
end
end
end
Then I used it inside coffeescript file like this:
# in app/assets/javascripts/notifications.coffee
MyApp.notifications.templates =
notice: '<%= ::MyApp::ERBHelpers.render 'application/notifications/notice', content: "%content%" %>'
alert: '<%= ::MyApp::ERBHelpers.render 'application/notifications/alert', content: "%content%" %>'
MyApp.notifications.create_elem = (type, content) -> MyApp.notifications.templates[type].replace('%content%', content)
PS: I tested it on Rails 5.0 app
In fact, it works for me. You need to do:
= render 'way/to/partial'
where 'way/to/partial' is relative path under existing assets folder. Wired thing is that in the path, you need to omit the first level folder under assets.