completeness 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZmU0MmJjYzY0N2E0NTZkODdjM2IzYTMzNGM2ODhjNTIwMzM0M2RkYg==
5
+ data.tar.gz: !binary |-
6
+ NmFhYjU1YzU4ODc3ODM5ZWE0MjE0NzliMjVjMGRhNjk2NjQyNWVhNw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MTFkYWJhNmIzNDM1Zjg0ZTYwNWRhMTA5ZDQyNDQ4OTkxYTg2NTYzMjAyMDE4
10
+ NGU2OWZjNGMzMWVhM2I3MmJhOTE4NDdmOGFhZDExNTkwZDMyNmZmOTE4YzU5
11
+ ODBmMjczNTU1ZTY4MzI3NDUzMzIwYmEwZmE5NTQyMGM5MGYyY2Y=
12
+ data.tar.gz: !binary |-
13
+ NGM0YTdhYjJiYzdiNjYzOGEwMzViNzVlZDdhN2U1Y2UzN2E2OGE1ZGU4ZGJl
14
+ MmU1M2VjY2UxYjU2NzJlOGUyYzQyOWNiMzBlOTVkOWJmZWIzZjQ0YjgzM2I4
15
+ OWZkMTcxYWQ5ZDBhZDRmMTk1NTY1MjdkYmI4MjE2MWJjMzU3NjI=
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --drb
3
+ --backtrace
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in completeness.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 undr
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,56 @@
1
+ # Completeness
2
+
3
+ Completeness is a way to add completeness progress (like in LinkedIn) into your application.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'completeness'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install completeness
18
+
19
+ ## Usage
20
+
21
+ It's extremely simple. Add `Completeness::Model` module into your model and define weights for each attribute.
22
+
23
+ ```ruby
24
+ class MyModel < Struct.new(:name, :email, :phone, :desctiption, :dob)
25
+ include Completeness::Model
26
+
27
+ completeness weight: 20 do
28
+ field :name, required: true
29
+ field :email, weight: 15, required: true
30
+ field :phone, weight: 15
31
+ field :description, weight: 5
32
+ field :dob, weight: 10, check: ->(object, value){ value.is_a?(Date) && value.past? }
33
+ end
34
+ end
35
+ ```
36
+
37
+ It will add into your model these methods
38
+
39
+ - `completeness_spec` - this is the `Completeness::Specification` object which contains all specification for the model. See [specification.rb](lib/completeness/specification.rb) for more details.
40
+ - `completed?` - it returns `true` if all required attributes are completely filled, otherwise returns `false`.
41
+ - `completed_percent` - it returns percentage of completeness the object. It will be integer value between 0 and 100.
42
+ - `completed_weight` - it returns summary weight of all attributes what was being completed.
43
+
44
+ The method `completeness` can take an options hash. It's default options for all fields what will be defined in the block. Available options are:
45
+
46
+ - `:weight` - default weight.
47
+ - `:required` - set `true` if you are going to mark all fields as required.
48
+ - `:check` - lambda or another object which respond to `call`. It rewrites of completeness check method. You can define a custom method. It should take two arguments (object and checked value) and return `true` or `false`. Default method is `->(obj, value){ value.present? }`.
49
+
50
+ ## Contributing
51
+
52
+ 1. Fork it
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create new Pull Request
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task :default => [:spec]
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'completeness/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "completeness"
8
+ spec.version = Completeness::VERSION
9
+ spec.authors = ["undr"]
10
+ spec.email = ["undr@yandex.ru"]
11
+ spec.description = %q{Completeness is a way to add completeness progress (like in LinkedIn) into your application.}
12
+ spec.summary = %q{Completeness is a way to add completeness progress (like in LinkedIn) into your application.}
13
+ spec.homepage = "https://github.com/undr/completeness"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+
22
+ spec.add_dependency "activesupport"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency 'pry'
26
+ spec.add_development_dependency 'rspec'
27
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_support/all'
2
+ require 'completeness/version'
3
+ require 'completeness/field'
4
+ require 'completeness/specification'
5
+ require 'completeness/dsl'
6
+ require 'completeness/model'
7
+
8
+ module Completeness
9
+ end
@@ -0,0 +1,19 @@
1
+ module Completeness
2
+ class DSL
3
+ def initialize(options = {}, &block)
4
+ @default_options = options
5
+ instance_eval(&block)
6
+ end
7
+
8
+ def field(name, options = {})
9
+ spec[name] = Field.new(spec, name, default_options.merge(options))
10
+ end
11
+
12
+ def spec
13
+ @spec ||= Specification.new
14
+ end
15
+
16
+ private
17
+ attr_reader :default_options
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ module Completeness
2
+ class Field
3
+ DEFAULT_WEIGHT = 10
4
+
5
+ attr_reader :spec, :name, :options
6
+
7
+ def initialize(spec, name, options = {})
8
+ @spec = spec
9
+ @name = name
10
+ @options = options
11
+ end
12
+
13
+ def required?
14
+ !!options[:required]
15
+ end
16
+
17
+ def completed?(object)
18
+ completeness_check.call(object, object.send(name))
19
+ end
20
+
21
+ def weight
22
+ options[:weight] || DEFAULT_WEIGHT
23
+ end
24
+
25
+ def <=>(other)
26
+ return 1 if required? && !other.required?
27
+ return -1 if !required? && other.required?
28
+ weight <=> other.weight
29
+ end
30
+
31
+ def weight_in_percent
32
+ (weight / (spec.total_weight / 100.0)).round
33
+ end
34
+
35
+ def completeness_check
36
+ if options[:check].present? && options[:check].respond_to?(:call)
37
+ options[:check]
38
+ else
39
+ ->(obj, value){ value.present? }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,31 @@
1
+ module Completeness
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ cattr_accessor :completeness_spec
7
+ end
8
+
9
+ module ClassMethods
10
+ def completeness(options = {}, &block)
11
+ self.completeness_spec = DSL.new(options, &block).spec
12
+ end
13
+ end
14
+
15
+ def completeness_spec
16
+ self.class.completeness_spec
17
+ end
18
+
19
+ def completed?
20
+ completeness_spec.completed?(self)
21
+ end
22
+
23
+ def completed_percent
24
+ completeness_spec.completed_percent(self)
25
+ end
26
+
27
+ def completed_weight
28
+ completeness_spec.completed_weight(self)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,59 @@
1
+ module Completeness
2
+ class Specification
3
+ attr_reader :attributes
4
+
5
+ def initialize
6
+ @attributes = {}
7
+ end
8
+
9
+ def [](key)
10
+ attributes[key]
11
+ end
12
+
13
+ def []=(key, value)
14
+ attributes[key] = value
15
+ end
16
+
17
+ def all_attributes
18
+ @all_attributes ||= attributes.values
19
+ end
20
+
21
+ def required_attributes
22
+ all_attributes.select(&:required?)
23
+ end
24
+
25
+ def total_weight
26
+ all_attributes.sum(&:weight)
27
+ end
28
+
29
+ def recomend_next_attribute_for(object)
30
+ weighted_uncompleted_attributes_for(object).first
31
+ end
32
+
33
+ def weighted_uncompleted_attributes_for(object)
34
+ uncompleted_attributes_for(object).sort.reverse
35
+ end
36
+
37
+ def completed_weight(object)
38
+ completed_attributes_for(object).sum(&:weight)
39
+ end
40
+
41
+ def completed_percent(object)
42
+ (completed_weight(object) / (total_weight / 100.0)).round
43
+ end
44
+
45
+ def completed?(object)
46
+ required_attributes.all?{|attribute| attribute.completed?(object)}
47
+ end
48
+
49
+ private
50
+
51
+ def completed_attributes_for(object)
52
+ all_attributes.select{|attribute| attribute.completed?(object) }
53
+ end
54
+
55
+ def uncompleted_attributes_for(object)
56
+ all_attributes.reject{|attribute| attribute.completed?(object) }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module Completeness
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Completeness::DSL do
4
+ describe '#field' do
5
+ let(:dsl){ Completeness::DSL.new(options){} }
6
+
7
+ subject{ dsl.spec.attributes[:name] }
8
+
9
+ before{ dsl.field(:name, weight: 15) }
10
+
11
+ context 'without global options' do
12
+ let(:options){ {} }
13
+
14
+ its(:name){ should eq(:name) }
15
+ its(:options){ should eq(weight: 15) }
16
+ its(:spec){ should eq(dsl.spec) }
17
+ end
18
+
19
+ context 'with global options' do
20
+ let(:options){ { required: true, weight: 20 } }
21
+
22
+ its(:name){ should eq(:name) }
23
+ its(:options){ should eq(required: true, weight: 15) }
24
+ its(:spec){ should eq(dsl.spec) }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ describe Completeness::Field do
4
+ describe '#required?' do
5
+ subject{ Completeness::Field.new(nil, :name) }
6
+
7
+ specify{ expect(subject.required?).to be_false }
8
+
9
+ context 'when :required equals to nil' do
10
+ subject{ Completeness::Field.new(nil, :name, required: nil) }
11
+ specify{ expect(subject.required?).to be_false }
12
+ end
13
+
14
+ context 'when :required equals to false' do
15
+ subject{ Completeness::Field.new(nil, :name, required: false) }
16
+ specify{ expect(subject.required?).to be_false }
17
+ end
18
+
19
+ context 'when :required equals to true' do
20
+ subject{ Completeness::Field.new(nil, :name, required: true) }
21
+ specify{ expect(subject.required?).to be_true }
22
+ end
23
+
24
+ context 'when :required equals to some object' do
25
+ subject{ Completeness::Field.new(nil, :name, required: '') }
26
+ specify{ expect(subject.required?).to be_true }
27
+ end
28
+ end
29
+
30
+ describe '#completed?' do
31
+ let(:object){ double(:object, name: name) }
32
+ let(:options){ {} }
33
+
34
+ subject{ Completeness::Field.new(nil, :name, options) }
35
+
36
+ context 'with default behavior' do
37
+ context 'when value is nil' do
38
+ let(:name){ nil }
39
+ specify{ expect(subject.completed?(object)).to be_false }
40
+ end
41
+
42
+ context 'when value is blank object' do
43
+ let(:name){ '' }
44
+ specify{ expect(subject.completed?(object)).to be_false }
45
+ end
46
+
47
+ context 'when value is present object' do
48
+ let(:name){ 'object' }
49
+ specify{ expect(subject.completed?(object)).to be_true }
50
+ end
51
+ end
52
+
53
+ context 'with passed completeness check' do
54
+ let(:options){ { check: ->(o, v){
55
+ expect(o).to eq(object)
56
+ expect(v).to eq(name)
57
+ !v.nil?
58
+ } } }
59
+
60
+ context 'when value is nil' do
61
+ let(:name){ nil }
62
+ specify{ expect(subject.completed?(object)).to be_false }
63
+ end
64
+
65
+ context 'when value is blank object' do
66
+ let(:name){ '' }
67
+ specify{ expect(subject.completed?(object)).to be_true }
68
+ end
69
+
70
+ context 'when value is present object' do
71
+ let(:name){ 'object' }
72
+ specify{ expect(subject.completed?(object)).to be_true }
73
+ end
74
+ end
75
+ end
76
+
77
+ describe '#weight' do
78
+ let(:options){ { weight: 120 } }
79
+
80
+ subject{ Completeness::Field.new(nil, :name, options) }
81
+
82
+ specify{ expect(subject.weight).to eq(120) }
83
+
84
+ context 'with default behavior' do
85
+ let(:options){ {} }
86
+ specify{ expect(subject.weight).to eq(Completeness::Field::DEFAULT_WEIGHT) }
87
+ end
88
+ end
89
+
90
+ describe '#<=>' do
91
+ let(:other){ Completeness::Field.new(nil, :other, options) }
92
+
93
+ subject{ Completeness::Field.new(nil, :name) }
94
+
95
+ context 'when other is required field' do
96
+ let(:options){ { required: true } }
97
+ specify{ expect(subject <=> other).to eq(-1) }
98
+ end
99
+
100
+ context 'when other is required field and its weight less than first' do
101
+ let(:options){ { required: true, weight: 5 } }
102
+ specify{ expect(subject <=> other).to eq(-1) }
103
+ end
104
+
105
+ context 'when other is required field and its weight more than first' do
106
+ let(:options){ { required: true, weight: 15 } }
107
+ specify{ expect(subject <=> other).to eq(-1) }
108
+ end
109
+
110
+ context 'when other is not required field' do
111
+ let(:options){ {} }
112
+ specify{ expect(subject <=> other).to eq(0) }
113
+ end
114
+
115
+ context 'when other is not required field and its weight less than first' do
116
+ let(:options){ { weight: 5 } }
117
+ specify{ expect(subject <=> other).to eq(1) }
118
+ end
119
+
120
+ context 'when other is not required field and its weight more than first' do
121
+ let(:options){ { weight: 15 } }
122
+ specify{ expect(subject <=> other).to eq(-1) }
123
+ end
124
+ end
125
+
126
+ describe '#weight_in_percent' do
127
+ let(:spec){ double(:spec, total_weight: 200) }
128
+
129
+ subject{ Completeness::Field.new(spec, :name) }
130
+
131
+ specify{ expect(subject.weight_in_percent).to eq(5) }
132
+ end
133
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Completeness::Model do
4
+ shared_examples_for :delegated_methods do |*method_names|
5
+ let(:object){ klass.new }
6
+ let(:klass){ Class.new{
7
+ include Completeness::Model
8
+ completeness{}
9
+ } }
10
+
11
+ method_names.each do |method_name|
12
+ specify do
13
+ expect(object.completeness_spec).to receive(method_name).with(object)
14
+ object.send(method_name)
15
+ end
16
+ end
17
+ end
18
+
19
+ describe '.completeness' do
20
+ let(:block){ ->(){} }
21
+ let(:options){ {} }
22
+ let(:dsl){ double(:dsl, spec: 'spec') }
23
+ let(:klass){ Class.new{ include Completeness::Model } }
24
+
25
+ before do
26
+ expect(Completeness::DSL).to receive(:new).with(options, &block).and_return(dsl)
27
+ klass.completeness(options, &block)
28
+ end
29
+
30
+ specify{ expect(klass.completeness_spec).to eq('spec') }
31
+ end
32
+
33
+ it_should_behave_like :delegated_methods, :completed?, :completed_percent, :completed_weight
34
+ end
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+
3
+ describe Completeness::Specification do
4
+ let(:name1_value){ nil }
5
+ let(:name2_value){ nil }
6
+ let(:name3_value){ nil }
7
+ let(:object){ double(:object, name1: name1_value, name2: name2_value, name3: name3_value) }
8
+
9
+ subject{ Completeness::Specification.new }
10
+
11
+ describe '#[]' do
12
+ before{ subject.stub(attributes: { name1: 'name1', name2: 'name2' }) }
13
+
14
+ specify{ expect(subject[:name1]).to eq('name1') }
15
+ specify{ expect(subject[:name2]).to eq('name2') }
16
+ end
17
+
18
+ describe '#[]=' do
19
+ specify{ expect{ subject[:name1] = 'name1' }.to change{subject[:name1]}.from(nil).to('name1') }
20
+ end
21
+
22
+ describe '#required_attributes' do
23
+ let(:name1){ Completeness::Field.new(subject, :name1, required: true) }
24
+ let(:name2){ Completeness::Field.new(subject, :name2, required: false) }
25
+ let(:name3){ Completeness::Field.new(subject, :name3, required: true) }
26
+
27
+ before do
28
+ subject[:name1] = name1
29
+ subject[:name2] = name2
30
+ subject[:name3] = name3
31
+ end
32
+
33
+ specify{ expect(subject.required_attributes).to eq([name1, name3]) }
34
+ end
35
+
36
+ describe '#total_weight' do
37
+ before do
38
+ subject[:name1] = Completeness::Field.new(subject, :name1, weight: 12)
39
+ subject[:name2] = Completeness::Field.new(subject, :name2, weight: 13)
40
+ subject[:name3] = Completeness::Field.new(subject, :name3, weight: 14)
41
+ end
42
+
43
+ specify{ expect(subject.total_weight).to eq(39) }
44
+ end
45
+
46
+ describe '#recomend_next_attribute_for' do
47
+ let(:name1){ Completeness::Field.new(subject, :name1, required: true) }
48
+ let(:name2){ Completeness::Field.new(subject, :name2, required: false, weight: 15) }
49
+ let(:name3){ Completeness::Field.new(subject, :name3, required: true, weight: 5) }
50
+
51
+ before do
52
+ subject[:name1] = name1
53
+ subject[:name2] = name2
54
+ subject[:name3] = name3
55
+ end
56
+
57
+ specify{ expect(subject.recomend_next_attribute_for(object)).to eq(name1) }
58
+
59
+ context do
60
+ let(:name1_value){ 'value' }
61
+ specify{ expect(subject.recomend_next_attribute_for(object)).to eq(name3) }
62
+ end
63
+
64
+ context do
65
+ let(:name1_value){ 'value' }
66
+ let(:name3_value){ 'value' }
67
+ specify{ expect(subject.recomend_next_attribute_for(object)).to eq(name2) }
68
+ end
69
+
70
+ context do
71
+ let(:name1_value){ 'value' }
72
+ let(:name2_value){ 'value' }
73
+ let(:name3_value){ 'value' }
74
+ specify{ expect(subject.recomend_next_attribute_for(object)).to be_nil }
75
+ end
76
+ end
77
+
78
+ describe '#weighted_uncompleted_attributes_for' do
79
+ let(:name1){ Completeness::Field.new(subject, :name1, required: true) }
80
+ let(:name2){ Completeness::Field.new(subject, :name2, required: false, weight: 15) }
81
+ let(:name3){ Completeness::Field.new(subject, :name3, required: true, weight: 5) }
82
+
83
+ before do
84
+ subject[:name1] = name1
85
+ subject[:name2] = name2
86
+ subject[:name3] = name3
87
+ end
88
+
89
+ specify{ expect(subject.weighted_uncompleted_attributes_for(object)).to eq([name1, name3, name2]) }
90
+
91
+ context do
92
+ let(:name1_value){ 'value' }
93
+ specify{ expect(subject.weighted_uncompleted_attributes_for(object)).to eq([name3, name2]) }
94
+ end
95
+
96
+ context do
97
+ let(:name1_value){ 'value' }
98
+ let(:name3_value){ 'value' }
99
+ specify{ expect(subject.weighted_uncompleted_attributes_for(object)).to eq([name2]) }
100
+ end
101
+
102
+ context do
103
+ let(:name1_value){ 'value' }
104
+ let(:name2_value){ 'value' }
105
+ let(:name3_value){ 'value' }
106
+ specify{ expect(subject.weighted_uncompleted_attributes_for(object)).to be_empty }
107
+ end
108
+ end
109
+
110
+ describe '#completed_weight' do
111
+ before do
112
+ subject[:name1] = Completeness::Field.new(subject, :name1, weight: 5)
113
+ subject[:name2] = Completeness::Field.new(subject, :name2, weight: 10)
114
+ subject[:name3] = Completeness::Field.new(subject, :name3, weight: 15)
115
+ end
116
+
117
+ specify{ expect(subject.completed_weight(object)).to eq(0) }
118
+
119
+ context 'when one attribute is completed' do
120
+ let(:name1_value){ 'value' }
121
+ specify{ expect(subject.completed_weight(object)).to eq(5) }
122
+ end
123
+
124
+ context 'when another attribute is completed' do
125
+ let(:name2_value){ 'value' }
126
+ specify{ expect(subject.completed_weight(object)).to eq(10) }
127
+ end
128
+
129
+ context 'when two attributes are completed' do
130
+ let(:name1_value){ 'value' }
131
+ let(:name2_value){ 'value' }
132
+ specify{ expect(subject.completed_weight(object)).to eq(15) }
133
+ end
134
+
135
+ context 'when all attributes are completed' do
136
+ let(:name1_value){ 'value' }
137
+ let(:name2_value){ 'value' }
138
+ let(:name3_value){ 'value' }
139
+ specify{ expect(subject.completed_weight(object)).to eq(30) }
140
+ end
141
+ end
142
+
143
+ describe '#completed_percent' do
144
+ before do
145
+ subject[:name1] = Completeness::Field.new(subject, :name1, weight: 5)
146
+ subject[:name2] = Completeness::Field.new(subject, :name2, weight: 10)
147
+ subject[:name3] = Completeness::Field.new(subject, :name3, weight: 15)
148
+ end
149
+
150
+ specify{ expect(subject.completed_percent(object)).to eq(0) }
151
+
152
+ context 'when one attribute is completed' do
153
+ let(:name1_value){ 'value' }
154
+ specify{ expect(subject.completed_percent(object)).to eq(17) }
155
+ end
156
+
157
+ context 'when another attribute is completed' do
158
+ let(:name2_value){ 'value' }
159
+ specify{ expect(subject.completed_percent(object)).to eq(33) }
160
+ end
161
+
162
+ context 'when two attributes are completed' do
163
+ let(:name1_value){ 'value' }
164
+ let(:name2_value){ 'value' }
165
+ specify{ expect(subject.completed_percent(object)).to eq(50) }
166
+ end
167
+
168
+ context 'when all attributes are completed' do
169
+ let(:name1_value){ 'value' }
170
+ let(:name2_value){ 'value' }
171
+ let(:name3_value){ 'value' }
172
+ specify{ expect(subject.completed_percent(object)).to eq(100) }
173
+ end
174
+ end
175
+
176
+ describe '#completed?' do
177
+ before do
178
+ subject[:name1] = Completeness::Field.new(subject, :name1, required: true)
179
+ subject[:name2] = Completeness::Field.new(subject, :name2, required: false)
180
+ subject[:name3] = Completeness::Field.new(subject, :name3, required: true)
181
+ end
182
+
183
+ specify{ expect(subject.completed?(object)).to be_false }
184
+
185
+ context 'when one required attribute is completed' do
186
+ let(:name1_value){ 'value' }
187
+ specify{ expect(subject.completed?(object)).to be_false }
188
+ end
189
+
190
+ context 'when one unrequired attribute is completed' do
191
+ let(:name2_value){ 'value' }
192
+ specify{ expect(subject.completed?(object)).to be_false }
193
+ end
194
+
195
+ context 'when all required attributes are completed' do
196
+ let(:name1_value){ 'value' }
197
+ let(:name3_value){ 'value' }
198
+ specify{ expect(subject.completed?(object)).to be_true }
199
+ end
200
+
201
+ context 'when all attributes are completed' do
202
+ let(:name1_value){ 'value' }
203
+ let(:name2_value){ 'value' }
204
+ let(:name3_value){ 'value' }
205
+ specify{ expect(subject.completed?(object)).to be_true }
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'completeness'
3
+
4
+ RSpec.configure do |config|
5
+ config.mock_with :rspec
6
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: completeness
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - undr
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Completeness is a way to add completeness progress (like in LinkedIn)
84
+ into your application.
85
+ email:
86
+ - undr@yandex.ru
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - .gitignore
92
+ - .rspec
93
+ - Gemfile
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - completeness.gemspec
98
+ - lib/completeness.rb
99
+ - lib/completeness/dsl.rb
100
+ - lib/completeness/field.rb
101
+ - lib/completeness/model.rb
102
+ - lib/completeness/specification.rb
103
+ - lib/completeness/version.rb
104
+ - spec/completeness/dsl_spec.rb
105
+ - spec/completeness/field_spec.rb
106
+ - spec/completeness/model_spec.rb
107
+ - spec/completeness/specification_spec.rb
108
+ - spec/spec_helper.rb
109
+ homepage: https://github.com/undr/completeness
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.0.7
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Completeness is a way to add completeness progress (like in LinkedIn) into
133
+ your application.
134
+ test_files:
135
+ - spec/completeness/dsl_spec.rb
136
+ - spec/completeness/field_spec.rb
137
+ - spec/completeness/model_spec.rb
138
+ - spec/completeness/specification_spec.rb
139
+ - spec/spec_helper.rb