0

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

В принципе у меня есть форма проверки вызываемую модели:

validates :user, :presence => true, :uniqueness => true 
validates :email, :presence => true, :uniqueness => true, :on => :create 
validates :passwordHash, :presence => true, :confirmation => true, :on => :create 

Пользователь не в пустых работ по форме обновления Вид:

= simple_form_for @user do |f|  
    = f.input :user 
    = f.input :locale 
    = f.input :localeLanguage, :label => 'Language', :as => :select, :collection => $language_array 
    = f.input :moderator 
    = f.input :email 
    = f.input :passwordHash, :label => 'Password' 

Но не на новых пользователей Вид:

= simple_form_for @user do |f| 
    %table.table-condensed 
     %tr 
     %td 
      =f.input :user, :label => false, :placeholder => 'username' 
     %tr 
     %td 
      = f.input :passwordHash, :label => false, :placeholder => 'password' 
     %tr 
     %td 
      = f.input :email, :label => false, :placeholder => 'email' 
     %tr 
     %td 
      = f.submit "Create User", :class => 'btn btn-primary' 

Единственное различие, которое я вижу между этими видами, состоит в том, что первый имеет сеансы cr когда пользователь уже вошел в систему, второй - нет. Но, насколько я знаю, это не должно иметь значения. Конечно, форма update имеет фактический объект @user, тогда как в new он пуст. Но я видел, как Ryan Bates reilscast о новой проверке пользователя, и он делает почти то же самое.

Выполняется действие users#create после отправки формы с пустыми значениями (что не должно быть возможным). Конечно, я получаю сообщение об ошибке, потому что passwordHash пуст.

Я должен указать, что я не использую никаких дополнительных драгоценных камней, чтобы помочь в подтверждении пароля (в railscast, Bates использует bcrypt, но я не могу использовать его, потому что мы создаем хэш пароля по-другому, и я думаю, что это только для подтверждения пароля). В любом случае это не должно влиять на проверку формы, если это так?

Любые теории или идеи приветствуются здесь, я схожу с ума. Я собираюсь написать дрянной javascript, чтобы сделать это вручную, что было бы ужасно и, вероятно, займет у меня неделю, я не буду делать javascript;)

Спасибо.

Редактировать

запрос Per Рашида, вот являются new и create действия:

def new 
    @user = User.new 
    end 

    def create 
    #failsafe for failing form validation 
    unless params[:passwordHash].present? 
     redirect_to new_user_path, :notice => 'User or password cannot be blank' 
    else 
     password_and_salt = User.hash_password(params[:passwordHash]) 
     hashed_password = password_and_salt[:password] 
     user_salt = password_and_salt[:salt] 
     @user = User.new(:user => params[:user], :passwordHash => hashed_password, :salt => user_salt) 
     if @user.save 
     session[:user_id] = @user.id 
     redirect_to session[:item_to_edit] 
     else 
     redirect_to new_user_path, :notice => "User already exists, please pick another one" 
     end 
    end 
    end 

Edit 2

Я переписанный метод create на основе первого ответа , но все еще возникает ошибка:

def create 
    respond_to do |format| 
     if params[:passwordHash].present? && params[:user].present? 
     password_and_salt = User.hash_password(params[:passwordHash]) 
     hashed_password = password_and_salt[:password] 
     user_salt = password_and_salt[:salt] 
     @user = User.new(:user => params[:user], :passwordHash => hashed_password, :salt => user_salt, :online_user => 1) 
     if @user.save 
      session[:user_id] = @user.id 
      redirect_to session[:item_to_edit] 
     else 
      format.html { render :action => "new" } 
      format.json { render :json => @user.errors, :status => :unprocessable_entity } 
     end 
     else 
      format.html { render :action => "new" } 
      format.json { render :json => @user.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 

Ошибка undefined method 'model_name' for NilClass:Class для этой линии:

= simple_form_for @user do |f| 

Очевидно, что @user = User.new не делает его обратно в форму. На этом этапе я немного запутался относительно того, как я должен написать метод create, чтобы он работал правильно и отображал сообщения об ошибках.Но я чувствую, что я поближе :)

