2014-02-28 70 views
0

我正在製作一個表格,爲Ruby on Rails項目創建新用戶。我想首先提一下,當正確填寫表單併爲用戶創建正確的方式時,表單本身工作得很好。但是,並不是所有的Active Record Validation似乎都能正常工作,特別是validates :institution_pid, presence: true位。表單的其餘部分以它應該的方式工作。如果元素爲空或正確填寫,則會在屏幕上彈出一條錯誤消息,以便用戶可以修復它,並且不會提交表單。但被選擇,如果表格沒有一個機構提交,而不是該錯誤顯示了它提交反正,然後我得到這個錯誤:活動記錄驗證,無法使用

ActiveFedora::ObjectNotFoundError in UsersController#create 

這是發生,很明顯,因爲它試圖利用該機構從尚未填寫的表格。我無法弄清楚爲什麼它這樣做,並提交,而不是驗證彈出一個錯誤,因爲表格沒有被正確填寫。

這裏是我的用戶模型:

class User < ActiveRecord::Base 
    # Connects this user object to Hydra behaviors. 
    include Hydra::User 

    # Connects this user object to Blacklights Bookmarks. 
    include Blacklight::User 
    include Aptrust::SolrHelper 

    # Connects this user object to Role-management behaviors. 
    include Hydra::RoleManagement::UserRoles 

    # Include default devise modules. Others available are: 
    # :database_authenticatable, 
    # :recoverable, :rememberable, :trackable, :validatable, 
    # :token_authenticatable, :confirmable, 
    # :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :recoverable, :rememberable, :trackable, :timeoutable,  :validatable 

    validates :email, :phone_number, :role_ids, presence: true 
    validates :email, uniqueness: true 
    validates :institution_pid, presence: true 
    validate :institution_pid_points_at_institution 

    # Custom format validations. See app/validators 
    validates :name, person_name_format: true, if: ->{ name.present? } 
    validates :email, email: true 

    # Handle and normalize phone numbers 
    phony_normalize :phone_number, :default_country_code => 'US' 

    validates :phone_number, :phony_plausible => true 

    # This method assigns permission groups 
    def groups 
    super + institution_groups 
    end 

    def institution_groups 
    if institutional_admin? 
     ["Admin_At_#{institution_group_suffix}"] 
    elsif institutional_user? 
     ["User_At_#{institution_group_suffix}"] 
    else 
     [] 
    end 
    end 

    # Blacklight uses #to_s on youruser class to get a user-displayable 
    # login/identifier for the account. 
    # 
    # Method modified from the Blacklight default. 
    def to_s 
    name || email 
    end 

    def as_json(options = nil) 
    json_data = super 
    json_data.delete('api_secret_key') 
    json_data.delete('encrypted_api_secret_key') 
    json_data 
    end 

    # Roles are managed through the hydra-role-management gem. 
    def is?(role) 
    self.roles.pluck(:name).include?(role.to_s) 
    end 

    def admin? 
    is? 'admin' 
    end 

    def institutional_admin? 
    is? 'institutional_admin' 
    end 

    def institutional_user? 
    is? 'institutional_user' 
    end 

    def role_id 
    if(admin?) 
     Role.where(name: 'admin').first_or_create.id 
    elsif(institutional_admin?) 
     Role.where(name: 'institutional_admin').first_or_create.id 
    elsif(institutional_user?) 
     Role.where(name: 'institutional_user').first_or_create.id 
    end 
    end 

    # Since an Institution is an ActiveFedora Object, these two objects cannot be related as normal (i.e. belongs_to) 
    # They will be connected through the User.institution_pid. 
    def institution 
    @institution ||= Institution.find(self.institution_pid) 
    rescue ActiveFedora::ObjectNotFoundError => e 
    logger.warn "#{self.institution_pid} is set as the institution for #{self}, but it doesn't exist" 
    @institution = NilInstitution.new 
    end 

    def institution_group_suffix 
    clean_for_solr(institution_pid) 
    end 

    # Guest users are disabled in this application. The default Blacklight installation includes the gem devise-guests 
    # which is not bundled with this app. hydra-role-management gem requires a guest boolean, so we must provide it here. 
    # This will be fixed in hydra-role-management 0.1.1 
    def guest? 
    false 
    end 

    attr_reader :api_secret_key 

    def api_secret_key=(key) 
    @api_secret_key = key 
    self.encrypted_api_secret_key = if key.blank? 
     nil 
    else 
     password_digest(key) 
    end 
    end 

    # Generate a new API key for this user 
    def generate_api_key(length = 20) 
    self.api_secret_key = SecureRandom.hex(length) 
    end 

    # Verifies whether an API key (from sign in) matches the user's API key. 
    def valid_api_key?(input_key) 
    return false if encrypted_api_secret_key.blank? 
    bcrypt = ::BCrypt::Password.new(encrypted_api_secret_key) 
    key = ::BCrypt::Engine.hash_secret("#{input_key}#{User.pepper}", bcrypt.salt) 
    Devise.secure_compare(key, encrypted_api_secret_key) 
    end 

    class NilInstitution 
    def name 
     "Deleted Institution" 
    end 

    def to_param 
     'deleted' 
    end 

    def brief_name 
     "Deleted Institution" 
    end 

    def users 
     [] 
    end 

    def intellectual_objects 
     [] 
    end 

    def bytes_by_format 
     {} 
    end 
    end 

    private 

    def institution_pid_points_at_institution 
    errors.add(:institution_pid, "is not a valid institution") unless Institution.exists?(institution_pid) 
    end 

