在过去的几个月里,我一直试图找出如何建立评估模型,以便一些用户可以评估其他用户的联合项目。
我之前曾问过这个问题,但后来有一些建议认为使这个模型多态的建议不是正确的方法。我实际上无法在这篇文章中得到建议,但我现在的问题略有不同。
http://stackoverflow.com/questions/36394489/rails-4-polymorphic-associations-and-concerns
我有一个用户模型和一个评估模型。
用户
has_many :given_evaluations, foreign_key: :evaluator_id, dependent: :destroy, class_name: Evaluation
has_many :received_evaluations, foreign_key: :evaluatee_id, dependent: :destroy, class_name: Evaluation
评价
belongs_to :evaluator, foreign_key: :evaluator_id, class_name: User
belongs_to :evaluatee, foreign_key: :evaluatee_id, class_name: User
我现在正试图弄清楚如何设置表单,以便合适的用户获得评估并限制哪个用户可以留下反馈。
在评估表中,我有:
<%= simple_form_for(@evaluation) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :overall_score, collection: 1..10, autofocus: true, :label => "How do you rate this project experience (1 being did not meet expectations - 10 being met all expectations) ?" %>
<%= f.input :project_score, collection: 1..10, :label => "How successful was the project (1 being did not meet expectations - 10 being met all expectations)?" %>
<%= f.input :continue_project?, as: :boolean, checked_value: true, unchecked_value: false, :label => "Do you intend to continue working on the project?" %>
<%= f.input :remark, as: :text, :label => "Evaluate your project experience", :input_html => {:rows => 10} %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
在我的评估控制器中,我有:
class EvaluationsController < ApplicationController
before_action :set_evaluation, only: [:show, :edit, :update, :destroy]
# before_filter :get_user, only: [:show, :edit, :update, :destroy]
# GET /evaluations
# GET /evaluations.json
def index
@evaluations = Evaluation.all
end
# GET /evaluations/1
# GET /evaluations/1.json
def show
@received_evaluations = @user.received_evaluations
end
# GET /evaluations/new
def new
@evaluation = Evaluation.new
end
# GET /evaluations/1/edit
def edit
end
# POST /evaluations
# POST /evaluations.json
def create
@evaluation = Evaluation.new(evaluation_params)
respond_to do |format|
if @evaluation.save
format.html { redirect_to @evaluation, notice: 'Evaluation was successfully created.' }
format.json { render :show, status: :created, location: @evaluation }
else
format.html { render :new }
format.json { render json: @evaluation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /evaluations/1
# PATCH/PUT /evaluations/1.json
def update
respond_to do |format|
if @evaluation.update(evaluation_params)
format.html { redirect_to @evaluation, notice: 'Evaluation was successfully updated.' }
format.json { render :show, status: :ok, location: @evaluation }
else
format.html { render :edit }
format.json { render json: @evaluation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /evaluations/1
# DELETE /evaluations/1.json
def destroy
@evaluation.destroy
respond_to do |format|
format.html { redirect_to evaluations_url, notice: 'Evaluation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_evaluation
@evaluation = Evaluation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def evaluation_params
params[:evaluation].permit(:overall_score, :project_score, :personal_score, :remark, :work_again?, :continue_project?)
end
end
我是否已将控制器操作设为正确显示?我是否需要在控制器中放置一些内容以确定哪个用户正在接收评估以及哪个用户正在进行评估。我是否需要将:user_id添加到评估控制器中允许的参数?
如何更改表单以确定接收评估的正确用户。
我的路线是:
resources :evaluations
devise_for :users, #class_name: 'FormUser',
:controllers => {
:registrations => "users/registrations",
# :omniauth_callbacks => "users/authentications"
:omniauth_callbacks => 'users/omniauth_callbacks'
}
# get '/auth/:provider/callback' => 'users/authentications#create'
# get '/authentications/sign_out', :to => 'users/authentications#destroy'
# PER SOURCEY TUTORIAL ----------
match '/users/:id/finish_signup' => 'users#finish_signup', via: [:get, :patch], :as => :finish_signup
工作流
我没有在用户路线中嵌套评估路线的原因是我可能会尝试(如果我能先弄清楚这一部分)将项目评估与团队配对评估分开,在这种情况下,我&# 39; d喜欢将评估用于两个目的。我稍后再回过头来。目前,评估模型是针对用户的。
最后,我使用devise gem进行用户身份验证。
识别评估的问题
考虑到保罗关于如何识别evaluate_id的建议,我将此选择添加到我的评估表中:
<%= f.select :evaluatee_id, User.all.map{|u| [u.formal_name]} %>
保罗建议将u.id包含在此行的[]中。我不明白这一行代码中的所有部分是如何组合在一起的(或者是什么地图的意思)但我会再次尝试分别找到这些问题的解释。我删除了u.id,因为我收到了以下错误(事实证明删除它仍会导致下面的错误):
Couldn't find Evaluation with 'id'=7 [WHERE "evaluations"."evaluatee_id" = ?]
我可以从控制台看到评估正在保存,但它没有记录evaluatee_id。
Evaluation.last
Evaluation Load (10.3ms) SELECT "evaluations".* FROM "evaluations" ORDER BY "evaluations"."id" DESC LIMIT 1
=> #<Evaluation id: 7, evaluatee_id: 0, overall_score: nil, project_score: nil, personal_score: nil, remark: "edededededede", work_again?: nil, continue_project?: nil, created_at: "2016-06-10 02:08:44", updated_at: "2016-06-10 02:08:44", evaluator_id: 34>
错误消息指向我的评估控制器中的show动作,该动作具有:
def show
# @received_evaluations = @user.received_evaluations
@received_evaluation = current_user.received_evaluations.find params[:id]
end
答案 0 :(得分:1)
我同意多态关联是错误的方法。
您应该在#create
方法中执行此操作,以使用正确的评估程序自动记录评估:
def create
# change this: @evaluation = Evaluation.new(evaluation_params)
# to this:
@evaluation = current_user.given_evaluations.build(evaluation_params)
# ... the rest is fine as-is ...
end
current_user
来自Devise并返回当前登录的用户。
我还要确保#update
执行current_user.given_evaluations.find(params[:id])
,这样您就无法更改尚未编写的评估。与#destroy
相同。
根据您的要求,您可能希望以类似的方式访问其他方法。
您的#show
方法对我来说不对。它应该只找到一个评估:
def show
@received_evaluation = current_user.received_evaluations.find params[:id]
end
#index
也可能应限定为当前用户。您可能希望显示给出的评估以及收到的评估:
def index
@given_evaluations = curent_user.given_evaluations
@received_evaluations = curent_user.received_evaluations
end
编辑:要设置evaluatee_id
,只需像其他任何参数一样传递它。首先,允许它来自前端:
def evaluation_params
params[:evaluation].permit(
:overall_score, :project_score, :personal_score,
:remark, :work_again?, :continue_project?, :evaluatee_id)
end
然后在表单中添加一个小部件,以便用户提供它。例如,它可以是列出所有用户的<select>
:
<%= f.select :evaluatee_id, User.all.map{|u| [u.id, u.name]} %>
这将生成类似这样的HTML:
<select name="evaluation[evaluatee_id]">
<option value="1">Joe</option>
<option value="2">Sarah</option>
<option value="3">Fred</option>
</select>
在上文中,1
,2
和3
是您可以选择评估的用户的ID。每个<option>
的内容都是他们的名字。浏览器将提交您选择的任何评估的选项值(ID)。
当然,您应该将u.name
更改为您实际用于命名用户的任何列/方法,例如email
或full_name
或其他。此外,您可能希望对列表进行排序和过滤 - 适用于您的应用程序。
另请注意,使用<select>
只是一种选择。您可以让评估者在先前页面上选择evaluatee,然后将其作为隐藏字段传递给表单。或者你喜欢什么!关键是,只要前端发送evaluation[evaluatee_id]
,您就可以像任何其他参数一样保存它。