2014-12-28 4 views
0

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

User.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)"]}> 
+0

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

ответ

2

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

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

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

Если вы хотите, чтобы сохранение пользователя в данный момент, можно сказать, рельсы, чтобы пропустить валидаций

user.save(validate: false) 

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

+0

Спасибо, небольшой отредактируйте ваш код. Должен быть сам не пользователь self.changes.include? :Эл. адрес. Я планирую использовать разработку в конечном итоге, но их собственный документ рекомендует сделать свой первый. –

+0

Зависит от того, где вы это называете, я говорил о консоли rails, если вы запустили ее внутри пользовательского класса, просто вызовите save напрямую, хотя я не рекомендую иметь сохранение, которое обходит проверки внутри вашей модели. –

0

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

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

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

От rails docs

: на - Определяет контексты, где эта проверка является активным. Выполняется во всех контекстах проверки по умолчанию (nil). Вы можете передать символ или массив символов.

+0

Я добавил: on =>: создать для подтверждения пароля. Так что мне нужно и на пароле? Также мой устаревший синтаксис? Я все еще получаю откат, добавив:: create to password validadtion –