2

同じページに配送先住所と請求先住所を含む住所フォームを作成しようとしています。ユーザーがチェックアウトの準備ができたら、配送先住所フォームと請求先住所の両方を同じページに表示したい。配送先住所と同じ請求先住所のみのレコードを住所テーブルに挿入する必要がある場合、異なる 2 つのレコードを挿入する必要があり、もちろん注文テーブル shipping_address_id,billing_address_id で更新を行う必要があります。

アドレス モデルが 1 つしかない場合、1 つの送信ボタンで 2 つのフォームを実現するにはどうすればよいですか。以下は、住所と注文の私のモデルです

また、請求と配送ごとにハッシュ値を取得しようとしています。

助けてください!!!

class Address < ActiveRecord::Base
  attr_accessible :name,:first_name,:last_name,:address1,:address2,:city,:state,:zip,:phone,:billing_default,:      user_id,:billing_address, :shipping_address
  belongs_to :user
  has_many :billing_addresses, :class_name => "Order", :foreign_key => "billing_address_id" 
  has_many :shipping_addresses, :class_name => "Order", :foreign_key => "shipping_address_id"

class Order < ActiveRecord::Base
  attr_accessible :cart_id, :order_no, :sales_tax, :shipping_fee,:total,:order_state,:gateway_type,:transaction_id,:transaction_status,:ip_address,:card_verification,:card_number,:billing_address_id,:shippin g_address_id,:first_name,:last_name,:user_id,:card_expires_on,:authenticity_token
  belongs_to :cart
  belongs_to :user
  belongs_to :billing_address, :class_name => "Address"
  belongs_to :shipping_address, :class_name => "Address"
  attr_accessor :card_number
  has_many :transactions, :through => :order_id
  has_many :invoices
  has_many :order_details
4

2 に答える 2

14

これは少し複雑な問題です。

まず、自問してみてください。請求先住所と配送先住所が同じ場合、本当に 1 つの住所だけを挿入したいのでしょうか。

  1. お客様が配送先住所の変更を希望しています。別のアドレス レコードを作成し、元のレコードを請求として保持するためのロジックが必要になります。
  2. 通常、注文が完了した後に請求先住所と配送先住所を更新すると、データの整合性が損なわれるため、更新は避けてください。注文が完了したら、それで終わりです。これらのアドレスは修正する必要があります。注文で別の配送先住所が必要な場合は、注文先住所と請求先住所の間に依存関係がないようにしてください。

今、あなたが先に進んでいると仮定します。

ネストされたフォームの使用

請求フィールドを非表示にし、フォームにチェック ボックスを追加して、 にマップしますorder.bill_to_shipping_address。デフォルトでオンにします。チェックを外すと請求先住所を表示します。

  $('input[name="order[bill_to_shipping_address]"]').on 'click', ->
    if $(this).is ':checked'
      $('fieldset.billing_fields').hide()
    else
      $('fieldset.billing_fields').show()

注文モデル:

accepts_nested_attributes_for :shipping_address
accepts_nested_attributes_for :billing_address, reject_if: :bill_to_shipping_address

このアプローチの欠点は、検証エラーがあり、ユーザーが気が変わって別の住所に請求した場合、拒否されるため請求フォームが表示されないことです。

フォーム オブジェクトを使用する

これはより複雑に見えるかもしれませんが、よりクリーンなソリューションです。

ActiveRecord オブジェクトをリファクタリングするための 7 パターン を参照してください

そのようなフォームオブジェクトを構築します。このコードは、Rails 4 アプリ用に最近​​書いたものから採用しました。あなたの関係を逆にするだけです。私の場合、注文には 1 つの請求先住所と 1 つの配送先住所があります。それは彼らのものではありません。

class OrderForm
  include ActiveModel::Model

  def self.model_name
    ActiveModel::Name.new(self, nil, "Order")
  end

  def persisted?
    false
  end

  attr_accessor :params

  delegate :email, :bill_to_shipping_address, to: :order

  # Removed most fields for brevity
  delegate :name, :street, :street_number, to: :shipping_address, prefix: :shipping
  delegate :name, :street, :street_number, to: :billing_address,  prefix: :billing

  # Removed most fields for brevity    
  validates :email, length: { maximum: 60 }, email_format: true
  validates :shipping_name, :shipping_street, presence: true    
  validates :billing_name, presence: true, unless: -> { bill_to_shipping_address }

  def initialize(params = nil)
    @params = params
  end

  def submit
    populate
    if valid?
      order.save!
      true
    else
      false
    end
  end

  def order
    @order ||= Order.new
  end

  private

  def shipping_address
    @shipping_address ||= order.build_shipping_address
  end

  def billing_address
    @billing_address ||= order.build_billing_address
  end

  def populate
    order.email = params[:email]
    order.bill_to_shipping_address = params[:bill_to_shipping_address]

    shipping_address.name = params[:shipping_name]
    # etc...

    unless order.bill_to_shipping_address?
      billing_address.name = params[:billing_name]
      # etc...
    end
  end
end

次に、コントローラーから:

  def new
    @order_form = OrderForm.new
  end

  def create
    @order_form = OrderForm.new(params[:order])
    if @order_form.submit
      # order saved, do whatever
    else
      render 'new'
    end
  end

フォームは、ネストされた属性とプロパティを気にしなくなりました。きれいでいいですね。

= form_for @order do |f|
  = f.text_field :email
  = f.text_field :shipping_street
  = f.text_field :billing_street
  # etc...
于 2013-07-25T16:11:12.663 に答える