2013-09-26 3 views
35

Я установил приложение примера RailsTutorial (приложение, подобное твитеру), и я пытаюсь понять, почему следующий фрагмент кода консоли не обновляет базу данных при попытке обновить пользовательский db. Я ожидаю, что информация пользователя будет обновляться после использования user.save. Однако это возвращается к неотредактированным данным. Это связано с ограничением пользователя? КонтроллерПочему мои рельсы откатываются при попытке пользователя.

Пользователей:

class UsersController < ApplicationController 

#before_filter :signed_in_user, only: [:index, :edit, :update, :destroy, :following, :followers] 
# By default before filters apply to all actions 
#before_filter :correct_user, only: [:edit, :update] 
    def edit 
    @user = User.find(params[:id]) 
    end 

    def update 

    @user = User.find params[:id] 

    respond_to do |format| 

    if @user.update_attributes(params[:user]) 
     flash[:notice] = "Profile updated" 
     format.html { redirect_to(@user, :notice => 'User was successfully updated.') } 
     format.json { respond_with_bip(@user) } 
    else 

     format.html { render :action => "edit" } 
     format.json { respond_with_bip(@user) } 
    end 
    end 
end 

    private 


    def correct_user 
    @user = User.find(params[:id]) 
    redirect_to(root_path) unless current_user?(@user) 
    end 

    def admin_user 
    redirect_to(root_path) unless current_user.admin? 
    end 


end 

Rails консоль:

1.9.3-p392 :001 > user = User.find(109) 


User Load (8.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 109]] 
=> #<User id: 109, name: "laurie", email: "[email protected]", created_at: "2013-09-26 18:10:12", updated_at: "2013-09-26 18:10:12", password_digest: "$2a$10$aXEtun8Z2Deqy2wNxvFRNOjPczKQkYc1vDezP5OduJuF...", remember_token: "YhIUhgFm9iMewxdNOHJ45A", admin: false> 

1.9.3-p392 :002 > user.name = "larry" 
=> "larry" 

1.9.3-p392 :003 > user.save 
    (0.2ms) begin transaction 
    User Exists (0.6ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('[email protected]') AND "users"."id" != 109) LIMIT 1 
    (0.1ms) rollback transaction 
=> false 

модель Пользователя:

class User < ActiveRecord::Base 

# Declaration of public variables 
    attr_accessible :email, :name, :password, :password_confirmation 
    has_secure_password 
    has_many :microposts, dependent: :destroy 
    has_many :relationships, foreign_key: "follower_id", dependent: :destroy 
    has_many :followed_users, through: :relationships, source: :followed 
    has_many :reverse_relationships, foreign_key: "followed_id", class_name: "Relationship", dependent: :destroy 
    has_many :followers, through: :reverse_relationships, source: :follower 

    before_save {email.downcase!} 
    before_save :create_remember_token 

    validates :name, presence: true, length: {maximum: 50} 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 
    validates :email, presence: true, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false} 
    validates :password, presence: true, length: {minimum: 6} 
    validates :password_confirmation, presence: true 
    after_validation {self.errors.messages.delete(:password_digest)} 

private 
    def create_remember_token 
     self.remember_token = SecureRandom.urlsafe_base64 
    end 
end 
+2

Метод '.save' в консоли не использует код контроллера, поэтому публикация его не имеет значения. Взгляните на свою модель и попытайтесь выяснить, почему этот странный оператор SELECT 1 AS one FROM ... SQL выдается, и рассмотрите возможность размещения кода для вашей модели вместо контроллера. Кроме того, вы случайно определили свой собственный метод 'save' в своей модели или у вас есть какие-либо пользовательские обратные вызовы на этой модели? Может быть, ответ там где-то. – jefflunt

+0

Это может быть потому, что у пользователя есть индекс уникальности по электронной почте, и есть более одного пользователя с адресом электронной почты 'auriepage @ gmail.com'. Это объясняет запрос, пытающийся найти пользователя, чей адрес электронной почты, но идентификатор которого не является 109 –

+0

У вас возникли проблемы с вашим классом 'User', определенно укажите ваш исходный код класса' User'. –

ответ

101

Возможно, у вашей модели пользователя есть проверки, которые не удовлетворяются. Поскольку вы не разместили эти сообщения, я не могу решить ваш вопрос. Чтобы сделать жизнь проще, вы можете отлаживать, почему ваш пользователь не хочет сэкономить.

Попробуйте запустить

user.errors.full_messages 

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

+0

