Rails - 对特定用户的反馈,如何设置表单来识别相关用户

Rails - feedback on specific users, how to set up the form to identify relevant users

在过去的几个月里,我一直在尝试弄清楚如何建立一个评估模型,以便一些用户可以在他们的联合项目上评估其他用户。

我之前问过这个问题,但后来得到一些建议,认为使这个模型多态化的建议不是正确的方法。我实际上无法在此 post 工作中获得建议,但我的问题现在略有不同。


我有一个用户模型和一个评价模型。

用户

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

工作流程

  1. 用户创建项目(所有者)
  2. 楼主邀请同学加入项目(队友)
  3. 如果队友在截止日期前接受,则参与项目的用户完成项目。
  4. 完成后,每个用户都会评估其他用户对项目的参与以及项目本身。为此,参与该项目的每个用户都会在其用户页面上看到一个按钮,以获取评估表的 link。我需要弄清楚如何引用团队成员的其他用户 ID 以及他们从事的项目。

我之所以没有把评估路线嵌套在用户路线中,是因为我可能会尝试(如果我能先弄清楚这部分)将项目评估与队友评估分开,在这种情况下,我'我喜欢将评估用于两个目的。我稍后再谈。目前,评估模型在用户身上。

最后,我使用设计 gem 进行用户身份验证。

识别被评估者的问题

根据 Paul 关于如何识别 evaluate_id 的建议,我将此 select 添加到我的评估表中:

<%= f.select :evaluatee_id, User.all.map{|u| [u.formal_name]} %>

Paul 建议在该行的 [] 中包含 u.id。我不明白这行代码中的所有部分是如何组合在一起的(或者 map 是什么意思),但我会再次尝试分别找到这些问题的解释。我删除了 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> 

错误消息指向我的评估控制器中的显示操作,其中包含:

def show
    # @received_evaluations = @user.received_evaluations

    @received_evaluation = current_user.received_evaluations.find params[:id]
  end

我同意多态关联在这里是错误的方法。

您应该在 #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,returns 当前登录的任何用户。

我还要确保 #updatecurrent_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>

其中123是您可以选择评价的用户ID。每个<option>的内容都是他们的名字。浏览器将提交您选择的任何评估者的选项值(ID)。

当然,您应该将 u.name 更改为您实际用于命名用户的任何 column/method,例如emailfull_name 或其他。此外,您可能希望对列表进行排序和过滤——任何适合您应用的内容。

另请注意,使用 <select> 只是一种选择。您可以让评估者在前一页上选择被评估者,然后将其作为隐藏字段传递给表单。或者任何你喜欢的!关键是只要前端发送一个evaluation[evaluatee_id],你就可以像保存其他参数一样保存它。