This bug has me perplexed.
I am displaying a Widget with the last 5 data points and a form for a new data_point. When I try to render both the form and the display partial it fails with a routing error. If I comment out either partial it works fine. So with only the form partial it works, or with only the display partial it works fine with the other.
Three relevant models/controllers: Widget, DataSet and DataPoint. DataPoints is STI so I have different partials to display the different types that match the class name.
When both render :partial => ... are uncommented it looks as if the data_point being passed to the second partial is the same as the data_point being passed to the first partial. It is all nil with only a data_set_id. I tried renaming the local from :data_point to :dp in case it was a name collision.
View, both partials and the routing error shown at the bottom.
Is there a limitation on passing :locals to partials when you are trying to render more than one partial in a view?
View: show.html.haml (the show action on the controller is empty)
- title "#{@widget.type.underscore.humanize} for #{@widget.data_set.name.to_s.downcase}"
.row
.span6
= render :partial => 'data_points/form', :locals => { :data_set => @widget.data_set, :data_point => @widget.data_set.data_points.build }
%br
- last_5 = @widget.data_set.data_points.last(5)
- if last_5.count > 0
%h3= "Last #{pluralize( last_5.count, 'Entry' )}"
- last_5.each do |dp|
%pre
= dp.inspect
= render :partial => "data_points/#{@widget.data_set.data_type.underscore}", :locals => { :data_set => @widget.data_set, :data_point => dp }
- else
%h3 No data yet!
= form_tag( push_widget_path @widget, :method => 'POST' ) do
= submit_tag( "Push Data", :class=>"btn btn-primary" )
= link_to "Edit your data", data_set_path( @widget.data_set ), :class=>'btn'
.span6
= image_tag "widgets/#{@widget.type.underscore}.png"
%p
Using the
%b= link_to @widget.data_set.name, @widget.data_set
data set.
= render :partial => "widgets/#{@widget[:type].underscore}", :locals => { :widget => @widget } rescue nil
%p
= link_to 'Edit', edit_widget_path(@widget), :class=>'btn'
Form Partial (data_points/_form.html.haml)
%pre
= data_set.inspect
%pre
= data_point.inspect
= form_for [data_set,data_point], :html=>{:class => 'well form-horizontal'} do |f|
-if data_point.errors.any?
#error_explanation
%h2= "#{pluralize(data_point.errors.count, "error")} prohibited this data_point from being saved:"
%ul
- data_point.errors.full_messages.each do |msg|
%li= msg
= render :partial => "data_points/#{data_set.data_type.underscore}_form", :locals => { :f => f, :data_point => data_point, :data_set => data_set }
= f.text_field :created_at, :type=>'datetime'
.form-actions
= f.submit 'Save'
Display Partial (data_points/_multi_value_data_point.html.haml)
.data-point{ :id=>"data-point-#{data_point.id}"}
%span.value
- data_point.data.map do |k,v|
- label = data_set.properties[:data_series][k][:name]
%span.key= "#{label}: "
= v
.meta
= data_point.created_at
%span.edit
= link_to 'Edit', edit_data_set_data_point_path( data_set, data_point )
%span.delete
= link_to 'Destroy', [data_set, data_point], :method => :delete, :data => {:confirm => 'Are you sure?'}
=# link_to 'Edit', '#', id: "edit-data-point-#{data_point.id}"
:javascript
$("#edit-data-point-#{data_point.id}").click( function(e) {
$("#data-point-#{data_point.id}").html( "#{escape_javascript( render :partial => "data_points/multi_value_data_point_form", :locals => { data_set: data_set, data_point: data_point } )}");
return false;
});
Routing Error
Routing Error
No route matches {:action=>"edit", :controller=>"data_points", :data_set_id=>#<MultiValueDataSet id: 4, ... properties removed ... type: "MultiValueDataSet">, :id=>#<DataPoint id: nil, data: {}, data_set_id: 4, created_at: nil, updated_at: nil>}
Try running rake routes for more information on available routes.
The problem stems from the fact that the form is building a new element that isn’t saved, and last is returning that unsaved element.
Simple solution, replace .last(5) with .find( :all, order: ‘id desc’, limit: 5 )