使用表单对象模式时,选中了Rails复选框会更新送货地址

时间:2019-01-23 15:49:43

标签: ruby-on-rails

所以我有一个表格,试图让用户将文本从帐单复制到送货地址。不幸的是,目前它正在自动将帐单地址保存在送货地址中。

我的表单如下所示(尽管由于大量字段而被截断了):

=form_for @customer, url: create_customer_path, html: {class: 'new-customer} do |f|
 .row
  .col-md-4
   = f.label :first_name
  .col-md-8
   = f.text_field :first_name, class: 'form-control', required:true
 .row
  .col-md-4
   = f.label :billing_address1
  .col-md-8
   = f.text_field :billing_address1, class: 'form-control', required:true
 .row
  .col-md-12
   = f.check_box :shipping_is_billing
   = f.label :shipping_is_billing, 'Same as billing address'
 .row
  .col-md-4
   = f.label :shipping_address1
  .col-md-8
   = f.text_field :shipping_address1

CustomersController

class CustomersController < ApplicationController

  def new
    @customer = CustomerForm.new
  end

  def create
    @customer = CustomerForm.new(customer_params)
    if @customer.save
      redirect_to customer_success_path
    else
      render 'new'
    end
  end

  private

  def customer_params
    params.require(:customer_form).permit!.tap do |p|
      p[:captcha_response] = params['g-recaptcha-response']
    end
  end

end

CustomerForm(对于大量字段被截断)

class CustomerForm
  include ActiveModel::Model

  CUSTOMER_ATTRS = %w[
    first_name
  ].freeze

  ADDRESS_ATTRS = %w[
    address1 address2 city state zip
  ].freeze

  attr_accessor(*CUSTOMER_ATTRS)
  attr_accessor(*ADDRESS_ATTRS.map { |attr| 'billing_' + attr })
  attr_accessor(*ADDRESS_ATTRS.map { |attr| 'shipping_' + attr })
  attr_accessor :confirm_email, :captcha_response, :shipping_is_billing

  validates :first_name, presence: true

  validates :billing_address1, presence: true

  validates :shipping_address1, presence: true, unless: :shipping_is_billing

  def save
    return false unless valid?
    persist!
  end

  private

  def captcha_passes
    captcha = Captcha.new
    return if captcha.valid?(captcha_response)
    errors.add(:captcha_response, 'is invalid')
  end

  def persist!
    customer = Customer.new(attrs_for_customer)
    customer.billing_address = CustomerAddress.new(attrs_for_address('billing_'))
    customer.shipping_address = CustomerAddress.new(
  attrs_for_address(shipping_is_billing ? 'billing_' : 'shipping_')
)
    customer.save!
    customer
  end

  def attrs_for_customer
    Hash[
      CUSTOMER_ATTRS.map { |attr| [attr, send(attr)] }
    ]
  end

  def attrs_for_address(prefix)
    Hash[
      ADDRESS_ATTRS.map { |attr| [attr, send(prefix + attr.to_s)] }
    ]
  end
end

JS

app.newCustomer = () => {
  function init() {
    let check = document.querySelector('#customer_form_shipping_is_billing')
    check.addEventListener('change', toggledUseBilling)
  }

  let toggledUseBilling = event => {
    shippingFields().forEach(field => {
      if(event.target.checked) {
        field.value = null;
        field.removeAttribute('required');
        field.setAttribute('disabled', true);
      } else {
        field.setAttribute('required', true);
        field.removeAttribute('disabled');
      }
    })
  }

  let shippingFields = () => {
    let selectors = [
      '#customer_form_shipping_address1',
      '#customer_form_shipping_address2',
      '#customer_form_shipping_city',
      '#customer_form_shipping_state',
      '#customer_form_shipping_zip',
    ]
    return document.querySelectorAll(selectors.join(', '));
  }

  return init();
}

在坚持下!我正在使用复选框上的三元运算符来确定要计费/发货的地址的属性。但这看起来并不实际。我如何从表单中抓取被标记的复选框?

这是我尝试过的事情:

  • 已将= f.check_box:shipping_is_billing切换为= check_box_tag:shipping_is_billing。然后,我必须更新我的JS,以确保我抓住了正确的复选框。这会存储运输数据,但在选中时不会复制业务数据。
  • 试图将attrs_for_address(shipping_is_billing?'billing_':'shipping_')切换为attrs_for_address(shipping_is_billing?'shipping_':'billing_')。如果我使用check_box,则会将数据填充到运输中,但此复选框无效。
  • 在check_box_tag周围放置一个form_tag,但这实际上去除了复选框
  • 将check_box更改为check_box_tag,更新了我的JS以在复选框上查找正确的ID。如果输入,可以保存送货地址,但如果选中此框,则不适用帐单地址,并且提示您送货地址不能为空

1 个答案:

答案 0 :(得分:0)

在persist内进行了绑定。方法。看起来shipping_is_billing正在拉一个串,这真是对了。更改为

customer.shipping_address = CustomerAddress.new(
  attrs_for_address(shipping_is_billing == "1" ? 'billing_' : 'shipping_')