Module: IsReviewable::Reviewable::InstanceMethods

Defined in:
lib/is_reviewable/reviewable.rb

Instance Method Summary collapse

Instance Method Details

#average_rating(recalculate = false) ⇒ Object

Calculate average rating for this reviewable object.


205
206
207
208
209
210
211
212
213
214
# File 'lib/is_reviewable/reviewable.rb', line 205

def average_rating(recalculate = false)
  if !recalculate && self.reviewable_caching_fields?(:average_rating)
    self.average_rating
  else
    conditions = self.reviewable_conditions(true)
    conditions[0] << ' AND rating IS NOT NULL'
    ::Review.average(:rating,
      :conditions => conditions).to_f.round(self.is_reviewable_options[:total_precision])
  end
end

#average_rating_by(identifiers) ⇒ Object

Calculate average rating for this reviewable object within a domain of reviewers.


218
219
220
221
222
223
# File 'lib/is_reviewable/reviewable.rb', line 218

def average_rating_by(identifiers)
  # FIXME: Only count non-nil ratings, i.e. See "average_rating".
  ::Review.average(:rating,
      :conditions => self.reviewer_conditions(identifiers).merge(self.reviewable_conditions)
    ).to_f.round(self.is_reviewable_options[:total_precision])
end

#review!(identifiers_and_options) ⇒ Object

View the object with and identifier (user or ip) - create new if new reviewer.

identifiers_and_options hash:

  • :reviewer/:user/:account - identify with a reviewer-model or IP (e.g. User, Account, …, “128.0.0.1”)

  • :rating - Review rating value, e.g. 3.5, “3.5”, … (optional)

  • :body - Review text body, e.g. “Lorem ipsum…” (optional)

  • :* - Any custom review field, e.g. :reviewer_mood => “angry” (optional)


268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/is_reviewable/reviewable.rb', line 268

def review!(identifiers_and_options)
  begin
    reviewer = self.validate_reviewer(identifiers_and_options)
    review = self.review_by(identifiers_and_options)
    
    # Except for the reserved fields, any Review-fields should be be able to update.
    review_values = identifiers_and_options.except(*::IsReviewable::Review::ASSOCIATIVE_FIELDS)
    review_values[:rating] = review_values[:rating].to_f if review_values[:rating].present?
    
    if review_values[:rating].present? && !self.valid_rating_value?(review_values[:rating])
      raise InvalidReviewValueError, "Invalid rating value: #{review_values[:rating]} not in [#{self.rating_scale.join(', ')}]."
    end
    
    unless review.present?
      # An un-existing reviewer of this reviewable object => Create a new review.
      review = ::Review.new do |r|
        r.reviewable_id   = self.id
        r.reviewable_type = self.class.name
        
        if Support.is_active_record?(reviewer)
          r.reviewer_id   = reviewer.id
          r.reviewer_type = reviewer.class.name
        else
          r.ip = reviewer
        end
      end
      self.reviews << review
    else
      # An existing reviewer of this reviewable object => Update the existing review.
    end
    
    # Update non-association attributes, such as rating, body (the review text), and any custom fields.
    review.attributes = review_values.slice(*review.attribute_names.collect { |an| an.to_sym })
    
    # Save review and cachable data.
    review.save && self.update_cache!
    review
  rescue InvalidReviewerError, InvalidReviewValueError => e
    raise e
  rescue Exception => e
    raise RecordError, "Could not create/update review #{review.inspect} by #{reviewer.inspect}: #{e}"
  end
end

#review_by(identifiers) ⇒ Object

Get review already reviewed by the given reviewer or ip.


256
257
258
# File 'lib/is_reviewable/reviewable.rb', line 256

def review_by(identifiers)
  self.reviews.find(:first, :conditions => reviewer_conditions(identifiers))
end

#reviewable?Boolean Also known as: is_reviewable?

Checks if this object reviewable or not.

Returns:

  • (Boolean)

178
179
180
# File 'lib/is_reviewable/reviewable.rb', line 178

def reviewable?
  self.class.reviewable?
end

#reviewable_precisionObject Also known as: rating_precision

The rating value precision used for this reviewable class.


192
193
194
# File 'lib/is_reviewable/reviewable.rb', line 192

def reviewable_precision
  self.class.reviewable_precision
end

#reviewable_scaleObject Also known as: rating_scale

The rating scale used for this reviewable class.


185
186
187
# File 'lib/is_reviewable/reviewable.rb', line 185

def reviewable_scale
  self.class.reviewable_scale
end

#reviewed?Boolean Also known as: is_reviewed?

Is this object reviewed by anyone?

Returns:

  • (Boolean)

238
239
240
# File 'lib/is_reviewable/reviewable.rb', line 238

def reviewed?
  self.total_reviews > 0
end

#reviewed_atObject

Reviewed at datetime.


199
200
201
# File 'lib/is_reviewable/reviewable.rb', line 199

def reviewed_at
  self.created_at if self.respond_to?(:created_at)
end

#reviewed_by?(identifiers) ⇒ Boolean Also known as: is_reviewed_by?

Check if an item was already reviewed by the given reviewer or ip.

identifiers hash:

  • :ip - identify with IP

  • :reviewer/:user/:account - identify with a reviewer-model (e.g. User, …)

Returns:

  • (Boolean)

249
250
251
# File 'lib/is_reviewable/reviewable.rb', line 249

def reviewed_by?(identifiers)
  self.reviews.exists?(:conditions => reviewer_conditions(identifiers))
end

#total_reviews(recalculate = false) ⇒ Object Also known as: number_of_reviews

Get the total number of reviews for this object.


227
228
229
230
231
232
233
# File 'lib/is_reviewable/reviewable.rb', line 227

def total_reviews(recalculate = false)
  if !recalculate && self.reviewable_caching_fields?(:total_reviews)
    self.total_reviews
  else
    ::Review.count(:conditions => self.reviewable_conditions)
  end
end

#unreview!(identifiers) ⇒ Object

Remove the review of this reviewer from this object.


314
315
316
317
318
319
320
321
322
323
# File 'lib/is_reviewable/reviewable.rb', line 314

def unreview!(identifiers)
  review = self.review_by(identifiers)
  review_rating = review.rating if review.present?
  
  if review && review.destroy
    self.update_cache!
  else
    raise RecordError, "Could not un-review #{review.inspect} by #{reviewer.inspect}: #{e}"
  end
end