Я пытаюсь написать регистрацию, используя devise и активного продавца.Форма сложна тем, что мой пользовательский объект выглядит так:
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
Теперь я имеюпереопределил RegistrationsController от Devise для обработки многостраничной формы с помощью решения из скринкаста многостраничной формы Райана Бейтса (http://railscasts.com/episodes/217-multistep-forms).) Мне пришлось немного настроить его, чтобы он работал с Devise, но я добился успеха.поскольку многостраничная форма Райана просто запрашивала разные поля из одной и той же модели на разных страницах, он смог переопределить свой метод valid?
, добавив блок: if в свой метод проверки a la:
validates_presence_of :username, :if => lambda { |o| o.current_step == "account" }
Но в моем случае я запрашиваю все поля в первой форме из моей родительской модели (Пользователь), а затем запрашиваю все поля из двух моих моделей внуков (Пользователь: PaymentProfile: Адрес, Пользователь: PaymentProfile:Credit_Card) на второй странице.
Проблема, с которой я сталкиваюсь, заключается в том, что хотя PaymentProfile.valid? Возвращает ошибки на основе ActiveMerchaНет логики, сама форма не отображает и даже не отображает эти ошибки.Код представления страницы оплаты выглядит следующим образом:
<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"]}
Итак, после показа вам всего этого, у меня возникли следующие вопросы: а) как мне правильно отобразить вывод ошибок, чтобы форма фактически выплевывала их?б) как мне предотвратить parent.valid?от проверки внуков?когда я не на этой странице?Я не могу использовать решение: if => lambda ... на дочерних моделях, потому что они не знают, что такое current_step.
Мои извинения за такой длинный пост, я просто хотел включить как можно большеинформация как можно.Я борюсь с этим уже неделю, и я не могу пройти мимо.Любой совет будет чрезвычайно полезным.Заранее спасибо.