Created
March 25, 2016 06:56
-
-
Save aganov/ea95dd45ebe3be567871 to your computer and use it in GitHub Desktop.
rails-completeness
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Completeness | |
extend ActiveSupport::Concern | |
included do | |
class_attribute :completeness_checks | |
class_attribute :completeness_attributes | |
attr_accessor :completeness_points | |
attr_accessor :incomplete_attributes | |
end | |
# Class methods | |
module ClassMethods | |
def define_completeness(&checks_block) | |
self.completeness_checks = Completeness::Builder.build(self, &checks_block) | |
self.completeness_attributes = self.completeness_checks.keys | |
end | |
end | |
# Instance methods | |
def complete? | |
self.completeness_points = {} | |
self.incomplete_attributes = [] | |
self.class.completeness_checks.each do |attribute, check| | |
if (check[:unless].blank? && check[:if].blank?) || (check[:if] && check[:if].call(self)) || (check[:unless] && !check[:unless].call(self)) | |
complete = check[:check].call(self.send(attribute)) | |
self.completeness_points[attribute] = (complete ? 1 : 0) * check[:points] | |
unless check[:points_per_item].blank? | |
points = check[:points_per_item] * self.send(attribute).count | |
self.completeness_points[attribute] = (points >= check[:points]) ? check[:points] : points | |
end | |
self.incomplete_attributes << attribute unless complete | |
end | |
end | |
self.incomplete_attributes.empty? | |
end | |
class Builder < Struct.new(:completeness_checks, :model) | |
def self.build(model, &block) | |
builder = self.new({}, model) | |
builder.instance_eval(&block) | |
builder.completeness_checks | |
end | |
protected | |
def check(*attributes) | |
options = attributes.extract_options! | |
attributes.each do |attribute| | |
if options[:with].nil? | |
association = self.model.reflect_on_association(attribute) | |
unless association.nil? | |
case association.macro | |
when :has_many | |
with = lambda { |relation| relation.present? && relation.count >= 1 } | |
end | |
end | |
end | |
self.completeness_checks[attribute] = { | |
points: options[:points], | |
points_per_item: options[:points_per_item], | |
check: options[:with] || with || lambda { |a| a.present? }, | |
unless: options[:unless], | |
if: options[:if] | |
} | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user = User.first | |
user.complete? | |
user.incomplete_attributes | |
user.completeness_points |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
include Completeness | |
define_completeness do | |
check :name, points: 34 | |
check :avatar, points: 33 | |
check :role, points: 33, with: lambda { |role| | |
![nil, "", "not_set"].include?(role) | |
} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment