问题
I'm trying to figure out how to implement an evaluation model in my Rails 4 app.
I've previously asked these related questions but am yet to solve this problem:
Rails 4 Polymorphic associations and concerns
Rails 4 - post completion evaluations model - structure
I have:
class Evaluation < ActiveRecord::Base
belongs_to :evaluator, :polymorphic => true
belongs_to :evaluatable, :polymorphic => true
I have also made concerns for evaluator and evaluatable as:
module Evaluator
extend ActiveSupport::Concern
included do
has_many :given_evaluations, as: :evaluator, dependent: :destroy, class_name: 'Evaluation'
end
end
module Evaluatable
extend ActiveSupport::Concern
included do
has_many :received_evaluations, as: :evaluatable, dependent: :destroy, class_name: 'Evaluation'
end
end
I have included each concern in my user model:
class User < ActiveRecord::Base
include Evaluator
include Evaluatable
In my show page, I want to show a particular user's evaluations (received from other users -who are evaluators).
In my show, I have:
<% Evaluation.find(params[:id]).received_evaluations.order('created_at DESC').each do |eval| %>
<div id="portfolioFiltering" class="masonry-wrapper row">
<%= eval.remark %>
<%= eval.personal_score %>
<small><%= eval.created_at %></small>
In my evaluations form, I"m not sure how to designate the recipient of the evaluation. I have made the basic form, but I'm not clear about how to tie it to the user who should receive the evaluation.
<%= simple_form_for(@evaluation) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :score, collection: 1..10, autofocus: true, :label => "How do you rate this experience (1 being did not meet expectations - 10 being met all expectations) ?" %>
<%= f.input :remark, as: :text, :label => "Evaluate your project experience", :input_html => {:rows => 10} %>
My evaluations table has:
t.integer "user_id"
t.integer "evaluatable_id"
t.string "evaluatable_type"
t.integer "overall_score"
t.integer "project_score"
t.integer "personal_score"
t.text "remark"
t.boolean "work_again?"
t.boolean "continue_project?"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "evaluations", ["evaluatable_type", "evaluatable_id"], name: "index_evaluations_on_evaluatable_type_and_evaluatable_id", unique: true, using: :btree
In my users controller, I have:
def show
# authorize! :read, @user
@received_evaluations = @user.received_evaluations
end
I currently get an error that says:
undefined method `received_evaluations' for #<Evaluation:0x007fb8c4b32160>
I'm not sure what this message means or how to solve it.
If I change the show to:
<% @user.received_evaluations.each do |eval| %>
I get this error:
undefined method `received_evaluations' for nil:NilClass
回答1:
Reading your different questions on this issue I think what are are trying to set up a mechanism for one User to evaluate another User.
Based on the above logic, the use of polymorphic associations is not required. They are probably overcomplicating things for you.
This is what I think you need:
class User
has_many :given_evaluations, foreign_key: :evaluator_id, class_name: Evaluation
has_many :received_evaluations, foreign_key: :evaluatee_id, class_name: Evaluation
end
class Evaluation
belongs_to :evaluator, foreign_key: :evaluator_id, class_name: User
belongs_to :evaluatee, foreign_key: :evaluatee_id, class_name: User
end
Your evaluation table would be like this:
id :integer not null, primary key
evaluator_id :integer not null
evaluatee_id :integer not null
overall_score :integer
continue_project :boolean
created_at :datetime not null
updated_at :datetime not null
You can then do away with the Evaluator and Evaluatable modules.
So, now to display a user's received evaluations and get rid of the error messages you are receiving:
In the controller:
# ensure we get the user for all relevant routes
before_filter :get_user, only: [:show, edit, :update, :destroy]
def get_user
@user = User.find(params[:id])
end
def show
# get the received evaluations and order
@received_evaluations = @user.received_evaluations
@received_evaluations = @received_evaluations.order('created_at DESC')
# you will probably want grab the evaluator record as well...
@received_evaluations = @received_evaluations.includes(:evaluator)
end
And in the show view
<% @received_evaluations.each do |eval| %>
<div id="portfolioFiltering" class="masonry-wrapper row">
<%= eval.remark %>
<%= eval.personal_score %>
<small><%= eval.created_at %></small>
...
</div>
<% end %>
来源:https://stackoverflow.com/questions/37506781/evaluation-polymorphic-associations-on-feedback-loop