使用嵌套表单创建用户时Rails回滚

时间:2015-08-07 18:01:24

标签: ruby-on-rails forms rails-activerecord

我在尝试将用户添加到我的数据库时收到回滚,但我不确定原因。

我有三种型号: 的 company.rb

class Company < ActiveRecord::Base
 acts_as_paranoid

 has_many :locations, dependent: :destroy
 has_many :users, dependent: :destroy
 has_many :tests, through: :locations
 has_many :reports, dependent: :destroy

 accepts_nested_attributes_for :locations, :users

 validates_presence_of :name
end

** user.rb **

class User < ActiveRecord::Base
 acts_as_paranoid

 devise :database_authenticatable,
      :recoverable,
      :rememberable,
      :trackable,
      :validatable,
      :registerable

 belongs_to :company
 has_and_belongs_to_many :roles
end

** location.rb **

class Location < ActiveRecord::Base
 acts_as_paranoid

 belongs_to :company
 has_many :network_hosts, dependent: :destroy
 has_many :tests, dependent: :destroy
 has_many :commands, dependent: :destroy

 validates_presence_of :company, :identifier, :name
 validates_uniqueness_of :identifier

 delegate :security_percentage, to: :last_test, allow_nil: true

 after_initialize :generate_identifier, if: -> { self.identifier.blank? }

 def generate_identifier
  self.identifier = SecureRandom.uuid.delete("-")
end

因此,当用户想要注册时,他们需要输入公司,位置和用户信息,这些信息由我的company_controller.rb

控制

** company_controller.rb **

class CompanyController < ApplicationController
 def new
  @company = Company.new
  1.times { @company.locations.build }
  1.times { @company.users.build }
 end

 def create
  @company = Company.new(company_params)
  if @company.save
   redirect_to root_url
  else
   render :new
  end
 end

 private

  def company_params
   params.require(:company).permit(:name, locations_attributes: [:name], users_attributes: [:first_name, :last_name, :full_name, :email, :password, :password_confirmation])
  end
end

表单使用带有嵌套属性的标准form_for,以便我可以在用户单击提交按钮时一次性完成所有内容

** company / new.html.erb **

<%= form_for @company, :url => url_for( :controller => 'company', :action => 'new' ) do |f| %>
  <div class="form-group">
    <%= f.label "Company Name" %>
    <%= f.text_field :name, class: "form-control", placeholder: "ACME Inc."  %>

    <%= f.fields_for :locations do | location_builder | %>
      <%= location_builder.label "Location Name" %>
      <%= location_builder.text_field :name, class: "form-control", placeholder: "Main Building" %>

    <% end %>
  </div>

  <div class="form-group">
    <%= f.fields_for :users do | user_builder | %>
      <%= user_builder.label "First Name" %>
      <%= user_builder.text_field :first_name, class: "form-control", placeholder: "John" %>

      <%= user_builder.label "Last Name" %>
      <%= user_builder.text_field :last_name, class: "form-control", placeholder: "Smith" %>

      <%= user_builder.label "Full Name" %>
      <%= user_builder.text_field :full_name, class: "form-control", placeholder: "John Smith" %>

      <%= user_builder.label "Email" %>
      <%= user_builder.email_field :email, class: "form-control", placeholder: "john@acme.com" %>

      <%= user_builder.label "Password" %>
      <%= user_builder.password_field :password, class: "form-control" %>

      <%= user_builder.label "Confirm Password" %>
      <%= user_builder.password_field :password_confirmation, class: "form-control" %>
    <% end %>
  </div>

  <%= f.submit "Submit", class: "btn btn-large btn-success" %>
<% end %>

但是,我正在日志中回滚,但这并没有发生,也无法找出原因。

