2014-09-02 6 views
0

У меня есть связь belongs_to и has_many между двумя моделями. У меня есть форма создания пользователя, которая создает пользователя и в процессе, создает организацию и связывает ее. У меня есть подтверждение наличия имени организации. Если эта проверка не удалась, я хотел бы, чтобы Organiation добавил ошибку Name cannot be blank в тот же хэш сообщений об ошибках, что и у User. В принципе, создается один список сообщений об ошибках.Rails 4 - показывает ошибки для вложенных ассоциаций

Вот мои модели:

class User < ActiveRecord::Base 
    devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :timeoutable 

    belongs_to :organization 

    validates_presence_of :display_name 
end 

class Organization < ActiveRecord::Base 
    has_many :users, dependent: :destroy 

    accepts_nested_attributes_for :users, :allow_destroy => true 

    validates_presence_of :name 
end 

Вот мой создать действие:

def create 
    @user = User.new(sign_up_params) 
    if params[:user][:organization][:access_code].blank? 
    # create new organization 
    @access_code = "#{SecureRandom.urlsafe_base64(16)}#{Time.now.to_i}" 
    @organization = Organization.create(name: params[:user][:organization][:name], access_code: @access_code) 
    @user.organization_id = @organization.id 
    @user.is_admin = true 
    else 
    # try and add someone to an organization 
    @organization = Organization.find(:all, conditions: ["name = ? AND access_code = ?", params[:user][:organization][:name], params[:user][:organization][:access_code]]) 
    if @organization.empty? 
     flash.now[:error] = "No organization has been found with that name and access code." 
     render :new 
     return 
    else 
     @user.organization_id = @organization.first.id 
    end 
    end 
    if @user.save 
    flash[:success] = "Your account has been successfully created! Check your email for a confirmation link to activate your account." 
    redirect_to sign_in_path 
    else 
    flash.now[:error] = "Something went wrong! Please try again." 
    render :new 
    end 
end 

Вот мое мнение:

<% provide(:title, 'Sign Up') %> 

<h1>Create Account</h1> 

<%= nested_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> 
    <%= render "shared/error_messages", obj: @user %> 

    <fieldset> 
    <legend>Account Information</legend> 
    <div class="form-group"> 
     <%= f.label :email %> 
     <%= f.email_field :email, class: "form-control", autofocus: true %> 
    </div> 
    <div class="form-group"> 
     <%= f.label :display_name, "Display Name" %> 
     <%= f.text_field :display_name, class: "form-control" %> 
    </div> 
    <div class="form-group"> 
     <%= f.label :password %> <% if @validatable %><i>(<%= @minimum_password_length %> characters minimum)</i><% end %> 
     <%= f.password_field :password, class: "form-control", autocomplete: "off" %> 
    </div> 
    <div class="form-group"> 
     <%= f.label :password_confirmation %> 
     <%= f.password_field :password_confirmation, class: "form-control", autocomplete: "off" %> 
    </div> 
    </fieldset> 
    <%= f.fields_for :organization do |o| %> 
    <fieldset> 
     <legend>Organization Information</legend> 
     <p> 
     <strong>Creating a New Organization:</strong> Fill out the Organization Name field, but leave the Access Code field blank.<br /> 
     <strong>Joining an Existing Organization:</strong> Fill out both the Organization Name and Access Code field, using the access code that you received from someone at your organization. 
     </p> 
     <div class="form-group"> 
     <%= o.label :name, "Organization Name" %> 
     <%= o.text_field :name, class: "form-control" %> 
     </div> 
     <div class="form-group"> 
     <%= o.label :access_code, "Organization Access Code" %> 
     <%= o.text_field :access_code, class: "form-control" %> 
     </div> 
    </fieldset> 
    <% end %> 
    <div class="form-actions"> 
    <%= f.submit "Create Account", class: "btn btn-primary" %> 
    <%= link_to "Cancel", :back %> 
    </div> 
<% end %> 

<%= render "users/shared/links" %> 

И вот error_messages парциальное:

<% if obj.errors.any? %> 
    <div id="error_explanation"> 
    <h2>There are <%= pluralize(obj.errors.count, "error") %> errors with this form:</h2> 
    <ul> 
    <% obj.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
    <% end %> 
    </ul> 
    </div> 
<% end %> 

Я получаю ошибки для User отображения, как они должны, только не для Organization. Может ли это быть чем-то связанным только с прохождением @user?

+0

Имеет смысл, что вы получаете сообщения об ошибках только для пользователя, если вы только передаете пользователю, верно? В вашем контроллере вместо того, чтобы говорить flash.now [: error] = "...", почему бы вам просто не сказать что-то вроде flash.now [: errors] = @ user.errors.full_messages + @ organization.errors. full_messages? – stefvhuynh

+0

