completeness 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +56 -0
- data/Rakefile +6 -0
- data/completeness.gemspec +27 -0
- data/lib/completeness.rb +9 -0
- data/lib/completeness/dsl.rb +19 -0
- data/lib/completeness/field.rb +43 -0
- data/lib/completeness/model.rb +31 -0
- data/lib/completeness/specification.rb +59 -0
- data/lib/completeness/version.rb +3 -0
- data/spec/completeness/dsl_spec.rb +27 -0
- data/spec/completeness/field_spec.rb +133 -0
- data/spec/completeness/model_spec.rb +34 -0
- data/spec/completeness/specification_spec.rb +208 -0
- data/spec/spec_helper.rb +6 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -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=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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
|
data/lib/completeness.rb
ADDED
@@ -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,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
|
data/spec/spec_helper.rb
ADDED
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
|