Rails 4:向非ActiveRecord类添加验证

时间:2014-06-04 16:26:57

标签: ruby-on-rails

我正在尝试创建一个表单对象,以便它与form_for一起使用。

这是我试图复制验证功能的对象:

class CheckoutForm
  include Virtus.model
  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  def persisted?
    false
  end

  attribute :purchase_id, Integer
  attribute :shipping_address_first_name, String
  attribute :shipping_address_last_name, String
  attribute :shipping_address_street_address, String
  attribute :shipping_address_street_address2, String
  attribute :shipping_address_zip_code, String
  attribute :shipping_address_city, String
  attribute :shipping_address_state_id, Integer
  attribute :shipping_address_phone_number, String


  attribute :billing_address_first_name, String
  attribute :billing_address_last_name, String
  attribute :billing_address_street_address, String
  attribute :billing_address_street_address2, String
  attribute :billing_address_zip_code, String
  attribute :billing_address_city, String
  attribute :billing_address_state_id, Integer
  attribute :billing_address_phone_number, String

  validates_presence_of :shipping_address_first_name, message: "blahhh"
  validates_presence_of :shipping_address_last_name
  validates_presence_of :shipping_address_street_address
  validates_presence_of :shipping_address_zip_code
  validates_presence_of :shipping_address_city
  validates_presence_of :shipping_address_state_id

  validates_presence_of :billing_address_first_name
  validates_presence_of :billing_address_last_name
  validates_presence_of :billing_address_street_address
  validates_presence_of :billing_address_zip_code
  validates_presence_of :billing_address_city
  validates_presence_of :billing_address_state_id

  validate do
    [shipping_address, billing_address].each do |object|
      unless object.valid?
        object.errors.each do |key, values|
          errors[key] = values
        end
      end
    end
  end


  def purchase
    @purchase ||= Purchase.find(purchase_id)
  end

  def shipping_address
    @shipping_address ||= purchase.build_shipping_address(
      first_name: shipping_address_first_name,
      last_name: shipping_address_last_name,
      street_address: shipping_address_street_address,
      street_address2: shipping_address_street_address2,
      city: shipping_address_city,
      zip_code: shipping_address_zip_code,
      state_id: shipping_address_state_id,
      phone_number: shipping_address_phone_number
    )
  end

  def billing_address
    @billing_address ||= purchase.build_billing_address(
      first_name: billing_address_first_name,
      last_name: billing_address_last_name,
      street_address: billing_address_street_address,
      street_address2: billing_address_street_address2,
      city: billing_address_city,
      zip_code: billing_address_zip_code,
      state_id: billing_address_state_id,
      phone_number: billing_address_phone_number
    )
  end


  def save
    return false unless valid?
    create_objects
  end

  private

    def create_objects
      ActiveRecord::Base.transaction do
        shipping_address.save!
        billing_address.save!
      end
    rescue
      false
    end

end

一切都按照我想要的方式运作。这是我的表格:

    <%= form_for @checkout, url: update_billing_checkout_path, method: :put do |f| %>
        <ul>
        <% @checkout.errors.each do |error| %>
            <%#= error.full_messages.each do |message| %>
                <li><%= error %></li>
            <%# end %>
        <% end %>
        </ul>
   ...

但是,当我检查错误时,它们都只是Symbol s,就像这样:

<li>shipping_address_zip_code</li>
<li>shipping_address_city</li>
<li>billing_address_first_name</li>

当您从full_messages继承时,ActiveRecord通常不会提供ActiveRecord::Base类。我还尝试添加一个选项validates_presence_of :first_name, message: "asdfasf"但是没有做任何事情。

我错过了什么?

1 个答案:

答案 0 :(得分:4)

你应该做

    <% @checkout.errors.full_messages.each do |error| %>
        <li><%= error %></li>
    <% end %>

查看文档here