crease 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +67 -30
- data/lib/crease.rb +1 -0
- data/lib/crease/builder.rb +89 -47
- data/lib/crease/configuration.rb +20 -0
- data/lib/crease/text_helpers.rb +6 -2
- data/lib/crease/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67e2fe93fb2d9c22afd67774b5a2f443d5f20489
|
4
|
+
data.tar.gz: 663d9fac09068a14f094a1cd5bce8dada3f46a41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b858fcd0cc79f8021dfd8d63ae870cbf48b76edd158818cfbaa803c9f17b6d31029ae175be9abfb2dc1ca1b8b3f0a5c6935440410c268db3ee7259f0eab874f
|
7
|
+
data.tar.gz: a450e8fc73d088ae9d629c16cb93dd15c3a04918c195b4c676f4077c37a0a457224c2937a572c3c0ba6a07e4885ccc42bfd9d3a55c724f370545ca6e45c9e008
|
data/README.md
CHANGED
@@ -4,17 +4,15 @@ Generate dynamic text about increasing and decreasing numbers.
|
|
4
4
|
|
5
5
|
## Usage
|
6
6
|
|
7
|
-
Let's say you're writing a dynamic report that needs to put data in context,
|
8
|
-
explaining it in simple English.
|
7
|
+
Let's say you're writing a dynamic report that needs to put data in context, explaining it in simple English.
|
9
8
|
|
10
|
-
You want to tell the world that
|
11
|
-
that the total population in Pittsburgh decreased, but you only want to write
|
12
|
-
one template that takes in data from each city and displays the right text.
|
9
|
+
You want to tell the world that the total population of Boston increased, and that the total population in Pittsburgh decreased, but you only want to write one template that takes in data from each city and displays the right text.
|
13
10
|
|
14
|
-
|
11
|
+
|
12
|
+
__With Crease, you just write:__
|
15
13
|
|
16
14
|
```ruby'
|
17
|
-
# app/views/city/report.html.erb
|
15
|
+
# In any ERb (or Haml) template, i.e. app/views/city/report.html.erb
|
18
16
|
<p>
|
19
17
|
In <%= @city.name %>, the total population
|
20
18
|
<%= increased.by @city.population_in_2000, @city.population_in_2010 %>,
|
@@ -22,24 +20,28 @@ With Crease, you can write:
|
|
22
20
|
<p>
|
23
21
|
```
|
24
22
|
|
23
|
+
And it will work for both cities.
|
24
|
+
|
25
|
+
|
25
26
|
For Boston, this evaluates to:
|
26
27
|
|
27
28
|
```
|
28
29
|
<p>
|
29
|
-
In Boston, the total population increased by 30,018, an increase of
|
30
|
+
In Boston, the total population increased by 30,018, an increase of 5.08%%.
|
30
31
|
<p>
|
31
32
|
```
|
32
33
|
|
33
|
-
> Note: we think that '105%' here is misleading: see the roadmap for more.
|
34
|
-
|
35
34
|
For Pittsburgh, the same template evaluates to:
|
36
35
|
|
37
36
|
```
|
38
37
|
<p>
|
39
|
-
In Pittsburgh, the total population decreased by 28,068, an decrease of 8.
|
38
|
+
In Pittsburgh, the total population decreased by 28,068, an decrease of 8.41%.
|
40
39
|
<p>
|
41
40
|
```
|
42
41
|
|
42
|
+
> Source of the above data: [Boston](https://www.google.com/#q=boston+population+2010) | [Pittsburgh](https://www.google.com/#q=pittsburgh+population+2010)
|
43
|
+
|
44
|
+
|
43
45
|
#### Examples
|
44
46
|
|
45
47
|
The following are examples of text you can write with Crease.
|
@@ -47,27 +49,50 @@ The following are examples of text you can write with Crease.
|
|
47
49
|
```ruby
|
48
50
|
# In the context of a template
|
49
51
|
|
50
|
-
|
51
|
-
increased.by(
|
52
|
-
increased.by(
|
53
|
-
|
52
|
+
# Increase or decrease with one number
|
53
|
+
increased.by(1) #=> "increased by 1.0"
|
54
|
+
increased.by(-1) #=> "decreased by 1.0"
|
55
|
+
|
56
|
+
# Increase or decrease with two numbers
|
57
|
+
increased.by(2, 4) #=> "increased by 2.0"
|
58
|
+
an.increase.of(2) #=> "an increase of 2.0"
|
59
|
+
decreased.by(2, 4) #=> "increased by 2.0"
|
54
60
|
# `#decreased` is just an alias for `#increased`
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
|
62
|
+
# Percent increase or decrease with one number, percent
|
63
|
+
increased.by(1).percent #=> "increased by 1.0%"
|
64
|
+
|
65
|
+
# Percent increase or decrease with two numbers, percent
|
66
|
+
increased.by(2, 4).percent #=> "increased by 100.0%"
|
67
|
+
increased.by(4, 1).percent #=> "decreased by 75.0%"
|
68
|
+
|
69
|
+
# Change with one number
|
70
|
+
a.change.of(2) #=> "a change of 2.0"
|
71
|
+
changed.by(-2) #=> "changed by -2.0"
|
72
|
+
|
73
|
+
# Change with two numbers
|
74
|
+
changed.by(1, 2) #=> "changed by 1.0"
|
75
|
+
a.change.of(4, 2) #=> "a change of -2.0"
|
76
|
+
|
77
|
+
# Percent change with one numbers
|
78
|
+
changed.by(2).percent #=> "changed by 2.0%"
|
79
|
+
a.change.of.by(2).percent #=> "changed by 2.0%"
|
80
|
+
|
81
|
+
# Percent change with two numbers
|
82
|
+
changed.by(2, 4).percent #=> "changed by 200.0%"
|
83
|
+
a.change.of(2, 4).percent #=> "a change of 200.0%"
|
84
|
+
a.change.of(4, 1).percent #=> "a change of -300.0%"
|
85
|
+
# This is a little misleading, and will be taken under advisement.
|
59
86
|
```
|
60
87
|
|
61
|
-
Inside templates, these method chains will be implicitly converted to strings,
|
62
|
-
with ERb or Haml calling `#to_s` on them.
|
88
|
+
Inside templates, these method chains will be implicitly converted to strings, with ERb or Haml calling `#to_s` on them.
|
63
89
|
|
64
|
-
If you are working with these outside of a template, you'll need to call `#to_s`
|
65
|
-
at the end of the method chain yourself.
|
90
|
+
If you are working with these outside of a template, you'll need to call `#to_s` at the end of the method chain yourself.
|
66
91
|
|
67
92
|
```ruby
|
68
93
|
# Outside a template
|
69
94
|
|
70
|
-
increased.by(1) #=> #<Crease::Builder:
|
95
|
+
increased.by(1) #=> #<Crease::Builder:0x007fdaa19a6db0 @before=nil, @subject=nil, @after=:by, @args=[1.0], @percent=false, @tense=:past, @sigfig=2>
|
71
96
|
increased.by(1).to_s #=> 'increased by 1.0'
|
72
97
|
```
|
73
98
|
|
@@ -91,10 +116,10 @@ Or install it yourself as:
|
|
91
116
|
|
92
117
|
$ gem install crease
|
93
118
|
|
119
|
+
|
94
120
|
#### Rails
|
95
121
|
|
96
|
-
Include the
|
97
|
-
helper if appropriate.
|
122
|
+
Include the TextHelpers module in your ApplicationHelper.
|
98
123
|
|
99
124
|
```ruby
|
100
125
|
# app/helpers/application_helper.rb
|
@@ -106,6 +131,20 @@ class ApplicationHelper
|
|
106
131
|
end
|
107
132
|
```
|
108
133
|
|
134
|
+
You can optionally configure Crease to convert all results to integers, or set a number of significant digits to round to.
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
# Create a file config/initializers/crease.rb
|
138
|
+
|
139
|
+
Crease.configure do |config|
|
140
|
+
# Round every result to a specific number of significant digits.
|
141
|
+
config.digits = 3 # Defaults to 2.
|
142
|
+
|
143
|
+
# Convert every result to integer. This option ignores the digits option.
|
144
|
+
config.integer = true # Defaults to false.
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
109
148
|
## Development
|
110
149
|
|
111
150
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -118,11 +157,9 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/beechn
|
|
118
157
|
|
119
158
|
## Roadmap
|
120
159
|
|
121
|
-
-
|
122
|
-
- We'd like to have a way to configure the gem -- for Rails, in an initializer -- so that we can specify default significant figures there. If someone wants everything to be an integer by default, it would be easier to do it there.
|
123
|
-
- Might even allow a Proc-based option that sets sigfigs dynamically.
|
160
|
+
- Allow a Proc-based option that sets sigfigs dynamically.
|
124
161
|
- Add documentation about understanding sigfigs.
|
125
|
-
|
162
|
+
|
126
163
|
|
127
164
|
|
128
165
|
## License
|
data/lib/crease.rb
CHANGED
data/lib/crease/builder.rb
CHANGED
@@ -1,100 +1,142 @@
|
|
1
1
|
module Crease
|
2
2
|
class Builder
|
3
3
|
|
4
|
-
def
|
5
|
-
@
|
6
|
-
|
4
|
+
def initialize(before: nil, subject: nil, after: nil, args: [], percent: false, tense: nil)
|
5
|
+
@before = before
|
6
|
+
@subject = subject
|
7
|
+
@after = after
|
8
|
+
@args = args
|
9
|
+
@percent = percent
|
10
|
+
@tense = tense
|
7
11
|
|
8
|
-
def initialize(context: nil, tense: :present)
|
9
|
-
criteria.merge!({ context: context, tense: tense })
|
10
12
|
self
|
11
13
|
end
|
12
14
|
|
13
15
|
def increase
|
14
|
-
|
16
|
+
@tense = :present
|
15
17
|
self
|
16
18
|
end
|
17
19
|
|
18
20
|
alias_method :decrease, :increase
|
19
21
|
|
22
|
+
def change
|
23
|
+
@subject = :change
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
20
27
|
def by(*args, sigfig: 2)
|
21
|
-
|
22
|
-
|
23
|
-
|
28
|
+
@after = :by
|
29
|
+
@args = args.map(&:to_f)
|
30
|
+
@sigfig = sigfig
|
24
31
|
self
|
25
32
|
end
|
26
33
|
|
27
34
|
def of(*args, sigfig: 2)
|
28
|
-
|
29
|
-
|
30
|
-
|
35
|
+
@after = :of
|
36
|
+
@args = args.map(&:to_f)
|
37
|
+
@sigfig = sigfig
|
31
38
|
self
|
32
39
|
end
|
33
40
|
|
34
41
|
def to_s
|
35
|
-
if
|
36
|
-
"#{
|
42
|
+
if @percent
|
43
|
+
"#{phrase} #{percent_value}%"
|
37
44
|
else
|
38
|
-
"#{
|
45
|
+
"#{phrase} #{value}"
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
42
49
|
def percent
|
43
|
-
|
50
|
+
@percent = true
|
44
51
|
self
|
45
52
|
end
|
46
53
|
|
47
|
-
def base_string
|
48
|
-
past = criteria[:tense] == :past ? 'd' : ''
|
49
|
-
str = "#{article}#{increase_or_decrease}#{past}"
|
50
|
-
str << " #{criteria[:word]}" if criteria[:word]
|
51
|
-
str
|
52
|
-
end
|
53
|
-
|
54
54
|
private
|
55
55
|
|
56
|
+
def phrase
|
57
|
+
"#{article} #{subject} #{after}".strip
|
58
|
+
end
|
59
|
+
|
56
60
|
def article
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
if @before
|
62
|
+
indefinitize(subject)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def subject # increase, decrease, or change
|
67
|
+
word = if @subject.to_s == 'change'
|
68
|
+
word = 'change'
|
69
|
+
else
|
70
|
+
increase_or_decrease
|
71
|
+
end
|
72
|
+
if @tense.to_s == 'past'
|
73
|
+
word << 'd'
|
74
|
+
else
|
75
|
+
word
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def after
|
80
|
+
@after
|
81
|
+
end
|
82
|
+
|
83
|
+
def indefinitize(subject)
|
84
|
+
if subject.match /increase/
|
85
|
+
'an'
|
86
|
+
elsif subject.match /decrease|change/
|
87
|
+
'a'
|
63
88
|
end
|
64
89
|
end
|
65
90
|
|
66
91
|
def increase_or_decrease
|
67
|
-
args
|
68
|
-
|
69
|
-
args.last > args.first ? :increase : :decrease
|
92
|
+
if @args.count == 2
|
93
|
+
@args.last > @args.first ? 'increase' : 'decrease'
|
70
94
|
else
|
71
|
-
args.first > 0 ?
|
95
|
+
@args.first > 0 ? 'increase' : 'decrease'
|
72
96
|
end
|
73
97
|
end
|
74
98
|
|
75
99
|
def value
|
76
|
-
|
100
|
+
apply_filters(@subject.to_s == 'change' ? difference : difference.abs)
|
101
|
+
end
|
102
|
+
|
103
|
+
def percent_value
|
104
|
+
apply_filters(@subject.to_s == 'change' ? percent_change : percent_difference.abs)
|
105
|
+
end
|
106
|
+
|
107
|
+
def percent_difference
|
108
|
+
if @args.count == 2
|
109
|
+
(difference / @args.first).to_f * 100
|
110
|
+
else
|
111
|
+
@args.first
|
112
|
+
end
|
77
113
|
end
|
78
114
|
|
79
115
|
def percent_change
|
80
|
-
args
|
81
|
-
|
82
|
-
|
83
|
-
base_calculation
|
116
|
+
if @args.count == 2
|
117
|
+
if @args.last > @args.first
|
118
|
+
(@args.last / @args.first).to_f * 100
|
84
119
|
else
|
85
|
-
|
86
|
-
end
|
120
|
+
((@args.first - @args.last) / @args.last).to_f * -100
|
121
|
+
end
|
87
122
|
else
|
88
|
-
|
89
|
-
end
|
123
|
+
@args.first
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def difference
|
128
|
+
if @args.count == 2
|
129
|
+
(@args.last - @args.first)
|
130
|
+
else
|
131
|
+
@args.first
|
132
|
+
end
|
90
133
|
end
|
91
134
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
(args.last - args.first).abs
|
135
|
+
def apply_filters(number)
|
136
|
+
if Crease.configuration.integer
|
137
|
+
number.to_i
|
96
138
|
else
|
97
|
-
|
139
|
+
number.round(@sigfig || Crease.configuration.digits)
|
98
140
|
end
|
99
141
|
end
|
100
142
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Crease
|
2
|
+
|
3
|
+
def self.configuration
|
4
|
+
@config ||= Configuration.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.configure
|
8
|
+
self.configuration ||= Configuration.new
|
9
|
+
yield(configuration)
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
attr_accessor :digits, :integer
|
14
|
+
|
15
|
+
def initialize(digits: 2, integer: false)
|
16
|
+
@digits = digits
|
17
|
+
@integer = integer
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/crease/text_helpers.rb
CHANGED
@@ -8,11 +8,15 @@ module Crease
|
|
8
8
|
alias_method :decreased, :increased
|
9
9
|
|
10
10
|
def an
|
11
|
-
Crease::Builder.new(
|
11
|
+
Crease::Builder.new(before: :an)
|
12
12
|
end
|
13
13
|
|
14
14
|
def a
|
15
|
-
Crease::Builder.new(
|
15
|
+
Crease::Builder.new(before: :a)
|
16
|
+
end
|
17
|
+
|
18
|
+
def changed
|
19
|
+
Crease::Builder.new(subject: :change, tense: :past)
|
16
20
|
end
|
17
21
|
|
18
22
|
end
|
data/lib/crease/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crease
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Cloyd
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- crease.gemspec
|
78
78
|
- lib/crease.rb
|
79
79
|
- lib/crease/builder.rb
|
80
|
+
- lib/crease/configuration.rb
|
80
81
|
- lib/crease/text_helpers.rb
|
81
82
|
- lib/crease/version.rb
|
82
83
|
homepage: https://github.com/beechnut/crease
|