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

时间:2016-06-03 09:32:20

标签: ruby-on-rails associations

在过去的几个月里,我一直试图找出如何建立评估模型,以便一些用户可以评估其他用户的联合项目。

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

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

工作流

  1. 用户创建项目(所有者)
  2. 所有者邀请同学加入项目(队友)
  3. 如果队友在截止日期前接受,项目所涉及的用户将完成该项目。
  4. 完成后,每个用户都会评估其他用户对项目和项目本身的参与情况。为此,项目中涉及的每个用户都会在其用户页面上看到一个按钮,以获取评估表单的链接。我需要弄清楚如何引用团队成员的其他用户ID以及他们所处理的项目。
  5. 我没有在用户路线中嵌套评估路线的原因是我可能会尝试(如果我能先弄清楚这一部分)将项目评估与团队配对评估分开,在这种情况下,我&# 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
    

1 个答案:

答案 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>

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

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

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