I have a form for creating a model (named Image) and the list for all entities of this model on the same view. The model is associated in a one-to-many relation with a second model called Deck (one Deck has many Images). The list in my view looks like this:
# image list
<% @deck.images.each do |img| %> # iterates also through invalidated model
<%= link_to 'Delete', deck_image_path(@deck, img),
:confirm => 'Sure?', :method => :delete %>
<% end %>
My problem occurs when the validation for the @image object fails. The iteration iterates also through the invalid image object and gives an error for the next line saying there is no such path for that object.
I could check every object for .new_record?, but is this the preferred way? Or am I doing something absolutely wrong? I have nobody else seen with such a problem ;/
Update 1 – Controller
def create
@deck = Deck.find(params[:id])
@image = @deck.images.build(params[:image])
respond_to do |format|
if @image.save
# redirect
flash[:notice] = "Saved succesfully."
format.html { redirect_to(@deck) }
else
# render
format.html {
flash.now[:error] = "Could not be saved."
render 'decks/show'
}
end
end
end
Update 2 – More confusion
Well, ok I am absolutely confused now. Changing the second line in the create method from
# not working
@image = @deck.images.build(params[:image])
to
# working
@image = Image.new(params[:image])
@image.deck = @deck
seems to work without any errors. What is the difference?
Update 3 – View and error message
<h3>Upload Image</h3>
<%= form_for @image, :url => deck_images_path(@deck), :html => { :multipart => true } do |form| %>
<fieldset>
<legend>Upload new image</legend>
<%= render :partial => 'shared/model_errors', :locals => {:model => @image} %>
<%= form.file_field :image %><br/>
<%= form.submit "Upload", :class => 'btn btn-primary' %>
</fieldset>
<% end %>
<h3>Show all existing images</h3>
<% @deck.images.each do |img| %>
<%= image_tag img.image.url %>
<%= link_to 'Delete'.html_safe, deck_image_path(@deck, img) %>
<% end %>
The error message:
No route matches {:controller=>"images", :action=>"destroy", :deck_id=>#<Deck id: 1,
name: "Test", description: "Test", created_at: "2012-12-10 20:44:22",
updated_at: "2012-12-10 20:44:22">, :id=>#<Image id: nil, created_at: nil,
updated_at: nil, image_file_name: nil, image_content_type: nil,
image_file_size: nil, image_updated_at: nil, deck_id: 1>}
According to [1]: Build vs new in Rails 3 parent_model.children.build oder parent_model.children.new seems to create a relationship in memory instantly. So parent_model.children gets filled with a new children model having its parent_id = parent.
The alternative with Children.new seems to add this new relationship after saving the new child object. Therefore its missing in an iteration over all children.