保存模型时的Rails回滚

时间:2019-01-28 09:15:53

标签: ruby-on-rails ruby ruby-on-rails-5

我正在创建许可证服务器,但我遇到了问题,那就是Rails无法保存模型。

我在after_create模型中设置了User方法,但是没有运气,我也尝试使用Rails控制台创建License模型,但是它回滚事务并且没有显示任何错误。

models / user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :validatable,
     authentication_keys: [:login]

  attr_writer :login
  has_one :license, dependent: :destroy

  validates :username, presence: true, uniqueness: { case_sensitive: false }
  validates_format_of :username, with: /^[a-zA-Z0-9_\.]*$/, multiline: true

  after_create :create_assocs

  def login
    @login || self.username
  end

  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions).where(['lower(username) = :value OR lower(email) = :value', { value: login.downcase }]).first
    else
      if conditions[:username].nil?
        where(conditions).first
      else
        where(username: conditions[:username]).first
      end
    end
  end

  def email_required?
    false
  end

  private

  def create_assocs
    create_license(license_types_id: LicenseType.first.id)
    # license = License.new(user_id: self.id, license_types_id: 1)
    # license.save
    # self.license.create(license_types_id: LicenseType.first.id)
  end
    end

models / license.rb

class License < ApplicationRecord
  belongs_to :license_type
  belongs_to :user

  after_create :set_expired_at

  private

  def set_expired_at
    # self.expired_at = DateTime.now + self.license_types.duration
  end
end

在Rails控制台中,

2.5.1 :001 > license = License.new(license_types_id: LicenseType.first.id)
  LicenseType Load (0.4ms)  SELECT  "license_types".* FROM "license_types" ORDER BY "license_types"."id" ASC LIMIT $1  [["LIMIT", 1]]
 => #<License id: nil, expired_at: nil, created_at: nil, updated_at: nil, license_types_id: 1, user_id: nil> 
2.5.1 :002 > license.save
   (0.5ms)  BEGIN
   (0.2ms)  ROLLBACK
 => false 

schema.rb

  create_table "licenses", force: :cascade do |t|
    t.datetime "expired_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.bigint "license_types_id"
    t.bigint "user_id"
    t.index ["license_types_id"], name: "index_licenses_on_license_types_id"
    t.index ["user_id"], name: "index_licenses_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: ""
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "username"
    t.string "key"
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["username"], name: "index_users_on_username", unique: true
  end

  add_foreign_key "licenses", "users"

创建后如何为新用户设置许可证?

2 个答案:

答案 0 :(得分:1)

许可模型包含两个外键user_idlicense_type_id

=>这意味着在创建License之前必须有一个拥有此License的用户,因为Rails 5约定说user_id必须存在

=>而且必须存在LicenseType,因为Rails 5约定说license_type_id必须存在

回滚原因可以通过以下方法进行调查

license = License.new(license_types_id: LicenseType.first.id)
license.save
#Begin
#ROLLBACK
errors_stack = license.errors

errors_stack包含导致回滚的模型级别错误

要解决这些回滚问题

user = User.first #or current_user
license = user.license.new(license_type_id: LicenseType.first.id)
license.save

user = User.first #or current_user
license = License.new(license_type_id: LicenseType.first.id, user_id: user.id)
license.save

或者要创建User并为用户分配License#after_create的替代方法:create_assocs

new_user = User.new(...)
new_user.license.build(license_type_id: LicenseType.first.id)
new_user.save

答案 1 :(得分:0)

您确定这种“没有错误”吗?在Rails 5中,默认情况下需要belongs_to关联,所以我想这是因为它失败了(在保存尝试之前,您没有设置user关联)。因此,您应该设置license.user或设置:

belongs_to :user, optional: true
如果您的业务逻辑不需要

License模型中。