2015-01-18 12 views
0

Я пытаюсь дать пользователям возможность добавлять сразу несколько платежей с помощью настраиваемого URL-адреса, но при возникновении проблем с проверкой возникает проблема с существующими записями.Как мне получить Rails, чтобы показывать или разрешать новые записи при использовании полей при неудачной проверке?

URL "/ setup/payments" предварительно заполняет форму двумя примерными платежами, чтобы дать им представление о типах платежей, которые они могут добавить.

Если есть проблема с проверкой, то они забывают добавить значение одного из полей, форма добавляет существующие элементы в @ company.payments, которые выглядят, как это в оказанной HTML:

<input id="company_payments_attributes_0_id" name="company[payments_attributes][0][id]" type="hidden" value="104"> 

Если пользователь попытается отправить форму еще раз, он столкнется с проблемами проверки на любом из них, потому что ни имя, ни значение не присутствуют для них в форме.

Как я могу убедиться, что существующие элементы в @ company.payments не добавлены в эту форму, если есть проблемы с проверкой, и мне нужно снова отобразить форму?

Вот пример всего кода я использую:

конфигурации/routes.rb

get '/setup/payments', :to => 'companies#setup_payments', :as => :setup_payments 
post '/setup/payments', :to => 'companies#save_payments', :as => :save_payments 

приложение/модели/company.rb

class Company < ActiveRecord::Base 

    belongs_to :user 
    has_many :payments 
    accepts_nested_attributes_for :payments 

end 

приложение/модели/payment.rb

class Payment < ActiveRecord::Base 

    belongs_to :company 
    validates :name, :presence => { :message => "Name is required" } 
    validates :value, :presence => { :message => "Value is required" } 

end 

приложение/контроллеры/companies_controller.rb

class CompaniesController < ApplicationController 

    def setup_payments 

     @company = curent_user.company 

     @payments = [ 
     { 
      :name => 'Coffee', 
      :value => 5 
     }, 
     { 
      :name => 'Breakfast', 
      :value => 10 
     } 
     ] 

     @company.payments.build(@payments) 

    end 

    def save_payments 

     @company = curent_user.company 

     if @company.update(company_params) 

      redirect_to root_path and return 

     else 

      render :setup_payments 

     end 

    end 

    private 

    def company_params 
     params.require(:company).permit(:name, payments_attributes: [:name, :value, :_destroy]) 
    end 

end 

приложение/просмотров/компании/setup_payments.html.erb

<% if @company.errors.any? %> 

    <h2>We found <%= pluralize(@company.errors.count, "error") %>:</h2> 

    <ol> 
     <% @company.errors.each do |attr, msg| %> 
     <li><%= msg %></li> 
     <% end %> 
    </ol> 

<% end %> 

<%= nested_form_for @company, :url => save_payments_path, :method => 'post' do |f| %> 

    <% if params[:company].nil? %> 

     <%= f.fields_for :payments, @company.payments.build(@payments) do |payment| %> 

     <%= render :partial => 'payments', :locals => { :payment => payment } %> 

     <% end %> 

    <% else %> 

     <%= f.fields_for :payments do |payment| %> 

     <%= render :partial => 'payments', :locals => { :payment => payment } %> 

     <% end %> 

    <% end %> 

    <%= f.link_to_add "Add Another", :payments %> 

    <%= f.button "Save Payments" %> 

<% end %> 

приложение/просмотров/компании/_payments .html.erb

<% if payment.object.new_record? %> 

    <%= payment.text_field :name %> 
    <%= payment.text_field :value %> 

<% end %> 

ответ

1

Если вы хотите игнорировать любые вложенные платежи, где либо имя, либо значение пустое, вы можете использовать параметр recject_if для accepts_nested_attributes_for.

accepts_nested_attributes_for :payments, reject_if: proc { |attributes| attributes['name'].blank? || attributes['value'].blank? } 

Так, при сохранении существующего платежа, который не имеет ни «имя» или «значение» атрибутов будет просто игнорировать их.

Другим вариантом было бы, чтобы не отображать существующие платежные документы в приложение/просмотров/компаний/setup_payments.html.erb

приложение/контроллеры/companies_controller.rb

def setup_payments 

    @company = curent_user.company 

    @example_attributes = [ 
    { 
     :name => 'Coffee', 
     :value => 5 
    }, 
    { 
     :name => 'Breakfast', 
     :value => 10 
    } 
    ] 

    @payments = @company.payments.build(@example_attributes) 

end 

приложение/просмотров/компании/setup_payments.html.Еврорадио

<% if params[:company].nil? %> 

    <%= f.fields_for :payments, @company.payments.build(@example_attributes) do |payment| %> 

    <%= render :partial => 'payments', :locals => { :payment => payment } %> 

    <% end %> 

<% else %> 

    <%= f.fields_for :payments, @payments do |payment| %> 

    <%= render :partial => 'payments', :locals => { :payment => payment } %> 

    <% end %> 
0

Благодаря Саймон, я закончил фиксируя вопрос со следующим изменением кода:

accepts_nested_attributes_for :payments, :reject_if => :all_blank 

только таким образом новые элементы не пройти проверку. Если я попытался отклонить элементы, если либо имя, либо значение, где пусто, тогда я мог бы столкнуться с ситуацией, когда «новый элемент» в форме не проходит проверку, потому что у нее один из этих пустых. Я хотел, чтобы только новые элементы проходили проверку, а не существующие.

P.S. если это еще не ясно, я совершенно новичок в Rails, поэтому, если у кого-то есть мысли о том, как я мог бы сделать выше в более «Railsy», пожалуйста, дайте мне знать :)