I have a simple template system which calls a show_me
method defined inside different classes of my model (kinda Widgets) when rendering a template. These widgets originally returned the html as a string. So in my erb I have somethink like this.
<% @template.widgets.each do |widget| %>
<%= widget.show_me %>
<% end %>
As the views of the widgets became more complex I start using partials to render them, calling the ActionView::Base
render method from inside my widgets (please don't throw up yet :)
def show_me
# ... specific calculations and other magic.
ActionView::Base.new(MyApp::Application.config.view_path).render(:partial => "widgets/weather_widget", :locals => {:data => data, :settings => settings})
end
So, this works like a charm (really...) but when I want to use helpers inside the widget specific partial (eg. widgets/_weater_widget.html.erb
) they don't work. for example. javascript_tag
raises
can't convert nil into String
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:790:in `join'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:790:in `rails_asset_id'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:813:in `rewrite_asset_path'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:742:in `compute_public_path'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:256:in `javascript_path'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:822:in `javascript_src_tag'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:362:in `block in javascript_include_tag'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:362:in `collect'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:362:in `javascript_include_tag'
I think I'm missing something when I create the ActionView::Base.
Any thoughts how to solve this? Also any suggestion on the overall design is welcome too :)
You may be able to get a call to a view helper to work from a model, but Rails will fight you every step of the way. Rails doesn't want you to do things like this.
Consider introducing a widget presenter class. It could live in
app/helpers,
likeThat way you can use OO techniques to share presentation logic between widget presenters, and you can keep Rails happy (and future developers) by isolating your information from it's presentation.
Please for the love of all things MVC don't render view code from a model. :( There is always a better way to do it.
Example:
Model
Helper
View
Obviously that may not be the exact solution for your situation, but is just a guide to show you something that can be done to keep your code clean. :)