简体   繁体   中英

Ruby on Rails: Complex Form Generation

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:

install the cocoon gem

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:

  1. Order
  2. Pizza
  3. Toppings? (another use for cocoon)

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

Edit

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM