откат консоли rails при сохранении

Я новичок в рельсах. Я работаю с rails 4.2, и я сломал что-то в моей модели или контроллере user.rb, поэтому я не могу использовать сохранение или обновление в консоли или в веб-браузере (для некоторых переменных в пользователе я могу изменить имя, адрес электронной почты и пароль в браузере). Я нашел аналогичную проблему здесь но я не мог получить там совет по работе.

Вот мой код User db table

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)"]}>

person NAthan Davis    schedule 28.12.2014    source источник
comment
Я знаю, что мой синтаксис для вышеизложенного не идеален, поэтому, пожалуйста, простите меня. Я не понимаю, как делать большие блоки кода   -  person NAthan Davis    schedule 28.12.2014


Ответы (2)


Дело в том, что запись не содержит поля с именем пароль, она имеет password_hash и password_salt, каждый раз, когда вы пытаетесь сохранить рельсы, ищет поле пароля, но не может его найти, я бы сказал, создайте условие, которое сообщает рельсам когда искать пароль, например

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

Это предотвратит запрос пароля каждый раз, когда пользователь меняет что-то незначительное в своей учетной записи, и будет запрашивать пароль, если пользователь изменит свой адрес электронной почты, вы, конечно, можете добавить больше параметров.

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

user.save(validate: false)

И последнее замечание: лучше и безопаснее использовать хорошо разработанный и зрелый гем аутентификации, такой как devise. имеет все функции, которые вам понадобятся в любой аутентификации.

person Mohammad AbuShady    schedule 28.12.2014
comment
Спасибо, небольшое редактирование вашего кода. Должен ли быть сам, а не пользователь self.changes.include? :Эл. адрес. В конечном итоге я планирую использовать devise, но их собственный документ рекомендует сначала сделать свой собственный. - person NAthan Davis; 28.12.2014
comment
Зависит от того, где вы это называете, я говорил о консоли rails, если вы запускаете ее внутри пользовательского класса, просто вызовите сохранение напрямую, хотя я не рекомендую сохранять сохранение, которое обходит проверки внутри вашей модели. - person Mohammad AbuShady; 28.12.2014

Ваши проверки не работают. У вас есть проверка для password, но в базе данных нет поля пароля (вместо этого из соображений безопасности вы сохраняете хэш и соль).

Чтобы исправить это, добавьте параметр :on, чтобы проверка выполнялась только при создании пользователей.

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

Из документов по рельсам

:on — указывает контексты, в которых эта проверка активна. Запускается во всех контекстах проверки по умолчанию (ноль). Вы можете передать символ или массив символов.

person AJcodez    schedule 28.12.2014
comment
Я добавил :on =› :create для подтверждения пароля. Так мне тоже нужен пароль? Также мой синтаксис устарел? Я все еще получаю откат, добавляя: :create к проверке пароля - person NAthan Davis; 28.12.2014