Я получаю следующие сообщения об ошибке: 1.9.3-p392: 005> user.errors. full_messages => [«Пароль не может быть пустым», «Пароль слишком короткий (минимум 6 символов)», «Подтверждение пароля не может быть пустым»] Это ошибки проверки, однако, когда я уже подписанный как пользователь, я не хочу менять пароль каждый раз, когда хочу изменить имя. Я хочу, чтобы редактирование работало независимо от проверки пароля (но должно быть подтверждено, что текущий пользователь является тем, который редактируется) – Venomoustoad

+0

@Venomoustoad Валидации могут иметь условия, например: (код) проверяет: пароль, наличие: истина, длина: {minimum: 6}, если:: password_changed? (/ code) password_changed должен быть методом в вашей модели пользователя. Вы можете включить эти условия, если хотите подтвердить пароль здесь. – jewilmeer

+1

Отображение ошибки в консоли помогло с моей проблемой; должен был установить user.password, прежде чем он позволит мне сохранить. –

2

Ваша валидация не проходит. Вы можете сделать:

user.errors.full_messages 

в консоли после неудачного сохранения, чтобы узнать почему.

6

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

user = User.find(108) 
user.name = "Larry" 
user.valid? # returns false 
user.errors.messages # returns something like {email: "Cant be blank"} 

Очевидно, что я сделал эту ошибку, потому что я не знаю, что ваш файл модель выглядит, но если это роли возвращено по одной из двух причин, как правило. Во-первых, ваши проверки не удались. Если они не являются сообщениями об ошибках, вероятно, потому что что-то в вашей цепочке фильтров возвращает false. Например

class User << ActiveRecord::Base 
    before_save :accidentally_return_false 

    def accidentally_return_false 
    self.some_boolean = (condition == value) 
    end 
end 

user = User.new(params) 
user.save # where condition does not equal value 
user.valid? # false because of the before save method 

Надежда, что помогает

4

Когда СОХРАНИТЬ откатов, используйте сохранить! вместо этого, и журнал ошибок будет напечатан.

2

У меня была эта же проблема и никаких ошибок не было. Оказалось, что моя функция before_save возвращала false, в результате чего сохранение было отменено (я предполагаю, что я новичок в рельсах).

Я пытался установить значение булева, которое можно было установить только после того, как файл был загружен.

Вот что я делаю:

before_save :set_orientation 

def set_orientation 
    # ...do stuff... 
    self[:is_landscape] = ratio > 1 # stores AND returns the boolean value!! 
end 

Последняя строка в функции также неявное возвращение которого я не хотел этого делать. Мое решение было сделать возвращение в явном виде:

before_save :set_orientation 

def set_orientation 
    # ...do stuff... 
    self[:is_landscape] = ratio > 1 # store the boolean value 
    return       # now return 
end 
+0

, если вы копаете эту глупую вещь самостоятельно. то вы гениальный друг: P – ImranNaqvi

0

Я имел такой же вопрос базы данных отбрасывания мои транзакции в консоли, когда я пытаюсь обновить свойство администратора на пользователя.Если вы занимаетесь учебным пособием по Hartl rails, проблема в том, что если вы наберете user.errors.messages в консоли, он скажет вам, что пароль слишком короткий. Это потому, что в модели есть проверка пароля, прежде чем она сохранит и хеширует ваш пароль в password_digest.

Работайте с этим в консоли, выполните свою обычную деятельность, например, установив user.admin = true, а затем, когда вы закончите, введите user.password = "foobar", затем введите user.password_confirmation = "foobar" , а затем, когда вы выполните user.save, он зафиксирует все ваши изменения.

13

Я знаю, что это старый пост, но, надеюсь, это может помочь кому-то пройти этот урок в будущем.

Как говорится в принятом ответе, это связано с проверками, которые не выполняются. Я столкнулся с этой проблемой и обнаружил, что другим способом является использование метода update_attribute на объекте user. Например, если вы хотите обновить name поле user объекта и он автоматически сохраняет в базе данных, без необходимости прикасаться к виртуальным password и password_confirmation полей, используйте следующую команду:

user.update_attribute(:name, "larry") 

Это будет обновлять name только поле и сохранить его в базе данных (не нужно вызывать метод save), не прикасаясь к полям и password_confirmation.

+2

Несмотря на то, что проверка модели не удалась, 'user.update_attribute' будет обновлять базу данных независимо от ее действительности, поскольку этот метод пропускает проверку. Также используется 'save (validate: false)', если мы хотим пропустить проверку и знать, что делаем –

+0

Этот ответ является золотым. Спасибо @ Richard Gieg – nuxxxx

Смежные вопросы