Reputation: 2185
I've been struggling on this for the last couple of day and some help would be greatly appreciated. A Rails app that has two models:
When creating a new balance
at http://localhost:3000/balances/new
, the form looks like this:
How can I enable users to be able to create multiple balances at the same time? There should only be one textbox for the date field which should be used for all the balances records created but there should be multiple account dropdown lists and balance textboxes on a form.
I've tried looking up nested forms but I'm struggling.
CODE
schema
create_table "accounts", force: :cascade do |t|
t.string "name"
t.boolean "credit"
t.boolean "active"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "balances", force: :cascade do |t|
t.decimal "balance"
t.date "date"
t.integer "account_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
account.rb
class Account < ActiveRecord::Base
has_many :balances
validates :name, presence: true, length: { maximum: 250 },
uniqueness: { case_sensitive: false }
end
balance.rb
class Balance < ActiveRecord::Base
belongs_to :account
#default_scope -> { order(date: :desc) }
validates :account, presence: true, length: { maximum: 250 }
end
accounts_controller.rb
....
def new
@account = Account.new
end
def create
@account = Account.new(account_params)
respond_to do |format|
if @account.save
format.html { redirect_to accounts_path, notice: 'Account was successfully created.' }
format.json { render :show, status: :created, location: @account }
else
format.html { render :new }
format.json { render json: @account.errors, status: :unprocessable_entity }
end
end
end
....
balances_controller.rb
....
def new
@balance = Balance.new
end
def create
@balance = Balance.new(balance_params)
respond_to do |format|
if @balance.save
format.html { redirect_to balances_path, notice: 'Balance was successfully created.' }
format.json { render :show, status: :created, location: @balance }
else
format.html { render :new }
format.json { render json: @balance.errors, status: :unprocessable_entity }
end
end
end
....
balances/_form.html.erb
<%= form_for(@balance) do |f| %>
<% if @balance.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@balance.errors.count, "error") %> prohibited this balance from being saved:</h2>
<ul>
<% @balance.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :date %><br>
<%= f.text_field :date %>
</div>
<div class="field">
<%= f.label :account_id %><br>
<%= f.collection_select(:account_id, Account.all.where(active: true).order('name ASC'), :id, :name,{})%>
</div>
<div class="field">
<%= f.label :balance %><br>
<%= f.text_field :balance %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Upvotes: 1
Views: 503
Reputation: 20263
So, it seems to me there's two parts to your challenge.
I'm not going to go into a lot of detail. Hopefully, this will point you in the right direction...
On your balances form, use form_tag
instead of form_for
which will allow you to represent multiple balances (instead of binding to a single balance instance). Create a balances partial (that includes the account name (as plain text, not a drop down), a balance input, and an account.id hidden field). Iterate on all active accounts, using the balances partial, to create the appropriate inputs. The date field will be outside the iterator so that you get your one date input. You can fiddle with all that so your balances all end up in one params hash.
In your controller, grab the params hash for balances, and iterate on that to create the balances using the one date value for each new balance.
I know that's very high level. And I apologize. But, writing out all the code is more than I have time for at the moment. Hope this helps you with the approach.
Upvotes: 1