简体   繁体   English

电子商务运输和账单地址放入Rails的一张桌子中

[英]Ecommerce shipping and billing address into one table in rails

I'm trying to create an address form with shipping and billing address on same page. 我正在尝试在同一页面上创建一个包含运输和账单地址的地址表格。 When user gets ready for checkout , I want both shipping address form and billing address for to appear on same page. 当用户准备好结帐时,我希望送货地址表格和帐单邮寄地址都显示在同一页面上。 If billing address same as shipping address only record should be inserted into address table , if different two records has to be inserted and of course an update has to take place in orders table shipping_address_id,billing_address_id. 如果帐单地址与送货地址相同,则仅记录应插入地址表中,如果必须插入不同的两个记录,则当然必须在订单表shipping_address_id,billing_address_id中进行更新。

Having only one address model, how do I achieve two forms with one submit button. 只有一个地址模型,如何使用一个提交按钮来实现两种形式。 Below is my model for address and orders 以下是我的地址和订单模型

I need some help in putting in controller also I'm trying to get a hash value for each billing and shipping 我在放置控制器时需要一些帮助,我正在尝试获取每次结算和运输的哈希值

Please help!!! 请帮忙!!!

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

This is a slightly complicated problem, you will find. 您会发现这是一个稍微复杂的问题。

First, ask yourself: Do you really only want to insert one address if billing and shipping addresses are the same? 首先,问问自己:您真的只想在帐单和送货地址相同的情况下插入一个地址吗?

  1. A customer wants to change the shipping address. 客户想更改送货地址。 You will need logic to create another address record and retain the original as billing. 您将需要逻辑来创建另一个地址记录并将原始记录保留为开票。
  2. Generally, avoid updates to billing and shipping addresses after an order is complete as they compromise data integrity. 通常,避免在订单完成后更新账单和收货地址,因为这会损害数据完整性。 Once an order is closed, that's it; 一旦关闭订单,就是这样; those addresses should be fixed. 这些地址应该是固定的。 When an order requires a different shipping address, avoid having a dependency between it and the billing address. 当订单需要其他送货地址时,请避免订单和帐单地址之间存在依赖关系。

Now, assuming you're going ahead. 现在,假设您要继续前进。

Using Nested Forms 使用嵌套表单

Hide billing fields, and add a check box to your form that maps to an order.bill_to_shipping_address . 隐藏帐单字段,并在您的表单中添加一个复选框,以映射到order.bill_to_shipping_address Default it to checked. 默认为选中状态。 Show billing address if it gets unchecked. 如果未选中,则显示帐单邮寄地址。

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

In your order model: 在您的订单模型中:

accepts_nested_attributes_for :shipping_address
accepts_nested_attributes_for :billing_address, reject_if: :bill_to_shipping_address

The draw back with this approach is, if there is a validation error, and the user happens to change his mind and bill to a different address, the billing form will not appear since it gets rejected. 这种方法的缺点是,如果存在验证错误,并且用户碰巧改变了主意并将帐单转到其他地址,则不会出现帐单,因为它被拒绝了。

Use a Form Object 使用表单对象

This might seem more complex, but it's a much cleaner solution. 这似乎更复杂,但是它是一种更干净的解决方案。

See 7 Patterns for refactoring ActiveRecord Objects . 请参阅7种用于重构ActiveRecord对象的模式

Build a form object as such. 这样构建一个表单对象。 I've adopted this code from something I recently wrote for a Rails 4 app. 我采用了我最近为Rails 4应用编写的内容中的代码。 Just reverse your relationships. 只是扭转你的关系。 In my case an order has one billing address and one shipping address; 就我而言,订单有一个帐单地址和一个送货地址; it does not belong to them. 它不属于他们。

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

Then from the controller: 然后从控制器:

  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

Your form now does not care about nested attributes and properties. 您的表单现在不再关心嵌套的属性和属性。 It's nice a clean. 很干净。

= form_for @order do |f|
  = f.text_field :email
  = f.text_field :shipping_street
  = f.text_field :billing_street
  # etc...

I'd suggest using a checkbox so the user can specify whether use the same billing and shipping address or type different ones. 我建议使用复选框,以便用户可以指定使用相同的帐单和送货地址还是键入不同的帐单和送货地址。

In the form file you need to handle nested forms in the following way: 在表单文件中,您需要通过以下方式处理嵌套表单:

   = form_for @order do f 
     = f.fields_for :billing_address do |ba|                
       = ba.text_field :address1
       = ba.text_field:address2
       = ba.text_field :city
       = ba.text_field :state
       = ba.text_field :zip
       = ba.text_field :phone
     = f.fields_for :shipping_address do |sa|                
       = sa.text_field :address1
       = sa.text_field:address2
       = sa.text_field :city
       = sa.text_field :state
       = sa.text_field :zip
       = sa.text_field :phone

In your model don't forget to add: 在您的模型中不要忘记添加:

accepts_nested_attributes_for :shipping_address
accepts_nested_attributes_for :billing_address

And probably need to add the autobuild to your address relations 可能需要将自动构建添加到您的地址关系中

belongs_to :billing_address, :class_name => "Address", autobuild: true
belongs_to :shipping_address, :class_name => "Address", autobuild: true

In the controller create/update actions, you just need to check the checkbox value and assign them equal, here's one approach: 在控制器的create / update操作中,您只需要检查复选框的值并将它们分配为相等,这是一种方法:

@order.shipping_address = @order.billing_address if params[:checkbox_use_same_address] == true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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