Флэш-сообщения на самом деле не связаны с этой проблемой. Проблема заключается в проверках ActiveModel, которые я устанавливаю через модели, которые, как я полагаю. Я предполагал, что передача '@ user' будет в порядке, и ошибки организации будут поступать через' @ user.organization'. – ryanpitts1

ответ

0

Хорошо, я выясняю свою проблему. Кажется, у меня, возможно, были некоторые вещи назад с ассоциациями модели, или, по крайней мере, с accepts_nested_attributes.

Вот мои обновленные модели:

class User < ActiveRecord::Base 
    devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :timeoutable 

    belongs_to :organization 

    accepts_nested_attributes_for :organization 

    validates_presence_of :display_name 
end 

class Organization < ActiveRecord::Base 
    has_many :users, dependent: :destroy 

    validates_presence_of :name 
end 

Вот мой обновленный создать действие в мой контроллер:

def create 
    @user = User.new(sign_up_params) 
    if params[:user][:organization_attributes][:access_code].blank? 
    # create new organization 
    @access_code = "#{SecureRandom.urlsafe_base64(16)}#{Time.now.to_i}" 
    @organization = Organization.create(name: params[:user][:organization_attributes][:name], access_code: @access_code) 
    @user.organization_id = @organization.id 
    @user.is_admin = true 
    else 
    # try and add someone to an organization 
    @organization = Organization.find(:all, conditions: ["name = ? AND access_code = ?", params[:user][:organization_attributes][:name], params[:user][:organization_attributes][:access_code]]) 
    if @organization.empty? 
     flash.now[:error] = "No organization has been found with that name and access code." 
     render :new 
     return 
    else 
     @user.organization_id = @organization.first.id 
    end 
    end 
    if @user.save 
    flash[:success] = "Your account has been successfully created! Check your email for a confirmation link to activate your account." 
    redirect_to sign_in_path 
    else 
    flash.now[:error] = "Something went wrong! Please try again." 
    render :new 
    end 
end 

Вот мой обновленный вид:

<% provide(:title, 'Sign Up') %> 

<h1>Create Account</h1> 

<%= nested_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> 
    <%= render "shared/error_messages", obj: @user %> 

    <fieldset> 
    <legend>Account Information</legend> 
    <div class="form-group"> 
     <%= f.label :email %> 
     <%= f.email_field :email, class: "form-control", autofocus: true %> 
    </div> 
    <div class="form-group"> 
     <%= f.label :display_name, "Display Name" %> 
     <%= f.text_field :display_name, class: "form-control" %> 
    </div> 
    <div class="form-group"> 
     <%= f.label :password %> <% if @validatable %><i>(<%= @minimum_password_length %> characters minimum)</i><% end %> 
     <%= f.password_field :password, class: "form-control", autocomplete: "off" %> 
    </div> 
    <div class="form-group"> 
     <%= f.label :password_confirmation %> 
     <%= f.password_field :password_confirmation, class: "form-control", autocomplete: "off" %> 
    </div> 
    </fieldset> 
    <% @user.build_organization unless @user.organization %> 
    <%= f.fields_for :organization do |o| %> 
    <fieldset> 
     <legend>Organization Information</legend> 
     <p> 
     <strong>Creating a New Organization:</strong> Fill out the Organization Name field, but leave the Access Code field blank.<br /> 
     <strong>Joining an Existing Organization:</strong> Fill out both the Organization Name and Access Code field, using the access code that you received from someone at your organization. 
     </p> 
     <div class="form-group"> 
     <%= o.label :name, "Organization Name" %> 
     <%= o.text_field :name, class: "form-control" %> 
     </div> 
     <div class="form-group"> 
     <%= o.label :access_code, "Organization Access Code" %> 
     <%= o.text_field :access_code, class: "form-control" %> 
     </div> 
    </fieldset> 
    <% end %> 
    <div class="form-actions"> 
    <%= f.submit "Create Account", class: "btn btn-primary" %> 
    <%= link_to "Cancel", :back %> 
    </div> 
<% end %> 

<%= render "users/shared/links" %> 

Вот мой обновленный error_messages partial (просто показ контекста - измененный код не был действительно связан с проблемой):

<% if obj.errors.any? %> 
    <div id="error_explanation"> 
    <h2><%= pluralize(obj.errors.count, "error") %> was found with this form:</h2> 
    <ul> 
    <% obj.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
    <% end %> 
    </ul> 
    </div> 
<% end %> 

Теперь, когда я пытаюсь сохранить данные без ввода какой-либо информации, отображаются все правильные ошибки. Кроме того, когда я ввожу все необходимые данные пользователя и оставляю все поля организации пустыми, отображаются правильные ошибки проверки, связанные с организацией, и запись пользователя не создается. Работает, как будто мне это нужно сейчас.

Смежные вопросы