【问题标题】:rails console rollback on save保存时rails控制台回滚
【发布时间】:2014-12-28 08:33:17
【问题描述】:

我是 Rails 新手。我正在使用 rails 4.2 并且我破坏了我的 user.rb 模型或控制器中的某些内容,因此我无法在控制台或 Web 浏览器中使用保存或更新(对于用户中的某些变量,我可以更改名称、电子邮件和浏览器中的密码)。我发现了一个类似的问题here,但我无法获得工作建议。

这是我的代码 用户数据库表

create_table "users", force: :cascade do |t|
  t.string   "name"
  t.string   "email"
  t.datetime "created_at",                          null: false
  t.datetime "updated_at",                          null: false
  t.string   "avatar_file_name"
  t.string   "avatar_content_type"
  t.integer  "avatar_file_size"
  t.datetime "avatar_updated_at"
  t.string   "password_hash"
  t.string   "password_salt"
  t.boolean  "admin",               default: false
end

用户.rb

class User < ActiveRecord::Base
    has_many :recipes
    has_many :comments

    #attr_accessible :email, :password, :password_confirmation
    attr_accessor :password

    before_save :encrypt_password

    validates_confirmation_of :password, :on => :create
    #validates :name, presence: true, uniqueness: true
    #validates :email, presence: true, uniqueness: true
    validates :password, presence: true, length: { in: 6..20 }


      has_attached_file :avatar, :styles => {
        :medium => "300x300>",
        :thumb => "100x100>"
      },
      :default_url => "/images/:style/missing.png",
      :bucket =>'davisrecipebook',
      :storage => :s3,
      :s3_credentials => "#{Rails.root}/config/s3.yml"
      #:s3_credentials => Proc.new{|a| a.instance.s3_credentials }
      #:storage => :dropbox,
      #:dropbox_credentials => Rails.root.join("config/dropbox.yml")

    #def s3_credentials
    #  {:bucket =>'davisrecipebook', :access_key_id => '', :secret_access_key => ''}
    #end


    validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
    validates_attachment_size :avatar, :less_than => 10.megabytes

    def self.authenticate(email, password)
        user = find_by_email(email)
        if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
            user
        else
            nil
        end
    end

    def encrypt_password
        if password.present?
            self.password_salt = BCrypt::Engine.generate_salt
            self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
        end
    end
end

控制台

2.1.5 :073 > User.last
  User Load (0.5ms)  SELECT  "users".* FROM "users"  ORDER BY "users"."id" DESC LIMIT 1
 => #<User id: 7, name: "hate", email: "death", created_at: "2014-12-28 07:32:22", updated_at: "2014-12-28 08:24:01", avatar_file_name: nil, avatar_content_type: nil, avatar_file_size: nil, avatar_updated_at: nil, password_hash: "$2a$10$9rEtvSoO0DOzm5u/Vop0O.5matAM8gTI0t6QZ470UyF...", password_salt: "$2a$10$9rEtvSoO0DOzm5u/Vop0O.", admin: false> 
2.1.5 :074 > s = _
 => #<User id: 7, name: "hate", email: "death", created_at: "2014-12-28 07:32:22", updated_at: "2014-12-28 08:24:01", avatar_file_name: nil, avatar_content_type: nil, avatar_file_size: nil, avatar_updated_at: nil, password_hash: "$2a$10$9rEtvSoO0DOzm5u/Vop0O.5matAM8gTI0t6QZ470UyF...", password_salt: "$2a$10$9rEtvSoO0DOzm5u/Vop0O.", admin: false> 
2.1.5 :075 > s.admin = true
 => true 
2.1.5 :076 > s.save
   (0.2ms)  BEGIN
  User Exists (0.6ms)  SELECT  1 AS one FROM "users" WHERE ("users"."name" = 'hate' AND "users"."id" != 7) LIMIT 1
  User Exists (0.3ms)  SELECT  1 AS one FROM "users" WHERE ("users"."email" = 'death' AND "users"."id" != 7) LIMIT 1
   (0.2ms)  ROLLBACK
 => false 
2.1.5 :077 > s.errors

@messages={:password=>["can't be blank", "can't be blank", "is too short (minimum is 6 characters)"]}>

【问题讨论】:

  • 我知道我上面的语法并不理想,所以请原谅我。我似乎看不到如何制作大块代码

标签: ruby-on-rails rails-console


【解决方案1】:

问题是,记录不包含名为密码的字段,它有password_hashpassword_salt,每当您尝试保存rails 时都会查找密码字段但找不到它,我会比如说创建一个条件来告诉 rails 何时查找密码,例如

validates :password, if: :password_required?
def password_required?
  user.changes.include? :email # just an example
end

这将防止每次用户更改其帐户中的微小内容时都要求输入密码,并且如果用户更改其电子邮件,它将要求输入密码,当然您可以添加更多选项。

如果你想暂时强制保存用户,你可以告诉 rails 跳过验证

user.save(validate: false)

最后要注意的是,使用像 devise 这样开发良好且成熟的身份验证 gem 会更好、更安全,它具有任何身份验证所需的所有功能。

【讨论】:

  • 感谢您对代码的小修改。应该是自我而不是用户self.changes.include? :电子邮件。我计划最终使用设计,但他们自己的文档建议先自己制作。
  • 取决于你在哪里调用它,我说的是 Rails 控制台,如果你在用户类中运行它,只需直接调用 save,虽然我不建议使用绕过验证的保存模型。
【解决方案2】:

您的验证失败。您对password 进行了验证,但数据库中没有密码字段(出于安全原因,您可以保存哈希和盐)。

要解决此问题,请添加 :on 参数以将验证范围限定为仅在创建用户时运行。

validates :password, on: :create, ...

来自rails docs

:on - 指定此验证处于活动状态的上下文。默认情况下在所有验证上下文中运行 (nil)。您可以传递一个符号或符号数组。

【讨论】:

  • 我添加了 :on => :create 用于密码确认。所以我也需要密码吗?我的语法也被弃用了吗?我仍然得到回滚添加::创建密码验证
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 2017-04-26
  • 2013-07-25
  • 2015-04-23
相关资源
最近更新 更多