@misha, здесь действие update контроллера, это просто довольно стандартные подмости:

def update 
    @user = User.find(params[:id]) 

    respond_to do |format| 
     if @user.update_attributes(params[:user]) 
     if session[:return_to] 
      format.html { redirect_to session[:return_to], :notice => 'User was successfully updated.' } 
     else 
      format.html { redirect_to users_path, :notice => 'User was successfully updated.' } 
     end 

     format.json { head :ok } 
     else 
     format.html { render :action => "edit" } 
     format.json { render :json => @user.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 
+0

пожалуйста показать нам соответствующие контроллеры (новые, создавать действия) –

+0

@RachidAlMaach, я только что обновил этот вопрос с информацией вы просили, надеюсь, что помогает определить ошибку, спасибо. – kakubei

+0

Непонятно, что на самом деле происходит не так. Чего вы ожидаете, что этого не произойдет? И вы могли бы показать действие контроллера обновления? – Mischa

ответ

0

Прежде всего то, что вы предполагаете здесь неверен:

What happens is the users#create action being invoked after submitting the form with empty values (which should not be possible). Of course I get an error because the passwordHash is empty.

Возможно, что вызывается users#create и на самом деле это должно быть. Именно в создании действия вы обрабатываете этот материал. Я думаю, ваша проблема в том, что вы делаете перенаправление, если @user не сохраняется. Вы должны снова отобразить представление, чтобы отображались сообщения об ошибках.

Таким образом, вместо:

redirect_to new_user_path, :notice => "User already exists, please pick another one" 

Try:

render :action => 'new' 

Редактировать основанный на ваш комментарий:

При сбое проверки Rails населяет @user.errors автоматически. Вам не нужно ничего делать в контроллере (т. Е. Ваше действие)! Все, что вам нужно сделать, это display the errors in @user.errors in your view.

об ошибке вы получаете в настоящее время:

Причины вы получаете ошибку в том, что @user не установлена. Вы должны переписать метод create на что-то вроде этого:

def create 
    respond_to do |format| 
    if params[:user][:passwordHash].present? 
     password_and_salt = User.hash_password(params[:user][:passwordHash]) 
     hashed_password = password_and_salt[:password] 
     user_salt = password_and_salt[:salt] 
    end 

    @user = User.new(params[:user].merge({:passwordHash => hashed_password, :salt => user_salt, :online_user => 1})) 

    if @user.save 
     session[:user_id] = @user.id 
     redirect_to session[:item_to_edit] 
    else 
     format.html { render :action => "new" } 
     format.json { render :json => @user.errors, :status => :unprocessable_entity } 
    end 
    end 
end 
+0

Хорошо, я в замешательстве. Действие обновления не имеет ничего общего с сообщениями, но я получаю сообщение о том, что имя пользователя не может быть пустым, когда его нет. Здесь, с вашими изменениями, я вернусь на страницу создания пользователя, но никаких сообщений об ошибках. Что мне не хватает? Ах, я думаю, что это 'format.json {render: json => @ user.errors,: status =>: unprocessable_entity}' эквивалент, который мне нужен в 'create', чтобы он отображал ошибки? Не могли бы вы помочь мне написать это для метода 'create'? См. Редактирование в исходном вопросе. – kakubei

+0

Где исходный вопрос? Когда проверка не удалась, Rails автоматически заполняет '@ user.errors'. Вам не нужно делать * ничего * в контроллере (т. Е. Ваше действие)! Все, что вам нужно сделать, это отобразить ошибки в '@ user.errors' в вашем представлении. – Mischa

+0

Извините, мне потребовалось некоторое время, чтобы отредактировать исходный вопрос, теперь вся информация должна быть там. – kakubei