Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 Polymorphic associations and concerns

I'm trying to add an Evaluation model to my Rails 4 app.

I have made a model called evaluation.rb. It has:

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]).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

QUESTIONS

How do I setup the show page to show a user's evaluations received?

How do I adapt the form so that it specifies a user id as the person who should receive the evaluation?

like image 825
Mel Avatar asked Apr 04 '16 04:04

Mel


People also ask

What is polymorphic associations in Rails?

Polymorphic relationship in Rails refers to a type of Active Record association. This concept is used to attach a model to another model that can be of a different type by only having to define one association.

What are Rails concerns?

A Rails Concern is a module that extends the ActiveSupport::Concern module. Concerns allow us to include modules with methods (both instance and class) and constants into a class so that the including class can use them. A concern provides two blocks: included.

How is polymorphic association set up in Rails?

The basic structure of a polymorphic association (PA)sets up 2 columns in the comment table. (This is different from a typical one-to-many association, where we'd only need one column that references the id's of the model it belongs to). For a PA, the first column we need to create is for the selected model.

What is polymorphic association in Sequelize?

A polymorphic association consists on two (or more) associations happening with the same foreign key. For example, consider the models Image , Video and Comment . The first two represent something that a user might post. We want to allow comments to be placed in both of them.


1 Answers

How do I setup the show page to show a user's evaluations received?

Your model concerns should help you with that. In your UsersController#show action, simply adding the following should do the trick:

@received_evaluations = @user.received_evaluations

Then you can use it in your show template:

<% @received_evaluations.each do |evaluation| %>
  // render some view stuff
<% end %>

Or use collection rendering.

note: the Evaluation.find(...) that's currently in your view should be put in the controller action, it's not good practice to leave that in the view.

How do I adapt the form so that it specifies a user id as the person who should receive the evaluation?

If you have identified the user that will serve as evaluatable you could set it in your controller action or in your view form in case you have a list of users to evaluate on your page.

In the controller:

@evaluation.evaluatable_id = user_to_evaluate.id
@evaluation.evaluatable_type = user_to_evaluate.class.to_s

Or this simpler statement should do the same:

@evaluation.evaluatable = user_to_evaluate

Similarly, you should be able to set the evaluator the same way:

@evaluation.evaluator = user_that_evaluates

In the view:

<% @users_to_evaluate.each do |user| %>
  <%= simple_form_for(Evaluation.new) 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}  %>
      <%= f.hidden_field :evaluator_id, :value => current_user.id %>
      <%= f.hidden_field :evaluator_type, :value => current_user.class.to_s %>
      <%= f.hidden_field :evaluatable_id, :value => user.id %>
      <%= f.hidden_field :evaluatable_type, :value => user.class.to_s %>
    </div>
  <% end %>
<% end %>
like image 102
Marc Lainez Avatar answered Sep 20 '22 08:09

Marc Lainez