completeness-fu 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ test/test.sqlite3
2
+ pkg
3
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'although not required, its recommended you use bundler during development'
6
+ end
7
+
8
+ require 'rake'
9
+
10
+ Bundler::GemHelper.install_tasks
11
+
12
+ desc 'Default: run unit tests.'
13
+ task :default => [:test]
14
+
15
+ require 'rake/testtask'
16
+ Rake::TestTask.new(:test) do |t|
17
+ t.pattern = 'test/**/*_test.rb'
18
+ t.verbose = true
19
+ end
20
+
21
+ require 'rake/rdoctask'
@@ -0,0 +1,51 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{completeness-fu}
8
+ s.version = "0.6.0"
9
+ s.date = %q{2011-03-29}
10
+
11
+ s.summary = %q{Simple dsl for defining how to calculate how complete a model instance is (similar to LinkedIn profile completeness)}
12
+ s.description = s.summary
13
+ s.homepage = %q{http://github.com/joshk/completeness-fu}
14
+
15
+ s.authors = ["Josh Kalderimis"]
16
+ s.email = %q{josh.kalderimis@gmail.com}
17
+
18
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
19
+
20
+ s.extra_rdoc_files = ["readme.markdown"]
21
+ s.rdoc_options = ["--charset=UTF-8"]
22
+ s.rubygems_version = %q{1.3.6}
23
+
24
+ s.require_paths = ['lib']
25
+ s.files = `git ls-files`.split("\n")
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
28
+
29
+ if s.respond_to? :specification_version then
30
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
31
+ s.specification_version = 3
32
+
33
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
34
+ s.add_development_dependency(%q<activemodel>, ["~> 3.0.0"])
35
+ s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
36
+ s.add_development_dependency(%q<shoulda>, ["~> 2.11.3"])
37
+ s.add_development_dependency(%q<mocha>, ["~> 0.9.8"])
38
+ else
39
+ s.add_dependency(%q<activemodel>, ["~> 3.0.0"])
40
+ s.add_dependency(%q<rake>, ["~> 0.8.7"])
41
+ s.add_dependency(%q<shoulda>, ["~> 2.11.3"])
42
+ s.add_dependency(%q<mocha>, ["~> 0.9.8"])
43
+ end
44
+ else
45
+ s.add_dependency(%q<activemodel>, ["~> 3.0.0"])
46
+ s.add_dependency(%q<rake>, ["~> 0.8.7"])
47
+ s.add_dependency(%q<shoulda>, ["~> 2.11.3"])
48
+ s.add_dependency(%q<mocha>, ["~> 0.9.8"])
49
+ end
50
+ end
51
+
@@ -1,20 +1,36 @@
1
- require 'completeness-fu/active_record_additions'
2
- require 'completeness-fu/scoring_builder'
1
+ module CompletenessFu
2
+ class CompletenessFuError < RuntimeError; end
3
3
 
4
- module ActiveRecord
5
- Base.class_eval do
6
- include CompletenessFu::ActiveRecordAdditions
4
+ class << self
5
+ attr_accessor :common_weightings
6
+ attr_accessor :default_weighting
7
+ attr_accessor :default_i18n_namespace
8
+ attr_accessor :default_gradings
7
9
  end
8
- end
9
10
 
11
+ self.common_weightings = { :low => 20, :medium => 40, :high => 60 }
12
+
13
+ self.default_weighting = 40
10
14
 
11
- CompletenessFu.common_weightings = { :low => 20, :medium => 40, :high => 60 }
15
+ self.default_i18n_namespace = [:completeness_scoring, :models]
12
16
 
13
- CompletenessFu.default_weighting = 40
17
+ self.default_gradings = {
18
+ :poor => 0..24,
19
+ :low => 25..49,
20
+ :medium => 50..79,
21
+ :high => 80..100
22
+ }
23
+
24
+ def self.setup_orm(orm_class)
25
+ orm_class.class_eval { include CompletenessFu::ActiveModelAdditions }
26
+ end
27
+
28
+ end
29
+
30
+ require 'completeness-fu/active_model_additions'
31
+ require 'completeness-fu/scoring_builder'
14
32
 
15
- CompletenessFu.default_i18n_namespace = [:completeness_scoring, :models]
16
33
 
17
- CompletenessFu.default_gradings = { :poor => 0..24,
18
- :low => 25..49,
19
- :medium => 50..79,
20
- :high => 80..100 }
34
+ CompletenessFu.setup_orm(::ActiveRecord::Base) if defined?(::ActiveRecord::Base)
35
+ CompletenessFu.setup_orm(::CassandraObject::Base) if defined?(::CassandraObject::Base)
36
+ CompletenessFu.setup_orm(::Mongoid::Document) if defined?(::Mongoid::Document)
@@ -1,86 +1,90 @@
1
+ require 'active_support/core_ext/class/inheritable_attributes'
2
+ require 'active_support/core_ext/class/attribute_accessors'
3
+
1
4
  module CompletenessFu
2
-
3
- class << self
4
- attr_accessor :common_weightings
5
- attr_accessor :default_weighting
6
- attr_accessor :default_i18n_namespace
7
- attr_accessor :default_gradings
8
- end
9
-
10
- class CompletenessFuError < Exception; end
11
-
12
- module ActiveRecordAdditions
13
-
5
+
6
+ module ActiveModelAdditions
7
+
14
8
  def self.included(base)
15
9
  base.class_eval do
16
10
  def self.define_completeness_scoring(&checks_block)
11
+ unless self.include?(ActiveModel::Naming)
12
+ raise CompletenessFuError, 'please make sure ActiveModel::Naming is included so completeness_scoring can translate messages correctly'
13
+ end
14
+
17
15
  class_inheritable_array :completeness_checks
18
16
  cattr_accessor :default_weighting
19
17
  cattr_accessor :model_weightings
20
-
18
+
21
19
  self.send :extend, ClassMethods
22
20
  self.send :include, InstanceMethods
23
-
21
+
24
22
  checks_results = CompletenessFu::ScoringBuilder.generate(self, &checks_block)
25
-
23
+
26
24
  self.default_weighting = checks_results[:default_weighting]
27
25
  self.completeness_checks = checks_results[:completeness_checks]
28
26
  self.model_weightings = checks_results[:model_weightings]
29
- self.before_validation checks_results[:cache_score_details] if checks_results[:cache_score_details]
27
+
28
+ if checks_results[:cache_score_details]
29
+ unless self.include?(ActiveModel::Validations::Callbacks)
30
+ raise CompletenessFuError, 'please make sure ActiveModel::Validations::Callbacks is included before define_completeness_scoring if you want to cache competeness scoring'
31
+ end
32
+ self.before_validation checks_results[:cache_score_details]
33
+ end
30
34
  end
31
35
  end
32
36
  end
33
-
34
-
37
+
38
+
35
39
  module ClassMethods
36
40
  def max_completeness_score
37
41
  self.completeness_checks.inject(0) { |score, check| score += check[:weighting] }
38
42
  end
39
43
  end
40
-
41
-
44
+
45
+
42
46
  module InstanceMethods
43
47
  # returns an array of hashes with the translated name, description + weighting
44
48
  def failed_checks
45
49
  all_checks_which_pass(false)
46
50
  end
47
-
51
+
48
52
  # returns an array of hashes with the translated name, description + weighting
49
53
  def passed_checks
50
54
  all_checks_which_pass
51
55
  end
52
-
56
+
53
57
  # returns the absolute complete score
54
58
  def completeness_score
55
59
  sum_score = 0
56
60
  passed_checks.each { |check| sum_score += check[:weighting] }
57
61
  sum_score
58
62
  end
59
-
63
+
60
64
  # returns the percentage of completeness (relative score)
61
65
  def percent_complete
62
66
  self.completeness_score.to_f / self.class.max_completeness_score.to_f * 100
63
67
  end
64
-
68
+
65
69
  # returns a basic 'grading' based on percent_complete, defaults are :high, :medium, :low, and :poor
66
70
  def completeness_grade
67
- CompletenessFu.default_gradings.each do |grading|
68
- return grading.first if grading.last.include?(self.percent_complete.round)
71
+ CompletenessFu.default_gradings.each do |grading|
72
+ return grading.first if grading.last.include?(self.percent_complete.round)
69
73
  end
70
74
  raise CompletenessFuError, "grade could not be determined with percent complete #{self.percent_complete.round}"
71
75
  end
72
-
73
-
74
- private
75
-
76
+
77
+
78
+ private
79
+
76
80
  def all_checks_which_pass(should_pass = true)
77
81
  self.completeness_checks.inject([]) do |results, check|
78
- check_result = run_check(check[:check])
82
+ check_result = run_check(check[:check])
79
83
  results << translate_check_details(check) if (should_pass ? check_result : !check_result)
80
84
  results
81
85
  end
82
86
  end
83
-
87
+
84
88
  def run_check(check)
85
89
  case check
86
90
  when Proc
@@ -91,18 +95,18 @@ module CompletenessFu
91
95
  raise CompletenessFuError, "check of type #{check.class} not acceptable"
92
96
  end
93
97
  end
94
-
98
+
95
99
  def translate_check_details(full_check)
96
- namespace = CompletenessFu.default_i18n_namespace + [self.class.name.downcase.to_sym, full_check[:name]]
97
-
100
+ namespace = CompletenessFu.default_i18n_namespace + [self.class.model_name.underscore.to_sym, full_check[:name]]
101
+
98
102
  translations = [:title, :description, :extra].inject({}) do |list, field|
99
103
  list[field] = I18n.t(field.to_sym, :scope => namespace)
100
104
  list
101
105
  end
102
-
106
+
103
107
  full_check.merge(translations)
104
108
  end
105
-
109
+
106
110
  def cache_completeness_score(score_type)
107
111
  score = case score_type
108
112
  when :relative
@@ -116,7 +120,7 @@ module CompletenessFu
116
120
  true
117
121
  end
118
122
  end
119
-
123
+
120
124
  end
121
-
125
+
122
126
  end
@@ -0,0 +1,138 @@
1
+ Welcome to Completeness-Fu
2
+ ==========================
3
+
4
+ In short, completeness-fu for ActiveModel allows you cleanly define the way a model instance is scored for completeness, similar to LinkedIn user profiles.
5
+
6
+
7
+ When should I use it?
8
+ ---------------------
9
+
10
+ When you want your objects/models/instances to be of a certain standard, if it be data presence, format or what values are allowed and not allowed,
11
+ before an object can be saved or updated then you use validations. But when you want to allow more information to be entered, thus relaxing some
12
+ of the validation rules and prompt the user to enrich the data, then completeness-fu is your cup of tea.
13
+
14
+ Take an events web site for example, you may want to import information from various sources which might have varied data quality.
15
+ If your validations are too strict then the information won't import, but if you relax your validations too much then you risk
16
+ having quantity but not quality. What you can do is relax the validations and add some quality checks which calculate a score
17
+ which is then used to determine if the event information is shown on the public site or is listed in the admin panel prompting
18
+ staff to enrich the data before it is made public.
19
+
20
+
21
+ What does it work with?
22
+ -----------------------
23
+
24
+ Completeness-Fu used to be for ActiveRecord only, but this has changed with the latest version with only ActiveModel needed as a gem dependency (and a little ActiveSupport). This means that the latest version works with the following ORMs :
25
+
26
+ - ActiveRecord
27
+
28
+ - Mongoid
29
+
30
+ - Cassandra Object
31
+
32
+ The `define_completeness_scoring` method is mixed into the above mentioned ORMs by default, but if you want to use Completeness-Fu in an ActiveModel model which isn't one of the above ORMs, make sure you include `ActiveModel::Naming`. If you want to cache the completeness score make sure you also include `ActiveModel::Validations` and `ActiveModel::Validations::Callbacks`.
33
+
34
+
35
+ How do I use it?
36
+ ----------------
37
+
38
+ If you want your model to only be regarded as complete if it has a title, description, and picture, you can do the following:
39
+
40
+ define_completeness_scoring do
41
+ check :title, lambda { |per| per.title.present? }, :high
42
+ check :description, lambda { |per| per.description.present? }, :medium
43
+ check :main_image, lambda { |per| per.main_image? }, :low
44
+ end
45
+
46
+ You also get the following methods for free on the model instance : _passed\_checks_, _failed\_checks_, _completeness\_score_, _percent\_complete_.
47
+
48
+ You can add the following to an initializer to set some defaults:
49
+
50
+ CompletenessFu.common_weights = { :low => 30, :medium => 50, :high => 70 }
51
+
52
+ CompletenessFu.default_weighting = :medium
53
+
54
+ `weights` and `default_weighting` can be changed per model, and you can use symbols for the checks instead of lambdas, thus allowing you to place check logic as methods in your class (public or private).
55
+
56
+ define_completeness_scoring do
57
+ weights :low => 30, :super_high => 60
58
+ default_weighting :medium
59
+
60
+ check :title, lambda { |per| per.title.present? }, :super_high
61
+ check :description, :description_present?
62
+ check :main_image, :main_image_or_pretty_picture?, :low
63
+ end
64
+
65
+ And if you want to cache the score to a field so you can use it in database searches you just have to add the following:
66
+
67
+ define_completeness_scoring do
68
+ cache_score :absolute # the default is :relative
69
+
70
+ check :title, lambda { |per| per.title.present? }, :super_high
71
+ check :description, :description_present?
72
+ end
73
+
74
+ If you are not using one of the above ORMs, make sure `ActiveModel::Validations` and `ActiveModel::Validations::Callbacks` are included.
75
+
76
+
77
+ Passed checks, Failed checks and i18n
78
+ ----------------------------------------
79
+
80
+ Both the _passed\_checks_ and _failed\_checks_ methods return an array of hashes with extended information about the check.
81
+ The check hash includes a translated title, description and extra information which is based on the name of the check.
82
+ The translation structure is as such:
83
+
84
+ en:
85
+ completeness_scoring:
86
+ models:
87
+ my_model_name:
88
+ name_of_check:
89
+ title: 'Title'
90
+ description: 'The Check Description'
91
+ extra: 'Extra Info'
92
+
93
+
94
+ Up and coming features
95
+ ----------------------
96
+
97
+ - enhance caching so filter type can be changed and field to save score to can be customized
98
+ - ability to 'share' common lambdas
99
+ - better docs
100
+ - increase test coverage (error edge cases, ORM inclusion)
101
+
102
+
103
+ Change Log
104
+ ----------
105
+
106
+ 4 Sep 10
107
+
108
+ - added bundler for development and testing
109
+ - make the plugin ORM agnostic, only ActiveModel is required
110
+
111
+ 15 Oct 09
112
+
113
+ - bug fix for failed checks when check is a symbol to a method
114
+ - bug fix for grading (percent complete needed to be rounded)
115
+ - change of CompletenessFu.default\_weightings to CompletenessFu.default\_weighting
116
+ - change of CompletenessFu.default\_grading to CompletenessFu.default\_gradings
117
+
118
+ 29 Sep 09
119
+
120
+ - added a 'grading' method which returns either :poor, :low, :medium or :high based on its percentage complete
121
+ - added ability to customize the default translations namespace using CompletenessFu.default\_i18n\_namespace
122
+
123
+ 28 Sep 09
124
+
125
+ - move the scoring check builder into its own class so that it works within a clean room
126
+
127
+ 24 Sep 09
128
+
129
+ - options to save the score to a field (caching) - good for searching on
130
+ - define methods on the class to use in the checks
131
+
132
+
133
+
134
+ Contributors
135
+ ------------
136
+
137
+ - Peter (pero-ict)
138
+ - Andrew Brown (omenking)
@@ -1,7 +1,7 @@
1
1
  en:
2
2
  completeness_scoring:
3
3
  models:
4
- scoringtest:
4
+ scoring_test:
5
5
  title:
6
6
  title: 'Title'
7
7
  description: 'The Scoring Test Description'
@@ -1,56 +1,37 @@
1
- require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
4
- require 'mocha'
5
-
6
- require 'active_record'
7
- require 'action_controller'
8
-
9
1
  begin
10
- require 'ruby-debug'
2
+ require 'bundler/setup'
11
3
  rescue LoadError
12
- puts "ruby-debug not loaded"
4
+ puts 'although not required, its recommended you use bundler when running the tests'
13
5
  end
14
6
 
15
- ROOT = File.join(File.dirname(__FILE__), '..')
7
+ require 'test/unit'
8
+ require 'shoulda'
9
+ require 'mocha'
16
10
 
17
- $LOAD_PATH << File.join(ROOT, 'lib')
18
- $LOAD_PATH << File.join(ROOT, 'lib', 'completeness-fu')
11
+ require 'active_model'
19
12
 
20
- require File.join(ROOT, 'lib', 'completeness-fu.rb')
13
+ require 'completeness-fu'
21
14
 
22
15
 
23
- TEST_DATABASE_FILE = File.join(ROOT, 'test', 'test.sqlite3')
16
+ ROOT = File.join(File.dirname(__FILE__), '..')
24
17
 
25
- File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
26
- ActiveRecord::Base.establish_connection(
27
- "adapter" => "sqlite3", "database" => TEST_DATABASE_FILE
28
- )
18
+ I18n.load_path << File.join(ROOT, 'test', 'en.yml')
29
19
 
30
- RAILS_DEFAULT_LOGGER = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
31
20
 
32
- load(File.dirname(__FILE__) + '/schema.rb')
21
+ def rebuild_class(class_name)
22
+ Object.send(:remove_const, class_name) rescue nil
33
23
 
24
+ klass = Object.const_set(class_name, Class.new)
34
25
 
35
- I18n.load_path << File.join(ROOT, 'test', 'en.yml')
26
+ klass.class_eval do
27
+ include ActiveModel::Naming
28
+ include ActiveModel::Validations
29
+ include ActiveModel::Validations::Callbacks
36
30
 
31
+ include CompletenessFu::ActiveModelAdditions
37
32
 
38
- def rebuild_class options = {}
39
- ActiveRecord::Base.send(:include, CompletenessFu::ActiveRecordAdditions)
40
- Object.send(:remove_const, "ScoringTest") rescue nil
41
- Object.const_set("ScoringTest", Class.new(ActiveRecord::Base))
42
- ScoringTest.class_eval do
43
- include CompletenessFu::ActiveRecordAdditions
44
- define_completeness_scoring do
45
- check :title, lambda { |test| test.title.present? }, 20
46
- end
33
+ attr_accessor :title
47
34
  end
48
- end
49
35
 
50
- def reset_class class_name
51
- ActiveRecord::Base.send(:include, CompletenessFu::ActiveRecordAdditions)
52
- Object.send(:remove_const, class_name) rescue nil
53
- klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
54
- klass.class_eval{ include CompletenessFu::ActiveRecordAdditions }
55
36
  klass
56
- end
37
+ end
@@ -1,153 +1,146 @@
1
1
  # encoding: utf-8
2
2
  require 'test/helper'
3
3
 
4
-
5
4
  class ScoringTest < Test::Unit::TestCase
6
-
7
- context "An ActiveRecord child class" do
5
+
6
+ context "A class which includes ActiveModel" do
7
+ setup { rebuild_class('ScoringTest') }
8
+
8
9
  should "have a define_completeness_scoring mixed in" do
9
- reset_class 'ScoringTest'
10
10
  assert ScoringTest.methods.include?('define_completeness_scoring')
11
11
  end
12
12
  end
13
-
14
-
13
+
15
14
  context "A class with scoring defined" do
16
15
  setup do
17
- reset_class 'ScoringTest'
18
- ScoringTest.class_eval do
16
+ klass = rebuild_class('ScoringTest')
17
+ klass.class_eval do
19
18
  define_completeness_scoring do
20
19
  check :title, lambda { |test| test.title.present? }, 20
21
20
  end
22
21
  end
23
22
  end
24
-
23
+
25
24
  should "have one scoring check" do
26
25
  assert_equal 1, ScoringTest.completeness_checks.size
27
26
  end
28
-
27
+
29
28
  should "have one failed check" do
30
29
  st = ScoringTest.new
31
30
  assert_equal 1, st.failed_checks.size
32
31
  end
33
-
34
-
32
+
35
33
  context "and with one complete check" do
36
34
  setup do
37
35
  @st = ScoringTest.new
38
36
  @st.title = 'I have a title'
39
37
  end
40
-
38
+
41
39
  should "have an absolute completeness score of 20" do
42
40
  assert_equal 20, @st.completeness_score
43
41
  end
44
-
42
+
45
43
  should "have a relative completeness score of 0 (percent complete)" do
46
44
  assert_equal 100, @st.percent_complete
47
45
  end
48
-
46
+
49
47
  should "have a description" do
50
48
  assert_equal "The Scoring Test Description", @st.passed_checks.first[:description]
51
49
  end
52
50
  end
53
51
  end
54
-
55
-
52
+
56
53
  context "A class with scoring defined with no weighting" do
57
54
  setup do
58
- reset_class 'ScoringTest'
59
- ScoringTest.class_eval do
55
+ klass = rebuild_class('ScoringTest')
56
+ klass.class_eval do
60
57
  define_completeness_scoring do
61
58
  check :title, lambda { |test| test.title.present? }
62
59
  end
63
60
  end
64
- @st = ScoringTest.new
61
+ @st = klass.new
65
62
  @st.title = 'I have a title'
66
63
  end
67
-
64
+
68
65
  should "have the default scoring used" do
69
66
  assert_equal 40, @st.completeness_score
70
67
  end
71
68
  end
72
69
 
73
-
74
70
  context "A class with scoring defined with a symbol weighting" do
75
71
  setup do
76
- reset_class 'ScoringTest'
77
- ScoringTest.class_eval do
72
+ klass = rebuild_class('ScoringTest')
73
+ klass.class_eval do
78
74
  define_completeness_scoring do
79
75
  check :title, lambda { |test| test.title.present? }, :high
80
76
  end
81
77
  end
82
- @st = ScoringTest.new
78
+ @st = klass.new
83
79
  @st.title = 'I have a title'
84
80
  end
85
-
81
+
86
82
  should "have a scoring from the common_weightings hash used used" do
87
83
  assert_equal ScoringTest.model_weightings[:high], @st.completeness_score
88
84
  end
89
85
  end
90
-
91
-
86
+
92
87
  context "A class with scoring defined with a custom weighting" do
93
88
  setup do
94
- reset_class 'ScoringTest'
95
- ScoringTest.class_eval do
89
+ klass = rebuild_class('ScoringTest')
90
+ klass.class_eval do
96
91
  define_completeness_scoring do
97
92
  weightings :super_high => 80
98
93
  check :title, lambda { |test| test.title.present? }, :super_high
99
94
  end
100
95
  end
101
- @st = ScoringTest.new
96
+ @st = klass.new
102
97
  @st.title = 'I have a title'
103
98
  end
104
-
99
+
105
100
  should "have a scoring from the common_weightings hash used used" do
106
101
  assert_equal ScoringTest.model_weightings[:super_high], @st.completeness_score
107
102
  end
108
103
  end
109
-
110
-
104
+
111
105
  context "A class with scoring defined with a custom weighting and no common weightings" do
112
106
  setup do
113
- reset_class 'ScoringTest'
114
- ScoringTest.class_eval do
107
+ klass = rebuild_class('ScoringTest')
108
+ klass.class_eval do
115
109
  define_completeness_scoring do
116
110
  weightings :super_high => 80 , :merge_with_common => false
117
111
  check :title, lambda { |test| test.title.present? }, :super_high
118
112
  end
119
113
  end
120
- @st = ScoringTest.new
114
+ @st = klass.new
121
115
  @st.title = 'I have a title'
122
116
  end
123
-
117
+
124
118
  should "have a scoring from the common_weightings hash used used" do
125
119
  assert_equal nil, ScoringTest.model_weightings[:high]
126
120
  assert_equal ScoringTest.model_weightings[:super_high], @st.completeness_score
127
121
  end
128
122
  end
129
-
130
-
123
+
131
124
  context "A class with scoring defined with a check using a symbol to a private method" do
132
125
  setup do
133
- reset_class 'ScoringTest'
134
- ScoringTest.class_eval do
126
+ klass = rebuild_class('ScoringTest')
127
+ klass.class_eval do
135
128
  define_completeness_scoring do
136
129
  check :title, :title_present?, :high
137
130
  check :name, :name_present?, :high
138
131
  end
139
132
 
140
133
  private
141
- def title_present?
142
- self.title.present?
143
- end
144
134
 
145
- def name_present?
146
- false
147
- end
135
+ def title_present?
136
+ self.title.present?
137
+ end
148
138
 
139
+ def name_present?
140
+ false
141
+ end
149
142
  end
150
- @st = ScoringTest.new
143
+ @st = klass.new
151
144
  @st.title = 'I have a title'
152
145
  end
153
146
 
@@ -164,45 +157,45 @@ class ScoringTest < Test::Unit::TestCase
164
157
  end
165
158
 
166
159
  end
167
-
168
-
160
+
169
161
  context "A class with scoring defined and cache to field directive" do
170
162
  setup do
171
- reset_class 'ScoringTest'
172
- ScoringTest.class_eval do
163
+ klass = rebuild_class('ScoringTest')
164
+ klass.class_eval do
173
165
  define_completeness_scoring do
174
166
  cache_score :absolute
175
167
  check :title, :title_present?, :high
176
168
  end
177
-
169
+
170
+ attr_accessor :cached_completeness_score
171
+
178
172
  private
179
- def title_present?
180
- self.title.present?
181
- end
173
+ def title_present?
174
+ self.title.present?
175
+ end
182
176
  end
183
- @st = ScoringTest.new
177
+ @st = klass.new
184
178
  @st.title = 'I have a title'
185
179
  end
186
-
180
+
187
181
  should "have a before filter added, and save the defined calculation to the default field" do
188
182
  assert_equal nil, @st.cached_completeness_score
189
183
  @st.valid?
190
184
  assert_equal @st.completeness_score, @st.cached_completeness_score
191
185
  end
192
186
  end
193
-
194
-
187
+
195
188
  context "A class with scoring" do
196
189
  setup do
197
- reset_class 'ScoringTest'
198
- ScoringTest.class_eval do
190
+ klass = rebuild_class('ScoringTest')
191
+ klass.class_eval do
199
192
  define_completeness_scoring do
200
193
  check :title, lambda { |test| test.title.present? }, :high
201
194
  end
202
195
  end
203
- @st = ScoringTest.new
196
+ @st = klass.new
204
197
  end
205
-
198
+
206
199
  should "have a grade of :high" do
207
200
  assert_equal :poor, @st.completeness_grade
208
201
  @st.title = 'I have a title'
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completeness-fu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ hash: 7
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Josh Kalderimis
@@ -9,33 +15,95 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-10-20 00:00:00 +02:00
18
+ date: 2011-03-29 00:00:00 +02:00
13
19
  default_executable:
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
- name: activerecord
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ none: false
20
24
  requirements:
21
- - - ">="
25
+ - - ~>
22
26
  - !ruby/object:Gem::Version
23
- version: 2.3.3
24
- version:
25
- description:
27
+ hash: 7
28
+ segments:
29
+ - 3
30
+ - 0
31
+ - 0
32
+ version: 3.0.0
33
+ prerelease: false
34
+ type: :development
35
+ requirement: *id001
36
+ name: activemodel
37
+ - !ruby/object:Gem::Dependency
38
+ version_requirements: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 49
44
+ segments:
45
+ - 0
46
+ - 8
47
+ - 7
48
+ version: 0.8.7
49
+ prerelease: false
50
+ type: :development
51
+ requirement: *id002
52
+ name: rake
53
+ - !ruby/object:Gem::Dependency
54
+ version_requirements: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 37
60
+ segments:
61
+ - 2
62
+ - 11
63
+ - 3
64
+ version: 2.11.3
65
+ prerelease: false
66
+ type: :development
67
+ requirement: *id003
68
+ name: shoulda
69
+ - !ruby/object:Gem::Dependency
70
+ version_requirements: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ hash: 43
76
+ segments:
77
+ - 0
78
+ - 9
79
+ - 8
80
+ version: 0.9.8
81
+ prerelease: false
82
+ type: :development
83
+ requirement: *id004
84
+ name: mocha
85
+ description: Simple dsl for defining how to calculate how complete a model instance is (similar to LinkedIn profile completeness)
26
86
  email: josh.kalderimis@gmail.com
27
87
  executables: []
28
88
 
29
89
  extensions: []
30
90
 
31
- extra_rdoc_files: []
32
-
91
+ extra_rdoc_files:
92
+ - readme.markdown
33
93
  files:
94
+ - .gitignore
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - Rakefile
34
98
  - VERSION.yml
35
- - init.rb
99
+ - completeness-fu.gemspec
36
100
  - lib/completeness-fu.rb
37
- - lib/completeness-fu/active_record_additions.rb
101
+ - lib/completeness-fu/active_model_additions.rb
38
102
  - lib/completeness-fu/scoring_builder.rb
103
+ - readme.markdown
104
+ - test/en.yml
105
+ - test/helper.rb
106
+ - test/scoring_test.rb
39
107
  has_rdoc: true
40
108
  homepage: http://github.com/joshk/completeness-fu
41
109
  licenses: []
@@ -46,28 +114,31 @@ rdoc_options:
46
114
  require_paths:
47
115
  - lib
48
116
  required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
49
118
  requirements:
50
119
  - - ">="
51
120
  - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
52
124
  version: "0"
53
- version:
54
125
  required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
55
127
  requirements:
56
128
  - - ">="
57
129
  - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
58
133
  version: "0"
59
- version:
60
134
  requirements: []
61
135
 
62
136
  rubyforge_project:
63
- rubygems_version: 1.3.5
137
+ rubygems_version: 1.5.0
64
138
  signing_key:
65
139
  specification_version: 3
66
140
  summary: Simple dsl for defining how to calculate how complete a model instance is (similar to LinkedIn profile completeness)
67
141
  test_files:
68
- - test/debug.log
69
142
  - test/en.yml
70
143
  - test/helper.rb
71
- - test/schema.rb
72
144
  - test/scoring_test.rb
73
- - test/test.sqlite3
data/init.rb DELETED
@@ -1 +0,0 @@
1
- require 'completeness-fu'
@@ -1 +0,0 @@
1
- # Logfile created on Wed Sep 23 14:40:19 +0200 2009 by logger.rb/22285
@@ -1,6 +0,0 @@
1
- ActiveRecord::Schema.define :version => 0 do
2
- create_table "scoring_tests", :force => true do |t|
3
- t.string :title
4
- t.string :cached_completeness_score
5
- end
6
- end
Binary file