gpt4 book ai didi

ruby-on-rails-3 - 验证多页表单的复杂模型

转载 作者:行者123 更新时间:2023-12-03 14:30:59 25 4
gpt4 key购买 nike

我正在尝试使用设计和事件商家编写注册。表单很复杂,因为我的用户对象如下所示:

class User < ActiveRecord::Base
include ActiveMerchant::Utils

# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable

# Setup accessible (or protected) attributes
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :first_name,
:subscription_attributes, :last_name, :zipcode,
:payment_profile_attributes, :customer_cim_id, :payment_profile_id

...

# Track multi-page registration
attr_writer :current_step

...

# Setup Payment Profile element (authorize.net billing profile)
has_one :payment_profile, :dependent => :delete
accepts_nested_attributes_for :payment_profile

现在 PaymentProfile 类有自己的子类,来自活跃商家的两个项目:
require 'active_merchant'

class PaymentProfile < ActiveRecord::Base
include ActiveMerchant::Billing
include ActiveMerchant::Utils

validate_on_create :validate_card, :validate_address

attr_accessor :credit_card, :address

belongs_to :user

validates_presence_of :address, :credit_card

def validate_address
unless address.valid?
address.errors.each do |error|
errors.add( :base, error )
end
end
end

def address
@address ||= ActiveMerchant::Billing::Address.new(
:name => last_name,
:address1 => address1,
:city => city,
:state => state,
:zip => zipcode,
:country => country,
:phone => phone
)
end

def validate_card
unless credit_card.valid?
credit_card.errors.full_messages.each do |message|
errors.add( :base, message )
end
end
end

def credit_card
@credit_card ||= ActiveMerchant::Billing::CreditCard.new(
:type => card_type,
:number => card_number,
:verification_value => verification_code,
:first_name => first_name,
:last_name => last_name
)
@credit_card.month ||= card_expire_on.month unless card_expire_on.nil?
@credit_card.year ||= card_expire_on.year unless card_expire_on.nil?
return @credit_card
end

现在,我使用 Ryan Bates 多页表单截屏视频 ( http://railscasts.com/episodes/217-multistep-forms) 中的解决方案覆盖了 Devise 的 RegistrationsController 以处理多页表单。我不得不稍微调整一下才能让它与 Devise 一起工作,但我成功了。现在,因为 Ryan 的多页表单只是要求在不同页面上来自同一模型的不同字段,所以他能够覆盖他的 valid?通过向他的验证方法 a la 添加一个 :if 块来实现方法:
validates_presence_of :username, :if => lambda { |o| o.current_step == "account" }

但在我的情况下,我从我的父模型(用户)中请求第一个表单上的所有字段,然后从我的两个孙子模型(用户:PaymentProfile:地址,用户:PaymentProfile:Credit_Card)中请求所有字段) 在第二页。

我面临的问题是,虽然 PaymentProfile.valid?返回基于 ActiveMerchant 逻辑的错误,表单本身不会呈现甚至显示这些错误。计费页面的查看代码如下所示:
<h2>Payment Details</h2>

<%= semantic_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>

<%= f.semantic_fields_for :payment_profile do |p| %>
<%= p.semantic_fields_for :address do |a| %>
<%= a.inputs "Billing Information", :id => "billing" do %>
<%= a.input :type, :label => "Credit Card", :as => :select, :collection => get_creditcards %>
<%= a.input :number, :label => "Card Number", :as => :numeric %>
<%= a.input :card_expire_on, :as => :date, :discard_day => true, :start_year => Date.today.year, :end_year => (Date.today.year+10), :add_month_numbers => true %>
<%= a.input :first_name %>
<%= a.input :last_name %>
<%= a.input :verification_code, :label => "CVV Code" %>
<% end %>
<% end %>

<%= f.semantic_fields_for :credit_card do |c| %>
<%= c.inputs "Billing Address", :id => "address" do %>
<%= c.input :address1, :label => "Address" %>
<%= c.input :city %>
<%= c.input :state, :as => :select, :collection => Carmen::states %>
<%= c.input :country, :as => :select, :collection => Carmen::countries, :selected => 'US' %>
<%= c.input :zipcode, :label => "Postal Code" %>
<%= c.input :phone, :as => :phone %>
<% end %>
<% end %>
<% end %>

<%= f.commit_button :label => "Continue" %>
<% unless @user.first_step? %>
<%= f.commit_button :label => "Back", :button_html => { :name => "back_button" } %>
<% end %>
<% end %>

我加了一个 puts errors有效后立即在我的代码中显示消息?命令,它显示如下:
{:base=>[["first_name", ["cannot be empty"]], ["last_name", ["cannot be empty"]], ["year", ["expired", "is not a valid year"]], ["type", ["is required", "is invalid"]], ["number", ["is not a valid credit card number"]], ["verification_value", ["is required"]], ["address1", ["is required"]], ["city", ["is required"]], ["state", ["is required"]], ["zip", ["is required", "must be a five digit number"]], ["phone", ["is required", "must be in the format of 333-333-3333"]]]}
{:base=>[["first_name", ["cannot be empty"]], ["last_name", ["cannot be empty"]], ["year", ["expired", "is not a valid year"]], ["type", ["is required", "is invalid"]], ["number", ["is not a valid credit card number"]], ["verification_value", ["is required"]], ["address1", ["is required"]], ["city", ["is required"]], ["state", ["is required"]], ["zip", ["is required", "must be a five digit number"]], ["phone", ["is required", "must be in the format of 333-333-3333"]]]}

现在此输出的结构与标准错误输出的输出不匹配,该输出是基于单层哈希构建的,例如:
{:username=>["can't be blank"]}

因此,在向您展示所有这些之后,我的问题是:
a) 如何让错误输出正确显示,以便表单实际将它们吐出?
b) 如何防止 parent.valid?从也验证grandchildren.valid?当我不在那个页面上时?我不能在子模型上使用 :if => lambda... 解决方案,因为他们不知道 current_step 是什么。

对于这么长的帖子,我深表歉意,我只是想包含尽可能多的信息。我已经为此纠结了一个星期,但我似乎无法克服它。任何建议都会非常有帮助。提前致谢。

最佳答案

错误未显示的原因可能是它们填充在基础上,而不是单个属性上。这发生在您的 validate_cardvalidate_address方法。您应该将错误添加到导致错误的特定属性中,而不是将错误添加到 base 中。

errors.add( attr , error )

其次,如果您想让验证依赖于某个状态,如您提到的截屏视频,那么您需要将状态标志与模型一起保存(可能最好是父模型)。您可以手动执行此操作,或者更好的是,您可以为此使用 gem(推荐): state_machine

祝你好运。

关于ruby-on-rails-3 - 验证多页表单的复杂模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5454856/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com