[英]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? 首先,问问自己:您真的只想在帐单和送货地址相同的情况下插入一个地址吗?
Now, assuming you're going ahead. 现在,假设您要继续前进。
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. 这种方法的缺点是,如果存在验证错误,并且用户碰巧改变了主意并将帐单转到其他地址,则不会出现帐单,因为它被拒绝了。
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.