I am trying to create multiple items (each with a name value and a content value) in a single form. The code I have is functioning, but I cannot figure out how to ignore items that are blank. Here's the code:
#item.rb
class Item < ActiveRecord::Base
attr_accessible :name, :content
validates_presence_of :name, :content
end
#items_controller.rb
class ItemsController < ApplicationController
def new
@items = Array.new(3){ Item.new }
end
def create
@items = params[:items].values.collect{|item|Item.new(item)}
if @items.each(&:save!)
flash[:notice] = "Successfully created item."
redirect_to root_url
else
render :action => 'new'
end
end
#new.html.erb
<% form_tag :action => 'create' do %>
<%@items.each_with_index do |item, index| %>
<% fields_for "items[#{index}]", item do |f| %>
<p>
Name: <%= f.text_field :name %>
Content: <%= f.text_field :content %>
</p>
<% end %>
<% end %>
<%= submit_tag %>
<% end %>
This code works when all fields for all items are filled out in the form, but fails if any fields are left blank (due to validations). The goal is that 1 or 2 items could be saved, even if others are left blank.
I'm sure there is a simple solution to this, but I've b开发者_运维技巧een tinkering for hours with no avail. Any help is appreciated!
I'd do this:
class Item
def empty?
attributes.values.compact.empty?
end
end
# in ItemsController
if @items.reject(&:empty?).all(&:save)
A couple notes:
- You were using
save!
, but you probably wantsave
.save!
would raise an exception if one of the items was invalid, and you'd just see an error page instead of yournew
template. - I replaced
each
withall
.each
wouldn't do what you intended--which is to returntrue
if and only if all of the Items validated and saved.all
does just that.
I'm not sure this is the best solution, but perhaps you could do something like:
@items.reject! { |item| item.attributes.values.compact.empty? }
精彩评论