So I'm fairly new with Rails and I'm trying to figure out the best way of generation a complex form. The basic idea is that a user places an order
, each order
is made up of one or more pizza_order
, each pizza_order
consists of either a special
pizza or just a pizza
. The main issue I'm having right now is how do I generate a dynamic form where the user can consistently generate an arbitrary amount of new pizza_order
models?
My thought was to have a button that they would press, and each time the button is pressed to render a partial view that consists of the fields necessary for a new pizza_order
. When the user presses submit the order
is generated, along with an array of new pizza_order
models that are associated with that order
. These are what my models look like so far.
Order
class Order < ActiveRecord::Base
belongs_to :user
has_many :pizza_orders
accepts_nested_attributes_for :pizza_orders
end
Pizza Order
class PizzaOrder < ActiveRecord::Base
belongs_to :pizza, polymorphic: true
belongs_to :order
end
Pizza
class Pizza < ActiveRecord::Base
has_and_belongs_to_many :toppings
has_many :pizza_orders, as: :pizza
belongs_to :crust
validates :crust, presence: true
end
Special
class Special < ActiveRecord::Base
belongs_to :pizza
validates :pizza, :presence => true
validates :cost, :presence => true
end
I'm fairly lost on what the controller and view will look like, so far this is the general layout for my view, I'll worry about filling in the attributes later, I'm more concerned with getting the proper rails fields set up.
<%= form_for @order do |t| %>
<%= t.fields_for t.pizza_orders do |po| %>
<% end%>
<!--Insert new pizza_orders after marker -->
<span id="marker"></span>
<%= button_tag "New Order", :type => 'button', :id => 'test' %>
<%= t.submit "Place Order" %>
<% end %>
If I'm understanding your plight correctly, this is a job for Cocoon! Cocoon allows you to generate dynamic nested fields (as many as you want).
So what I'd do is:
Watch this video You can fast forward to where he's showing how to dynamically add ingredients to recipes but really this entire tutorial is a FANTASTIC reference that will save you lots of googling.
Then in your pizza order view, render a partial (just as you said) only do it with cocoon.
<%= simple_form_for @order do |t| %>
<%= t.simple_fields_for :pizza_orders do |po| %>
<%= render 'order_fields', p: po %>
<% end%>
<div class="add-field"><%= link_to_add_association 'Add Pizza Order', t, :pizza_orders %></div>
<!--Insert new pizza_orders after marker -->
<span id="marker"></span>
<%= button_tag "New Order", :type => 'button', :id => 'test' %>
<%= t.submit "Place Order" %>
<% end %>
Then create the partial _order_fields.html.erb
and put whatever fields you need as follows:
<div class="nested-fields">
<%= p.input :order_field1 %>
<%= p.input :order_field2 %>
<%= p.input :order_field3 %>
<%= link_to_remove_association "Delete", p %>
</div>
Remember to do your strong params just like any other nesting and you should be all set! Also make sure the parent model accepts_nested_attributes_for
the child and is allowed to destroy it.
Now, regarding the rest of your code: I think you might be making your models overly complicated. While I don't know the fields you're dealing with my intuition is that your use of polymorphic associations is unnecessary.
At a glance I would set it up like this Two, maybe three models:
Order
would has_many :pizzas
Data about crust type, price of the pizza would be saved within each pizza's model. Like so: rails g model Pizza price:decimal crust:string type:string
. If it's a special, let the type be "special."
Extra model associations muddies your code, hinders you from using available tools and may lead to increased blood pressure. Pizza is one of life's simple pleasures and should be left unburdened by polymorphic associations; for the sake of yourself, don't over-complicate it. :-D
You will need the Simple Forms gem to copy what I have above directly. (I highly recommend it.) Please note that you will need to change form_for
to simple_form_for
and fields_for
to simple_fields_for
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.