2016-03-18 7 views
0

Ich baue einen einfachen einseitigen Einkaufswagen mit Rails und Javascript.Einkaufswagen mit vielen Eingaben number_field in Rails

Ich habe eine Datenbank mit meiner ~ 8 Produkte und das ist, wie meine Shopping-Seite wie folgt aussieht:

<%= form_for @order do |f| %> 
    <% @product.each do |product| %> 
     <%= f.number_field(:product, class: "order-list", name: "#{product.name}", data: {price: "#{product.price}"}, value: 0, in: 0..5) %> 
    <% end %> 
    <%= f.submit "Continue" %> 
<% end %> 

Wenn ich auf Senden klicken, erhalte ich diese params

{"utf8"=>"✓", "authenticity_token"=>"mkFBHjgsGZ/dwmQ+Ct6HzafLNwDQlVXOVTdsO97IUUrg7PV9HlpdzJa9Iy03I85t0Nx7dUBKuqZfuGmE700fFQ==", "NameofProduct1"=>"0", "NameofProduct2"=>"0", "NameofProduct3"=>"2", "NameofProduct4"=>"1", "NameofProduct5"=>"0", "commit"=>"Continue", "controller"=>"orders", "action"=>"create"} 

Was ist der beste Weg, um ähnliche Einkaufswagen mit nur Eingabe Zahlenfelder zu behandeln? Wie geht man mit den Params um? Auf der Serverseite sollte ich mit allen Produkten eine Schleife machen, den Namen finden, ihn mit der Menge verschmelzen und in der Datenbank speichern? Ist es eine gute Idee, jedes Produkt als Objekt in einem Array zu speichern?

Auch, wie man mit dem Modell umgeht: um es nur params mit Wert mehr als 0 zu übergeben? Weil ich Zugang wie "NameofProductxxxx" habe.

In Zukunft möchte ich es DRY haben - wenn ich Produkt hinzufügen möchte ich nicht das Modell oder die Parameter ändern.

Die letzte Seite sieht wie folgt aus (Entschuldigung für die lokale Sprache): Danke

enter image description here

Antwort

2

Zuerst Sie einrichten müssen einen richtigen viele zu viele Beziehung zwischen Auftrag und Produkt.

class Order < ActiveRecord::Base 
    has_many :line_items 
    has_many :products, through: :line_items 
    accepts_nested_attributes_for :line_items 
end 

# as in a row on a order form. 
class LineItem < ActiveRecord::Base 
    belongs_to :order 
    belongs_to :product 
end 

class Product < ActiveRecord::Base 
    belongs_to :order 
    belongs_to :product 
    has_many :orders, through: :line_items 
end 

Sie können die LineItem Modell erzeugen mit:

rails g model LineItem order:belongs_to product:belongs_to quantity:integer 

Sie könnten ein Doppeltyp für quantity verwenden möchten, wenn Sie mit Dezimalzahlen zu tun haben.

Sie würden dann fields_for verwenden, um Felder zum Erstellen/Aktualisieren der verknüpften Werbebuchungen gleichzeitig mit der Bestellung zu erstellen. fields_for iteriert durch die zugehörigen Datensätze und schafft „scoped“ Eingänge:

<%= form_for(@order) do |f| %> 
    <%= f.fields_for(:line_items) do |ff| %> 
    <%= ff.collection_select(:product_id, Product.all, :id, :name) %> 
    <%= ff.label(:quantity) %> 
    <%= ff.number_field(:quantity) %> 
    <% end %> 
<% end %> 

Beachten Sie, dass Sie nicht über eine Auswahl für das Produkt-ID verwenden müssen - es könnte genauso gut ein verstecktes Feld sein. Absenden des Formulars sollte in params Hash-Ergebnis, das wie folgt aussieht:

order: { 
    line_items_attributes: [ 
    { 
     product_id: 6, 
     quantity: 4 
    } 
    ] 
} 

Da unser Auftragsmodell accepts_nested_attributes_for :line_items Sie die params wie so weiße Liste würde:

class OrdersController < ApplicationController 

    def new 
    @order = Order.new 
    @order.line_items.new # seeds form with an empty item. 
    end 

    def create 
    @order = Order.create(order_params) 
    respond_with(@order) 
    end 

    def update 
    @order = Order.find(params[:id]) 
    @order.update(order_params) 
    respond_with(@order) 
    end 

    private 
    def order_params 
    params.require(:order).permit(line_items_attributes: [:product_id, :quantity]) 
    end 
end 

Anzeige der Kosten pro Zeile die nächste Sorge ist, das musst du lösen.

Normalerweise würde man nur so etwas wie:

class LineItem < ActiveRecord::Base 
    belongs_to :order 
    belongs_to :product 

    def total 
    product.price * quantity 
    end 
end 

<%= f.fields_for(:line_items) do |ff| %> 
    <%= ff.collection_select(:product_id, Product.all, :id, :name) %> 
    <%= ff.label(:quantity) %> 
    <p><%= ff.object.total if ff.object.persisted? %></p> 
<% end %> 

Allerdings, wenn Sie die Gesamt aktualisieren möchten, wenn der Benutzer ändert sich die Menge oder der Artikel, den Sie einen AJAX-Aufruf implementieren müssen, die ist eine konkurrierende Frage oder ein Tutorial für sich.

+0

Stellen Sie sicher, dass Sie die Dokumentation für ['access_nested_attributes'] (http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html) gelesen haben. Dies ist einer der schwierigsten Teile des Rails-Kerns. – max

+0

Wow, erstaunlich. Danke Max! – Dudis

+0

Max, kann ich zusätzliche Fragen haben? Just thinking .. wenn ich nur ein paar Produkte mit Zahleneingaben habe ... ist es nicht einfacher, es mit einem einzigen Produkt db & Einzelauftrag db zu tun und der Warenkorb zeigt auf Javascript basiert - wenn der Wert eines Produkts steigt, wir wird es im Warenkorb zeigen ... ohne es in db zu speichern. Was ist deine Meinung dazu? Vorteile gegen Nachteile? – Dudis

Verwandte Themen