如何在红宝石导轨上的多个型号上实施星级评定系统?

时间:2019-06-18 05:59:03

标签: ruby-on-rails ruby

我有两个用户模型:CompanyFreelancer。在交易结束时,每个都给予对方星级。我尝试使用ratyrate宝石。但是它只允许使用单个rater模型。有什么办法可以做到这一点? Ratyrate使用User模型作为rater生成以下模型:

class Rate < ActiveRecord::Base
  belongs_to :rater, :class_name => "User"
  belongs_to :rateable, :polymorphic => true
end

class RatingCache < ActiveRecord::Base
  belongs_to :cacheable, :polymorphic => true
end

class AverageCache < ActiveRecord::Base
  belongs_to :rater, :class_name => "User"
  belongs_to :rateable, :polymorphic => true
end

class OverallAverage < ActiveRecord::Base
  belongs_to :rateable, :polymorphic => true
end

我所做的如下:

class Rate < ActiveRecord::Base
  belongs_to :rater, :class_name => "Company"
  belongs_to :rateable, :polymorphic => true
end

class Company < ActiveRecord::Base
  ratyrate_rater
end

class Freelancer < ActiveRecord::Base
 ratyrate_rateable "performance"
end

我认为:

<%= rating_for @freelancer, 'performance' %>

但这仅允许公司对自由职业者进行评分。我该如何以两种方式实现这一目标,以便双方都能相互评价?

2 个答案:

答案 0 :(得分:1)

我认为您需要看看polymorphic-associations

它允许您拥有一个可以属于多个模型的模型。就您而言,

class Rating < ApplicationRecord
  belongs_to :rateable, polymorphic: true
end

class Company < ApplicationRecord
  has_many :ratings, as: :rateable
end

class Freelancer < ApplicationRecord
  has_many :ratings, as: :rateable
end

,然后将ratyrate添加到Rating

作为一个友好的注释(并且由于您的声誉不是87,所以您在这里不是很新):您应该添加更多详细信息和您尝试过的问题。这将表明您已经努力解决了自己的问题,然后向StackOverflow寻求帮助。同样,缩小问题范围也将有助于获得良好的答案:)

答案 1 :(得分:0)

我使用acts_as_rateable plugin并对其进行了一些自定义解决。

我的最终实现如下:

app / models / company.rb

require 'acts_as_rateable'
class Company < ApplicationRecord
  acts_as_rateable
end

app / models / freelancer.rb

require 'acts_as_rateable'
class Freelancer < ApplicationRecord
  acts_as_rateable
end

app / controllers / companies_controller.rb

def rate_freelancer
  @freelancer.rate_it(params[:rating], current_company)
  respond_to :html
  respond_to :js
end

app / controllers / freelancer_controller.rb

def rate_company
  @company.rate_it(params[:rating], current_freelancer)
  respond_to :html
  respond_to :js
end

config / routes.rb

post 'rate_freelancer' => 'companies#rate_freelancer'
post 'rate_company' => 'freelancers#rate_company'

app / models / rate.rb

# Table name: rates
#
#  id    :uuid             not null, primary key
#  score :float

class Rate < ActiveRecord::Base
  has_many :ratings

  validates_presence_of :score
  validates_uniqueness_of :score
  validates_numericality_of :score, :greater_than_or_equal_to => 1, :less_than_or_equal_to => 10

  attr_accessor :user_id
  attr_accessor :free_text
  attr_accessor :rater_name
end

app / models / rating.rb

# Table name: ratings
#
#  id            :bigint(8)        not null, primary key
#  user_id       :uuid
#  rate_id       :uuid
#  rateable_id   :uuid
#  rateable_type :string
#  free_text     :text
#  rater_name    :string
#  created_at    :datetime         not null
#  updated_at    :datetime         not null

class Rating < ActiveRecord::Base
  belongs_to :rate
  belongs_to :rateable, :polymorphic => true

  class << self
    def parse_as(ratings, output = :xml)
      if output == :xml
        ratings.to_xml(:only => [:user_id, :free_text, :rater_name,  :created_at],
                   :methods => [:score])
      elsif output == :json
        ratings.to_json(:only => [:user_id, :free_text, :rater_name, :created_at],
                    :methods => [:score])
      end
    end
  end 
  def score
    rate.score
  end
end

在评分表视图中:

<section class='rating-widget pt-2'>
  <div class='rating-stars text-center'>
      How was your experience? <br>
      <ul id='stars'>
          <li class='star' title='Poor' data-value='1'>
              <i class='fa fa-star fa-fw'></i>
          </li>
          <li class='star' title='Fair' data-value='2'>
              <i class='fa fa-star fa-fw'></i>
          </li>
          <li class='star' title='Good' data-value='3'>
              <i class='fa fa-star fa-fw'></i>
          </li>
          <li class='star' title='Excellent' data-value='4'>
              <i class='fa fa-star fa-fw'></i>
          </li>
          <li class='star' title='WOW!!!' data-value='5'>
              <i class='fa fa-star fa-fw'></i>
          </li>
       </ul>
    </div>
</section>

运行该脚本的脚本:

<script type="text/javascript">
$(document).ready(function() {
    /* 1. Visualizing things on Hover*/
    $('#stars li').on('mouseover', function() {
        var onStar = parseInt($(this).data('value'), 10); // The star currently mouse on
        // Now highlight all the stars that's not after the current hovered star
        $(this).parent().children('li.star').each(function(e) {
            if (e < onStar) {
                $(this).addClass('hover');
            } else {
                $(this).removeClass('hover');
            }
        });
    }).on('mouseout', function() {
        $(this).parent().children('li.star').each(function(e) {
            $(this).removeClass('hover');
        });
    });
    /* 2. Action to perform on click */
    $('#stars li').on('click', function() {
        var onStar = parseInt($(this).data('value'), 10); // The star currently selected
        var stars = $(this).parent().children('li.star');
        for (i = 0; i < stars.length; i++) {
            $(stars[i]).removeClass('selected');
        }
        for (i = 0; i < onStar; i++) {
            $(stars[i]).addClass('selected');
        }
        var ratingValue = parseInt($('#stars li.selected').last().data('value'), 10);
        var url = "<%= @url %>";
        var user_id = "<%= @user_id %>";
        $.ajax({
                type: "POST",
                url: url,
                data: { value: ratingValue, user_id: user_id },
                dataType: "JSON"
            })
            .done(function() {
                window.location.reload();
            });
    });
});
</script>

最后的样式使星星发光:

/* Rating Star Widgets Style */
.rating-stars ul {
  list-style-type:none;
  padding:0;

  -moz-user-select:none;
  -webkit-user-select:none;
}
.rating-stars ul > li.star {
  display:inline-block;
}

/* Idle State of the stars */
.rating-stars ul > li.star > i.fa {
  font-size:2em; /* Change the size of the stars */
  color:#ccc; /* Color on idle state */
}

/* Hover state of the stars */
.rating-stars ul > li.star.hover > i.fa {
  color:#FFCC36;
}

/* Selected state of the stars */
.rating-stars ul > li.star.selected > i.fa {
  color:#FF912C;
}

.rated-stars{
  i.fa{
    font-size:2em;
    color:#FFCC36;
  }
}