dossier-segmenter 0.9.0

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.
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dossier::Segmenter::Report do
4
+ let(:report_class) { Class.new(Dossier::Report) }
5
+ let(:segmenter_class) { report_class.const_get(:Segmenter) }
6
+ let(:report) { report_class.new }
7
+
8
+ it "creates a segment subclass under its own namespace when inherited" do
9
+ expect(segmenter_class.ancestors).to include(Dossier::Segmenter)
10
+ end
11
+
12
+ it "sets its class on the created segment_class" do
13
+ expect(segmenter_class.report_class).to eq report_class
14
+ end
15
+
16
+ it "has a reference to its segmenter class" do
17
+ expect(CuteAnimalsReport.segmenter_class).to eq CuteAnimalsReport::Segmenter
18
+ end
19
+
20
+ it "does not have a segmenter if no segments have been defined" do
21
+ expect(report).to_not be_segmented
22
+ end
23
+ end
@@ -0,0 +1,171 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dossier::Segmenter do
4
+
5
+ let(:report_class) { Class.new(Dossier::Report) }
6
+ let!(:segmenter_class) {
7
+ report_class.segmenter_class.tap do |klass|
8
+ klass.instance_eval do
9
+ segment :family
10
+ segment :domestic, display_name: ->(row) { "#{row[:domestic] ? 'Domestic' : 'Wild'} #{row[:group_name]}" } do
11
+ segment :group, display_name: :group_name, group_by: :group_id
12
+ end
13
+ end
14
+ end
15
+ }
16
+ let(:headers) { CuteAnimalsReport::HEADERS.call }
17
+ let(:rows) { CuteAnimalsReport::ROWS.call }
18
+ let(:results) { mock('Results', headers: headers, rows: rows) }
19
+ let(:report) { report_class.new.tap { |r| r.stub(:raw_results).and_return(results) } }
20
+ let(:segmenter) { report.segmenter }
21
+
22
+ describe "report data" do
23
+ let(:data) {
24
+ {
25
+ 'canine.true.10' => [
26
+ ['canine', true, 10, 'foxes', 'fennec', 'tan', 9, 896, true, 1_000],
27
+ ['canine', true, 10, 'foxes', 'fire', 'orange', 0, 468, false, 0],
28
+ ],
29
+ 'canine.false.10' => [
30
+ ['canine', false, 10, 'foxes', 'arctic', 'white', 5, 108, false, 2_500],
31
+ ['canine', false, 10, 'foxes', 'crab-eating', 'brown', 3, 328, false, 5_000],
32
+ ['canine', false, 10, 'foxes', 'red', 'orange', 5, 963, false, 750],
33
+ ],
34
+ 'canine.true.15' => [
35
+ ['canine', true, 15, 'dog', 'shiba inu', 'tan', 7, 191, true, 200],
36
+ ['canine', true, 15, 'dog', 'labrador', 'varied', 5, 269, true, 50],
37
+ ['canine', true, 15, 'dog', 'beagle', 'mixed', 8, 917, true, 25],
38
+ ['canine', true, 15, 'dog', 'boxer', 'brown', 5, 14, true, 50],
39
+ ],
40
+ 'feline.false.22' => [
41
+ ['feline', false, 22, 'tiger', 'bengal', 'orange', 4, 184, false, 100_000],
42
+ ['feline', false, 22, 'tiger', 'siberian', 'white', 5, 970, false, 500_000],
43
+ ],
44
+ 'feline.false.23' => [
45
+ ['feline', false, 23, 'lion', 'lion', 'tan', 5, 128, false, 100_000],
46
+ ],
47
+ 'feline.true.219' => [
48
+ ['feline', true, 219, 'cat', 'short hair', 'varied', 6, 2062, true, 10],
49
+ ['feline', true, 219, 'cat', 'abyssinian', 'tan', 7, 125, true, 20],
50
+ ['feline', true, 219, 'cat', 'persian', 'varied', 6, 625, false, 50],
51
+ ['feline', true, 219, 'cat', 'wirehair', 'grey', 7, 758, true, 75],
52
+ ]
53
+ }
54
+ }
55
+
56
+ it "stores the report rows in a hash organized by segment" do
57
+ expect(segmenter.data).to eq(data)
58
+ end
59
+ end
60
+
61
+ describe "instances" do
62
+ it "takes a report upon instantiation" do
63
+ expect(segmenter.report).to eq report
64
+ end
65
+
66
+ it "has access to the class segment chain" do
67
+ expect(segmenter.segment_chain.length).to eq 3
68
+ end
69
+ end
70
+
71
+ describe "class" do
72
+ it "has a reference to the report that created it" do
73
+ expect(segmenter_class.report_class).to eq report_class
74
+ end
75
+
76
+ it "determines headers to skip when displaying" do
77
+ expect(segmenter_class.skip_headers.sort).to eq %w[family group_name group_id domestic].sort
78
+ end
79
+ end
80
+
81
+ describe "DSL" do
82
+ describe "segment" do
83
+ describe "definition creation" do
84
+ let(:segmenter_class) { report_class.segmenter_class }
85
+ let(:definition) { segmenter_class.segments.last }
86
+
87
+ it "creates a segment definition" do
88
+ segmenter_class.segment :foo
89
+ expect(definition).to be_a Dossier::Segment::Definition
90
+ end
91
+
92
+ it "passes the name option" do
93
+ segmenter_class.segment :foo
94
+ expect(definition.name).to eq :foo
95
+ end
96
+
97
+ it "passes the group_by option" do
98
+ segmenter_class.segment :name, group_by: :foo
99
+ expect(definition.group_by).to eq :foo
100
+ end
101
+
102
+ it "passes the display_name option" do
103
+ segmenter_class.segment :name, display_name: :foo
104
+ expect(definition.display_name).to eq :foo
105
+ end
106
+ end
107
+
108
+ it "keeps an array of segments" do
109
+ expect(segmenter_class.segments.count).to eq 3
110
+ end
111
+
112
+ it "keeps the segments in the order defined" do
113
+ expect(segmenter_class.segments[0].name).to eq :family
114
+ expect(segmenter_class.segments[1].name).to eq :domestic
115
+ end
116
+
117
+ it "allows nesting segment definations" do
118
+ expect(segmenter_class.segments[2].name).to eq :group
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "segment options" do
124
+ it 'works the way I want it to' do
125
+ segment = mock('Segment', key_path: 'feline.false')
126
+ options = segmenter.segment_options_for segment
127
+ expect(options.map { |hash| hash['group_id'] }).to eq [22, 23]
128
+ end
129
+ end
130
+
131
+ describe "segment traversal" do
132
+
133
+ describe "from the segmenter to the first segment" do
134
+ it "has an array of families" do
135
+ expect(report.segmenter.families.length).to eq 2
136
+ end
137
+
138
+ describe "to the second segment" do
139
+ let(:family) { report.segmenter.families.first }
140
+
141
+ it "has an array of domestics" do
142
+ expect(family.domestics.length).to eq 2
143
+ end
144
+
145
+ describe "to the third segment" do
146
+ let(:domestic) { family.domestics.first }
147
+
148
+ it "has an array of groups" do
149
+ expect(domestic.groups.length).to eq 2
150
+ end
151
+
152
+ describe "to the rows" do
153
+ let(:group) { domestic.groups.first }
154
+
155
+ it "has rows" do
156
+ expect(group.rows.length).to eq 2
157
+ end
158
+
159
+ describe "to additional rows" do
160
+ let(:group) { domestic.groups.last }
161
+
162
+ it "has rows" do
163
+ expect(group.rows.length).to eq 4
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,41 @@
1
+ class CuteAnimalsReport < Dossier::Report
2
+ HEADERS = -> { %w[family domestic group_id group_name name color cuteness gifs playful cost_new] }
3
+ ROWS = -> { [
4
+ ["canine", true, 10, "foxes", "fennec", "tan", 9, 896, true, 1_000],
5
+ ["canine", true, 10, "foxes", "fire", "orange", 0, 468, false, 0],
6
+ ["canine", false, 10, "foxes", "arctic", "white", 5, 108, false, 2_500],
7
+ ["canine", false, 10, "foxes", "crab-eating", "brown", 3, 328, false, 5_000],
8
+ ["canine", false, 10, "foxes", "red", "orange", 5, 963, false, 750],
9
+ ["canine", true, 15, "dog", "shiba inu", "tan", 7, 191, true, 200],
10
+ ["canine", true, 15, "dog", "labrador", "varied", 5, 269, true, 50],
11
+ ["canine", true, 15, "dog", "beagle", "mixed", 8, 917, true, 25],
12
+ ["canine", true, 15, "dog", "boxer", "brown", 5, 14, true, 50],
13
+ ["feline", false, 22, "tiger", "bengal", "orange", 4, 184, false, 100_000],
14
+ ["feline", false, 22, "tiger", "siberian", "white", 5, 970, false, 500_000],
15
+ ["feline", false, 23, "lion", "lion", "tan", 5, 128, false, 100_000],
16
+ ["feline", true, 219, "cat", "short hair", "varied", 6, 2062, true, 10],
17
+ ["feline", true, 219, "cat", "abyssinian", "tan", 7, 125, true, 20],
18
+ ["feline", true, 219, "cat", "persian", "varied", 6, 625, false, 50],
19
+ ["feline", true, 219, "cat", "wirehair", "grey", 7, 758, true , 75]
20
+ ] }
21
+
22
+ def initialize(*)
23
+ super
24
+ self.results = OpenStruct.new(headers: HEADERS.call, rows: ROWS.call)
25
+ end
26
+
27
+ def format_gifs(value)
28
+ formatter.commafy_number(value)
29
+ end
30
+
31
+ def format_cost_new(value)
32
+ formatter.number_to_dollars(value)
33
+ end
34
+
35
+ class Segmenter
36
+ segment :family
37
+ segment :domestic, display_name: ->(row) { "#{row[:domestic] ? 'Domestic' : 'Wild'} #{row[:group_name]}" }
38
+ segment :group, display_name: :group_name, group_by: :group_id
39
+ end
40
+ end
41
+
@@ -0,0 +1,2 @@
1
+ require File.expand_path('../config/application', __FILE__)
2
+ run Dummy::Application
@@ -0,0 +1,27 @@
1
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../../../../Gemfile', __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ Bundler.setup
7
+
8
+ $:.unshift File.expand_path('../../../../lib', __FILE__)
9
+
10
+ require "action_controller/railtie"
11
+
12
+ Bundler.require
13
+
14
+ ApplicationController = Class.new(ActionController::Base)
15
+
16
+ require 'dossier/segmenter'
17
+
18
+ module Dummy
19
+ class Application < ::Rails::Application
20
+ config.cache_classes = !Rails.env.development?
21
+ config.active_support.deprecation = :stderr
22
+ config.secret_token = 'http://s3-ec.buzzfed.com/static/enhanced/webdr03/2013/5/25/8/anigif_enhanced-buzz-11857-1369483324-0.gif'
23
+ end
24
+ end
25
+
26
+ Dummy::Application.initialize!
27
+
File without changes
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe "segmented report" do
4
+ let(:path) { dossier_report_path(report: 'cute_animals') }
5
+
6
+ before(:each) { visit path }
7
+
8
+ it "displays the correct html" do
9
+ expect(page).to have_content('canine')
10
+ expect(page).to have_content('shiba inu')
11
+ end
12
+
13
+ it "does not display options that are only used for grouping" do
14
+ expect(page).to_not have_content('219') # group_ids
15
+ end
16
+
17
+ it "displays its options" do
18
+ pending "support options"
19
+ expect(page).to have_content('Some options plz!')
20
+ end
21
+
22
+ it "has summaries" do
23
+ expect(page).to have_content '$300,000.00'
24
+ expect(page).to have_content '3,570.0'
25
+ end
26
+
27
+ end
28
+
@@ -0,0 +1,20 @@
1
+ ENV['RAILS_ENV'] = 'test'
2
+
3
+ require File.expand_path('../dummy/config/application', __FILE__)
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+
8
+ require 'rails/test_help'
9
+ require 'rspec/rails'
10
+ require 'pry'
11
+ require 'capybara/rspec'
12
+
13
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
14
+
15
+ RSpec.configure do |config|
16
+ config.treat_symbols_as_metadata_keys_with_true_values = true
17
+ config.run_all_when_everything_filtered = true
18
+ config.filter_run :focus
19
+ config.order = 'random'
20
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dossier-segmenter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Hunter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dossier
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.8'
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: rspec-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.13'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.13
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 3.2.13
69
+ - !ruby/object:Gem::Dependency
70
+ name: capybara
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '2.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '2.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '0.7'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '0.7'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: 0.9.10
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: 0.9.10
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Adds control breaks to dossier reports by defined segments based on query
126
+ results.
127
+ email:
128
+ - adamhunter@me.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - .rspec
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.md
138
+ - Rakefile
139
+ - app/views/dossier/reports/cute_animals.html.haml
140
+ - dossier-segmenter.gemspec
141
+ - lib/dossier/segment.rb
142
+ - lib/dossier/segment/chain.rb
143
+ - lib/dossier/segment/definition.rb
144
+ - lib/dossier/segment/rows.rb
145
+ - lib/dossier/segment/summary.rb
146
+ - lib/dossier/segmenter.rb
147
+ - lib/dossier/segmenter/engine.rb
148
+ - lib/dossier/segmenter/report.rb
149
+ - lib/dossier/segmenter/version.rb
150
+ - script/rails
151
+ - spec/dossier/segment/chain_spec.rb
152
+ - spec/dossier/segment/definition_spec.rb
153
+ - spec/dossier/segment/rows_spec.rb
154
+ - spec/dossier/segment/summary_spec.rb
155
+ - spec/dossier/segment_spec.rb
156
+ - spec/dossier/segmenter/report_spec.rb
157
+ - spec/dossier/segmenter_spec.rb
158
+ - spec/dummy/app/reports/cute_animals_report.rb
159
+ - spec/dummy/config.ru
160
+ - spec/dummy/config/application.rb
161
+ - spec/dummy/public/favicon.ico
162
+ - spec/features/segmented_report_spec.rb
163
+ - spec/spec_helper.rb
164
+ homepage: https://github.com/adamhunter/dossier-segmenter
165
+ licenses:
166
+ - MIT
167
+ metadata: {}
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - '>='
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ requirements: []
183
+ rubyforge_project:
184
+ rubygems_version: 2.0.3
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Extends Dossier to have segmented report functionality.
188
+ test_files:
189
+ - spec/dossier/segment/chain_spec.rb
190
+ - spec/dossier/segment/definition_spec.rb
191
+ - spec/dossier/segment/rows_spec.rb
192
+ - spec/dossier/segment/summary_spec.rb
193
+ - spec/dossier/segment_spec.rb
194
+ - spec/dossier/segmenter/report_spec.rb
195
+ - spec/dossier/segmenter_spec.rb
196
+ - spec/dummy/app/reports/cute_animals_report.rb
197
+ - spec/dummy/config.ru
198
+ - spec/dummy/config/application.rb
199
+ - spec/dummy/public/favicon.ico
200
+ - spec/features/segmented_report_spec.rb
201
+ - spec/spec_helper.rb