end 

這是我的用戶控制器:

class UsersController < ApplicationController 
    inherit_resources 
    load_and_authorize_resource 
    before_filter :authenticate_user! 

    def destroy 
    name = @user.to_s 
    destroy!(notice: "User #{@user.to_s} was deleted.") 
    end 

    def edit_password 
    @user = current_user 
    end 

    def update_password 
    @user = User.find(current_user.id) 
    if @user.update_with_password(user_params) 
     sign_in @user, :bypass => true 
     redirect_to root_path 
     flash[:notice] = "Successfully changed password." 
    else 
     redirect_to root_path 
     flash[:alert] = "Current password was incorrect, new password was too short, or passwords did not match. Password has not been changed." 
    end 
    end 

    def generate_api_key 
    @user.generate_api_key 

    if @user.save 
     msg = ["Please record this key. If you lose it, you will have to generate a new key.", 
     "Your API secret key is: #{@user.api_secret_key}"] 
     msg = msg.join("<br/>").html_safe 
     flash[:notice] = msg 
    else 
     flash[:alert] = 'ERROR: Unable to create API key.' 
    end 

    redirect_to user_path(@user) 
    end 

    private 

    def build_resource_params 
     [params.fetch(:user, {}).permit(:name, :email, :phone_number, :password, :password_confirmation).tap do |p| 
     p[:institution_pid] = build_institution_pid if params[:user][:institution_pid] 
     p[:role_ids] = build_role_ids if params[:user][:role_ids] 
     end] 
    end 

    def build_institution_pid 
     institution = Institution.find(params[:user][:institution_pid]) 
     authorize!(:add_user, institution) 
     institution.id 
    end 

    def build_role_ids 
     [].tap do |role_ids| 
     unless params[:user][:role_ids].empty? 
      roles = Role.find(params[:user][:role_ids]) 

      authorize!(:add_user, roles) 
      role_ids << roles.id 

     end 
     end 
    end 

    def user_params 
    params.required(:user).permit(:password, :password_confirmation, :current_password) 
    end 

end 

這是形式的代碼我使用:

<div class="page-header"> 
    <h1>Registering New User</h1> 
</div> 

<%= simple_form_for(@user, html: {class: 'form-horizontal'}) do |f| %> 
    <%= f.error_notification %> 

    <div class="form-inputs"> 
     <%= f.input :name, autofocus: true %> 
     <%= f.input :email %> 
     <%= f.input :phone_number %> 

     <%= f.input :institution_pid, collection: institutions_for_select, as: :select, label: "Institution" %> 

     <%= f.association :roles, collection: roles_for_select, as: :radio_buttons %> 

     <%= f.input :password %> 
     <%= f.input :password_confirmation %> 

    </div> 
    <br> 
    <div class="form-actions"> 
     <%= button_tag(type: 'submit', class: "btn doc-action-btn btn-success") do %> 
      <i class="glyphicon glyphicon-check"></i> Submit 
     <% end %> 
     <%= link_to @user, {class: "btn doc-action-btn btn-cancel"} do %> 
      <i class="glyphicon glyphicon-remove"></i> Cancel 
     <% end %> 
    </div> 
<% end %> 

而且這裏是機構元素的表單生成的HTML,這給了我一個麻煩,如果有幫助的話。

<div class="controls"> 
    <select class="select required" id="user_institution_pid" name="user[institution_pid]"> 
    <option value=""></option> 
    <option value="aptrust-dev:363">APTrust</option> 
    <option selected="selected" value="aptrust-dev:365">North Carolina State University</option> 
    <option value="aptrust-dev:364">Columbia University</option> 
    </select> 
</div> 

登錄:

Started POST "/users" for 127.0.0.1 at 2014-02-28 09:05:15 -0500 
Processing by UsersController#create as HTML 
Parameters: {"utf8"=>"✓", "authenticity_token"=>"WjALLu82iJDDNBEnNpdqupVERdYVOg1l1W/t5v7yaog=", "user"=>{"name"=>"", "email"=>"", "phone_number"=>"", "institution_pid"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}} 
Unpermitted parameters: institution_pid 
Completed 500 Internal Server Error in 3ms 

ActiveFedora::ObjectNotFoundError (Unable to find "" in fedora.): 
    app/controllers/users_controller.rb:52:in `build_institution_pid' 
    app/controllers/users_controller.rb:46:in `block in build_resource_params' 
    app/controllers/users_controller.rb:45:in `tap' 
    app/controllers/users_controller.rb:45:in `build_resource_params' 


    Rendered /Users/kec6en/.rvm/gems/[email protected]/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.7ms) 
    Rendered /Users/kec6en/.rvm/gems/[email protected]/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.1ms) 
    Rendered /Users/kec6en/.rvm/gems/[email protected]/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.1ms) 
    Rendered /Users/kec6en/.rvm/gems/[email protected]/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (22.0ms) 
+0

UsersController中的create方法在哪裏? –

+0

另外,您可以在提交表單時共享服務器日誌。 –

+0

你可以和我聊天http://chat.stackoverflow.com/rooms/48530/ror –

回答

-1

我想通了。感謝您查看我的代碼。我需要添加一行來檢查build_institution_pid方法中的參數是否爲空。現在一切都驗證了它應該的方式。