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

心已入冬 提交于 2020-01-17 06:06:07

问题


I've been trying, for the last few months, to figure out how to set up an evaluation model so that some users can evaluate other users on their joint projects.

I previously asked this question, but have since had some advice that the suggestion to make this model polymorphic was not the right approach. I wasn't actually able to get the advice in this post working, but my question is now slightly different.

http://stackoverflow.com/questions/36394489/rails-4-polymorphic-associations-and-concerns

I have a user model and an evaluation model.

User

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

Evaluation

belongs_to :evaluator, foreign_key: :evaluator_id, class_name: User
  belongs_to :evaluatee, foreign_key: :evaluatee_id, class_name: User

I'm now trying to figure out how to setup the form so that the right user gets the evaluation and to limit the which user can leave the feedback.

In the evaluation form, I have:

<%= 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 %>

In my evaluations controller, I have:

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

Have I got the controller action for show correct? Do I need to put something in the controller to identify which user is receiving the evaluation and which is giving the evaluation. Do I need to add the :user_id to the permitted params in the evaluations controller?

How do I change the form to identify the correct user that's receiving the evaluation.

My routes are:

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

Workflow

  1. A user creates a project (owner)
  2. The owner invites classmates to join the project (team mates)
  3. If team mates accept by the cut off date, the users involved in the project complete the project.
  4. Once complete, each user evaluates the other users involvement in the project and the project itself. To do that, each user that is involved in the project sees a button on their user page, to get a link to the evaluation form. I need to figure out how to reference the other user ids for the team mates as well as the project they worked on.

The reason why I didn't nest the evaluation route inside the user routes is that I might try (if I can figure out this part first) to separate project evaluation from team mate evaluation, in which case, I'd like to use evaluation for two purposes. I'll come back to that later. For now, the evaluation model is on a user.

Finally, I use devise gem for user authentication.

PROBLEMS IDENTIFYING EVALUATEE

Taking Paul's suggestion for how to identify the evaluate_id, I added this select to my evaluation form:

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

Paul suggested including u.id inside the [] of this line. I don't understand how all the pieces fit together in this line of code (or what map means) but I will try again to find explanations of those issues separately. I removed the u.id, because I was getting the error below (it turns out that removing it still leads to the error below):

Couldn't find Evaluation with 'id'=7 [WHERE "evaluations"."evaluatee_id" = ?]

I can see from the console that the evaluation is saving, but it is not recording the 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> 

The error message points to the show action in my evaluations controller, which has:

def show
    # @received_evaluations = @user.received_evaluations

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

回答1:


I agree that polymorphic associations are the wrong approach here.

You should do this in your #create method to automatically record evaluations with the correct evaluator:

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

The current_user comes from Devise and returns whatever user is currently logged in.

I would also make sure that #update does current_user.given_evaluations.find(params[:id]), so that you can't change evaluations you haven't written. Same for #destroy.

Depending on your requirements you may want to access other methods in a similar way.

Your #show method looks wrong to me. It should only find one evaluation:

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

Also #index should probably be scoped to the current user. Possibly you want to show evaluations you gave plus evaluations you received:

def index
  @given_evaluations = curent_user.given_evaluations
  @received_evaluations = curent_user.received_evaluations
end

EDIT: To set the evaluatee_id, just pass it like any other param. First, permit it to come from the front end:

def evaluation_params
  params[:evaluation].permit(
    :overall_score, :project_score, :personal_score,
    :remark, :work_again?, :continue_project?, :evaluatee_id)
end

Then add a widget to your form to let users provide it. For instance it could be a <select> listing all the users:

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

This will generate HTML something like this:

<select name="evaluation[evaluatee_id]">
  <option value="1">Joe</option>
  <option value="2">Sarah</option>
  <option value="3">Fred</option>
</select>

In the above, 1, 2, and 3 are the IDs of the users you can choose to evaluate. The contents of each <option> are their names. The browser will submit the option value (the ID) of whichever evaluatee you choose.

Of course you should change u.name to whatever column/method you actually use to name users, e.g. email or full_name or whatever. Also you might want to sort and filter the list---whatever is appropriate for your app.

Also note that using a <select> is just one option. You could have evaluators choose the evaluatee on a prior page, and pass it through the form as a hidden field instead. Or whatever you like! The point is that as long as the front end is sending an evaluation[evaluatee_id], you can save it like any other param.



来源:https://stackoverflow.com/questions/37610784/rails-feedback-on-specific-users-how-to-set-up-the-form-to-identify-relevant

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!