我正在使用表单为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/ruby-2.0.0-p353@fluctus/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.7ms)
Rendered /Users/kec6en/.rvm/gems/ruby-2.0.0-p353@fluctus/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.1ms)
Rendered /Users/kec6en/.rvm/gems/ruby-2.0.0-p353@fluctus/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.1ms)
Rendered /Users/kec6en/.rvm/gems/ruby-2.0.0-p353@fluctus/gems/actionpack-4.0.3/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (22.0ms)
答案 0 :(得分:0)
这是导致代码失败的原因。
Unpermitted parameters: institution_pid
DO
params.require(:user).permit(:institution_pid)
或s.th.像这样。
了解更多 http://edgeapi.rubyonrails.org/classes/ActionController/Parameters.html
答案 1 :(得分:-1)
我明白了。无论如何,感谢您查看我的代码。我需要在build_institution_pid
方法中添加一行来检查参数是否为空。现在一切都验证了应有的方式。