我有两个用户模型:Company
和Freelancer
。在交易结束时,每个都给予对方星级。我尝试使用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' %>
但这仅允许公司对自由职业者进行评分。我该如何以两种方式实现这一目标,以便双方都能相互评价?
答案 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;
}
}