Started POST "/signup" for 127.0.0.1 at 2015-08-07 13:49:22 -0400
Processing by CompanyController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"2OHwJ9UfEbfkZHjLdm9BfOd7jlRdvoEz0L4NRJCKl64=", "company"=>{"name"=>"ACME Brick", "locations_attributes"=>{"0"=>{"name"=>"Main House"}}, "users_attributes"=>{"0"=>{"first_name"=>"Testin", "last_name"=>"User", "full_name"=>"Test User", "email"=>"test@test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}}, "commit"=>"Submit"}
  User Load (0.8ms)  SELECT  "users".* FROM "users"  WHERE "users"."deleted_at" IS NULL AND "users"."id" = 7  ORDER BY "users"."id" ASC LIMIT 1
  Role Load (0.3ms)  SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles"."deleted_at" IS NULL AND "roles_users"."user_id" = $1  [["user_id", 7]]
   (0.1ms)  BEGIN
  Location Exists (0.3ms)  SELECT  1 AS one FROM "locations"  WHERE "locations"."identifier" = '3b7febb35ea740488788d43fcc5e989c' LIMIT 1
  User Exists (0.3ms)  SELECT  1 AS one FROM "users"  WHERE "users"."email" = 'test@test.com' LIMIT 1
   (0.1ms)  ROLLBACK
  Rendered company/new.html.erb within layouts/application (5.0ms)
Completed 200 OK in 108ms (Views: 32.2ms | ActiveRecord: 1.9ms | Solr: 0.0ms)

**公司表**

class CreateCompanies < ActiveRecord::Migration
  def change
    create_table :companies do |t|
      t.string :name

      t.timestamps
    end
  end
end

**位置表**

class CreateLocations < ActiveRecord::Migration
  def change
    create_table :locations do |t|
      t.belongs_to :company, index: true
      t.string :identifier
      t.string :name

      t.timestamps
    end
  end
end

**用户表**

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table(:users) do |t|

      t.belongs_to :company, index: true
      
      t.string :username
      t.string :first_name
      t.string :last_name
      t.string :full_name

      t.string :time_zone, :default => "Central Time (US & Canada)"

      t.string :avatar_file_name
      t.string :avatar_content_type
      t.integer :avatar_file_size
      t.datetime :avatar_updated_at

      ## Database authenticatable
      t.string :email,              :null => false, :default => ""
      t.string :phone_number
      t.string :encrypted_password, :null => false, :default => ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, :default => 0
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Token authenticatable
      t.string :authentication_token

      t.timestamps
    end

    add_index :users, :email,                :unique => true
    add_index :users, :reset_password_token, :unique => true

    create_table :roles_users, :id => false do |t|
      t.references :role, :user
    end
  end

  def self.down
    drop_table :users
    drop_table :roles_users
  end
end

**日志中的错误**

Started POST "/signup" for 127.0.0.1 at 2015-08-07 18:12:54 -0400
Processing by CompanyController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"aAc83zKKlV4w1i2GhTqTo3ehtXP+tPvYbBBRq1ccYzA=", "company"=>{"name"=>"Test Co.", "locations_attributes"=>{"0"=>{"name"=>"Main"}}, "users_attributes"=>{"0"=>{"first_name"=>"John", "last_name"=>"Smith", "full_name"=>"John Smith", "email"=>"john@acme.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}}, "commit"=>"Submit"}
  User Load (0.5ms)  SELECT  "users".* FROM "users"  WHERE "users"."deleted_at" IS NULL AND "users"."id" = 7  ORDER BY "users"."id" ASC LIMIT 1
  Role Load (0.3ms)  SELECT "roles".* FROM "roles" INNER JOIN "roles_users" ON "roles"."id" = "roles_users"."role_id" WHERE "roles"."deleted_at" IS NULL AND "roles_users"."user_id" = $1  [["user_id", 7]]
   (0.1ms)  BEGIN
  Location Exists (0.3ms)  SELECT  1 AS one FROM "locations"  WHERE "locations"."identifier" = '0d759e5405084663a1c110d37f04573a' LIMIT 1
  User Exists (0.2ms)  SELECT  1 AS one FROM "users"  WHERE "users"."email" = 'john@acme.com' LIMIT 1
   (0.1ms)  ROLLBACK
Completed 422 Unprocessable Entity in 75ms
** [Airbrake] Notice was not sent due to configuration:         
  Environment Monitored? false         
  API key set? true

ActiveRecord::RecordInvalid (Validation failed: Locations company can't be blank):
  app/controllers/company_controller.rb:10:in `create'
  app/controllers/application_controller.rb:95:in `set_time_zone'


  Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.9ms)
  Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.7ms)
  Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.2ms)
  Rendered /Users/godzilla/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (15.6ms)

它引用了位置标识符已经存在,但它没有。这是在尝试创建新Location时动态制作的(请注意generate_identifier模型中的方法location.rb)。最重要的是,用户也不存在。

如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

当您编写validates_presence_of :company时,这意味着您的公司记录必须在创建位置时存在,但尚未完全保存。但是,您的位置仍与公司对象关联,并且无需此验证即可正确保存。我认为您可以在存在company_id时进行验证,因为公司ID在保存期间可用。