denormalizer 0.0.1 → 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.
data/CHANGELOG CHANGED
@@ -1,5 +1,11 @@
1
1
  == unreleased changes
2
2
 
3
+ == 0.0.2
4
+
5
+ * Added basic testing for the mixins
6
+ * Changed the scope names to plurals
7
+ * Added instance methods to check for individual denormalized method outputs
8
+
3
9
  == 0.0.1
4
10
 
5
11
  * Added mixin with denormalize_all, denormalize, and also_denormalize methods
@@ -31,10 +31,10 @@ Denormalize associations. This will run the denormalization method on each of t
31
31
 
32
32
  Use the denormalized data
33
33
 
34
- Book.denormalized_active
35
- Book.denormalized_not_active
34
+ Book.denormalized_actives
35
+ Book.denormalized_not_actives
36
36
 
37
- Book.first.denormalized_active? (coming soon)
37
+ Book.first.denormalized_active?
38
38
 
39
39
  == Thought Process
40
40
 
@@ -56,8 +56,10 @@ The first minimizes code duplication but is not chainable and often slower than
56
56
 
57
57
  == Todo
58
58
 
59
- * Improve test coverage
60
- * Add methods to directly access denormalized data from model instances
59
+ * Add code to make sure association denormalization does loop infinitely
60
+ * Improve testing on the Denormalizer::MethodOutput model
61
+ * Refactor dome of the denormalize mixin code to the MethodOutput model
62
+ * Figure out how to replace mysql with a different database/memory store system
61
63
 
62
64
  == Contributing to denormalizer
63
65
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -6,4 +6,13 @@ class Denormalizer::MethodOutput < ActiveRecord::Base
6
6
 
7
7
  FalseOutput = 0
8
8
  TrueOutput = 1
9
+
10
+ def self.by_object_and_method_name(obj, method_name)
11
+ attributes = {
12
+ :denormalized_object_type => obj.class.name,
13
+ :denormalized_object_id => obj.id,
14
+ :denormalized_object_method => method_name
15
+ }
16
+ where(attributes).limit(1)
17
+ end
9
18
  end
@@ -0,0 +1,128 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "denormalizer"
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jeremiah Hemphill"]
12
+ s.date = "2012-07-13"
13
+ s.description = "Cache method outputs and automatically create chainable scopes based on their outputs"
14
+ s.email = "jeremiah@cloudspace.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "CHANGELOG",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "app/models/denormalizer/method_output.rb",
30
+ "denormalizer.gemspec",
31
+ "lib/denormalizer.rb",
32
+ "lib/denormalizer/config.rb",
33
+ "lib/denormalizer/denormalize.rb",
34
+ "lib/denormalizer/engine.rb",
35
+ "lib/denormalizer/railtie.rb",
36
+ "lib/generators/denormalizer/install_generator.rb",
37
+ "lib/generators/denormalizer/templates/config.rb",
38
+ "lib/generators/denormalizer/templates/migrations/install_migration.rb.erb",
39
+ "spec/association_denormalization_spec.rb",
40
+ "spec/denormalize_all_spec.rb",
41
+ "spec/denormalizer_spec.rb",
42
+ "spec/dummy/Rakefile",
43
+ "spec/dummy/app/controllers/application_controller.rb",
44
+ "spec/dummy/app/helpers/application_helper.rb",
45
+ "spec/dummy/app/models/book.rb",
46
+ "spec/dummy/app/models/printing.rb",
47
+ "spec/dummy/app/views/layouts/application.html.erb",
48
+ "spec/dummy/config.ru",
49
+ "spec/dummy/config/application.rb",
50
+ "spec/dummy/config/boot.rb",
51
+ "spec/dummy/config/database.yml",
52
+ "spec/dummy/config/environment.rb",
53
+ "spec/dummy/config/environments/development.rb",
54
+ "spec/dummy/config/environments/production.rb",
55
+ "spec/dummy/config/environments/test.rb",
56
+ "spec/dummy/config/initializers/backtrace_silencers.rb",
57
+ "spec/dummy/config/initializers/denormalizer.rb",
58
+ "spec/dummy/config/initializers/inflections.rb",
59
+ "spec/dummy/config/initializers/mime_types.rb",
60
+ "spec/dummy/config/initializers/secret_token.rb",
61
+ "spec/dummy/config/initializers/session_store.rb",
62
+ "spec/dummy/config/locales/en.yml",
63
+ "spec/dummy/config/routes.rb",
64
+ "spec/dummy/db/migrate/20120706021202_book.rb",
65
+ "spec/dummy/db/migrate/20120706125004_create_denormalizer_tables.rb",
66
+ "spec/dummy/db/schema.rb",
67
+ "spec/dummy/public/404.html",
68
+ "spec/dummy/public/422.html",
69
+ "spec/dummy/public/500.html",
70
+ "spec/dummy/public/favicon.ico",
71
+ "spec/dummy/public/javascripts/application.js",
72
+ "spec/dummy/public/javascripts/controls.js",
73
+ "spec/dummy/public/javascripts/dragdrop.js",
74
+ "spec/dummy/public/javascripts/effects.js",
75
+ "spec/dummy/public/javascripts/prototype.js",
76
+ "spec/dummy/public/javascripts/rails.js",
77
+ "spec/dummy/public/stylesheets/.gitkeep",
78
+ "spec/dummy/script/rails",
79
+ "spec/integration/navigation_spec.rb",
80
+ "spec/method_denormalization_spec.rb",
81
+ "spec/spec_helper.rb"
82
+ ]
83
+ s.homepage = "http://github.com/jeremiahishere/denormalizer"
84
+ s.licenses = ["MIT"]
85
+ s.require_paths = ["lib"]
86
+ s.rubygems_version = "1.8.15"
87
+ s.summary = "Cache method outputs"
88
+
89
+ if s.respond_to? :specification_version then
90
+ s.specification_version = 3
91
+
92
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
93
+ s.add_runtime_dependency(%q<rails>, [">= 3.0.0"])
94
+ s.add_development_dependency(%q<capybara>, [">= 0.4.0"])
95
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
96
+ s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
97
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
98
+ s.add_development_dependency(%q<rspec-rails>, ["~> 2.6.1"])
99
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
100
+ s.add_development_dependency(%q<database_cleaner>, [">= 0"])
101
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.3"])
102
+ s.add_development_dependency(%q<ci_reporter>, [">= 0"])
103
+ else
104
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
105
+ s.add_dependency(%q<capybara>, [">= 0.4.0"])
106
+ s.add_dependency(%q<sqlite3>, [">= 0"])
107
+ s.add_dependency(%q<ruby-debug19>, [">= 0"])
108
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
109
+ s.add_dependency(%q<rspec-rails>, ["~> 2.6.1"])
110
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
111
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
112
+ s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
113
+ s.add_dependency(%q<ci_reporter>, [">= 0"])
114
+ end
115
+ else
116
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
117
+ s.add_dependency(%q<capybara>, [">= 0.4.0"])
118
+ s.add_dependency(%q<sqlite3>, [">= 0"])
119
+ s.add_dependency(%q<ruby-debug19>, [">= 0"])
120
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
121
+ s.add_dependency(%q<rspec-rails>, ["~> 2.6.1"])
122
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
123
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
124
+ s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
125
+ s.add_dependency(%q<ci_reporter>, [">= 0"])
126
+ end
127
+ end
128
+
@@ -35,7 +35,7 @@ module Denormalizer
35
35
  "denormalizer_method_outputs.denormalized_object_method" => method_name.to_s,
36
36
  "denormalizer_method_outputs.method_output" => Denormalizer::MethodOutput::TrueOutput
37
37
  }
38
- true_scope_name = "denormalized_#{method_name.to_s.gsub('?', '')}".to_sym
38
+ true_scope_name = "denormalized_#{method_name.to_s.gsub('?', '')}".pluralize.to_sym
39
39
  scope true_scope_name, lambda { joins(:denormalized_method_outputs).where(true_attributes)}
40
40
 
41
41
  # setup false scope
@@ -43,8 +43,14 @@ module Denormalizer
43
43
  "denormalizer_method_outputs.denormalized_object_method" => method_name.to_s,
44
44
  "denormalizer_method_outputs.method_output" => Denormalizer::MethodOutput::FalseOutput
45
45
  }
46
- false_scope_name = "denormalized_not_#{method_name.to_s.gsub('?', '')}".to_sym
46
+ false_scope_name = "denormalized_not_#{method_name.to_s.gsub('?', '')}".pluralize.to_sym
47
47
  scope false_scope_name, lambda { joins(:denormalized_method_outputs).where(false_attributes)}
48
+
49
+ instance_method_name = "denormalized_#{method_name.to_s}"
50
+ define_method instance_method_name do
51
+ saved_output = Denormalizer::MethodOutput.by_object_and_method_name(self, method_name).first
52
+ return saved_output.method_output == Denormalizer::MethodOutput::TrueOutput
53
+ end
48
54
  end
49
55
 
50
56
  after_save :method_denormalization
@@ -76,14 +82,16 @@ module Denormalizer
76
82
  method_output = self.send(method_name) ? Denormalizer::MethodOutput::TrueOutput : Denormalizer::MethodOutput::FalseOutput
77
83
 
78
84
  # find a match then create or update based on success
79
- attributes = {
80
- :denormalized_object_type => self.class.name,
81
- :denormalized_object_id => self.id,
82
- :denormalized_object_method => method_name
83
- }
84
- saved_output = Denormalizer::MethodOutput.where(attributes).limit(1).first
85
+ # TODO: refactor this entire section to metho on Denormalizer::MethodOutput (JH 7-13-2012)
86
+ saved_output = Denormalizer::MethodOutput.by_object_and_method_name(self, method_name).first
85
87
  if saved_output.nil?
86
- Denormalizer::MethodOutput.create(attributes.merge({ :method_output => method_output }))
88
+ attributes = {
89
+ :denormalized_object_type => self.class.name,
90
+ :denormalized_object_id => self.id,
91
+ :denormalized_object_method => method_name,
92
+ :method_output => method_output
93
+ }
94
+ Denormalizer::MethodOutput.create(attributes)
87
95
  else
88
96
  saved_output.method_output = method_output
89
97
  saved_output.save
@@ -93,6 +101,8 @@ module Denormalizer
93
101
  end
94
102
 
95
103
  def association_denormalization
104
+ # TODO: make sure this doesn't loop infinitely (JH 7-13-2012)
105
+ # if two models have a circular association or a model has a self association, this will not work
96
106
  self.denormalized_associations.each do |assoc_method|
97
107
  assoc = self.send(assoc_method)
98
108
  if assoc.is_a?(Array)
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe "association denormalization" do
4
+ before(:each) { @printing = Printing.new }
5
+ subject { @printing }
6
+
7
+ describe "class methods" do
8
+ describe "also_denormalize" do
9
+ it "should add to the denormalized_associations array" do
10
+ @printing.denormalized_associations.should include :book
11
+ end
12
+
13
+ it "should add association_denormalization to the after_save" do
14
+ @printing.should_receive(:association_denormalization)
15
+ @printing.save(:validate => false)
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "instance methods" do
21
+ describe "association_denormalization" do
22
+ before(:each) do
23
+ @book = Book.new
24
+ end
25
+
26
+ it "should call method_denormalization for the association" do
27
+ @printing.book = @book
28
+ @book.should_receive(:method_denormalization)
29
+ @printing.association_denormalization
30
+ end
31
+
32
+ it "should call method_denormalization for each member of the association if it is an array" do
33
+ @printing.stub(:book).and_return([@book])
34
+ @book.should_receive(:method_denormalization)
35
+ @printing.association_denormalization
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe "denormalize_all" do
4
+ describe "class methods" do
5
+ describe "denormalize_all" do
6
+ it "should call method_denormalization on all instances of the object" do
7
+ @book = Book.new
8
+ Book.stub(:all).and_return([@book])
9
+ @book.should_receive(:method_denormalization)
10
+ Book.denormalize_all
11
+ end
12
+
13
+ it "should call association_denormalization on all instances of the object" do
14
+ @printing = Printing.new
15
+ Printing.stub(:all).and_return([@printing])
16
+ @printing.should_receive(:association_denormalization)
17
+ Printing.denormalize_all
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+ require 'ruby-debug'
3
+
4
+ describe "method denormalization" do
5
+ before(:each) { @book = Book.new }
6
+ subject { @book }
7
+
8
+ describe "class methods" do
9
+ describe "denormalize" do
10
+ it "should add to the denormalized_method_outputs array" do
11
+ @book.denormalized_methods.should include :short_name?
12
+ @book.denormalized_methods.should include :printed?
13
+ end
14
+
15
+ it "should create a scope called denormalized_method_names for the method method_name?" do
16
+ Book.should respond_to :denormalized_short_names
17
+ end
18
+
19
+ it "should create a scope called denormalized_not_method_names for the method method_name?" do
20
+ Book.should respond_to :denormalized_not_short_names
21
+ end
22
+
23
+ it "should add method_denormalization to the after_save" do
24
+ @book.should_receive(:method_denormalization)
25
+ @book.save(:validate => false)
26
+ end
27
+ end
28
+ end
29
+
30
+ # these tests are dependent on the Book model denormalizing the short_name? and printed?
31
+ describe "scopes" do
32
+ describe "denormalized_short_names" do
33
+ it "should match this sql" do
34
+ sql = Book.denormalized_short_names.to_sql
35
+ sql.should match "INNER JOIN \"denormalizer_method_outputs\" ON \"denormalizer_method_outputs\".\"denormalized_object_id\" = \"books\".\"id\" AND \"denormalizer_method_outputs\".\"denormalized_object_type\" = 'Book'"
36
+ sql.should match "WHERE \"denormalizer_method_outputs\".\"denormalized_object_method\" = 'short_name.' AND \"denormalizer_method_outputs\".\"method_output\" = 1"
37
+ end
38
+ end
39
+
40
+ describe "denormalized_not_short_names" do
41
+ it "should match this sql" do
42
+ sql = Book.denormalized_not_short_names.to_sql
43
+ sql.should match "INNER JOIN \"denormalizer_method_outputs\" ON \"denormalizer_method_outputs\".\"denormalized_object_id\" = \"books\".\"id\" AND \"denormalizer_method_outputs\".\"denormalized_object_type\" = 'Book'"
44
+ sql.should match "WHERE \"denormalizer_method_outputs\".\"denormalized_object_method\" = 'short_name.' AND \"denormalizer_method_outputs\".\"method_output\" = 0"
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "methods" do
50
+ describe "denormalized_short_name?" do
51
+ it "should include the denormalized method" do
52
+ @book.should respond_to :denormalized_short_name?
53
+ end
54
+
55
+ it "should match the actual output if synced" do
56
+ @book.name = "abc"
57
+ @book.save
58
+ @book.short_name?.should equal @book.denormalized_short_name?
59
+ end
60
+ end
61
+
62
+ describe "method_denormalization" do
63
+ before(:each) do
64
+ @book.stub(:new_record?).and_return(false)
65
+ @book.stub(:id).and_return(1000)
66
+ @book.name = "The Tale of Two Cities"
67
+ end
68
+
69
+ it "should do nothing for new records" do
70
+ @book.stub(:new_record?).and_return(true)
71
+ @book.should_not_receive(:denormalized_methods)
72
+ @book.method_denormalization
73
+ end
74
+
75
+ it "should call each denormalized method" do
76
+ @book.should_receive(:short_name?)
77
+ @book.should_receive(:printed?)
78
+ @book.method_denormalization
79
+ end
80
+
81
+ it "should save the output of each denormalized method to the database" do
82
+ @book.method_denormalization
83
+ Denormalizer::MethodOutput.where(:denormalized_object_type => "Book", :denormalized_object_id => 1000, :denormalized_object_method => "short_name?").should_not be_empty
84
+ end
85
+ end
86
+ end
87
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: denormalizer
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jeremiah Hemphill
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-07-06 00:00:00 Z
13
+ date: 2012-07-13 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -142,6 +142,7 @@ files:
142
142
  - Rakefile
143
143
  - VERSION
144
144
  - app/models/denormalizer/method_output.rb
145
+ - denormalizer.gemspec
145
146
  - lib/denormalizer.rb
146
147
  - lib/denormalizer/config.rb
147
148
  - lib/denormalizer/denormalize.rb
@@ -150,6 +151,8 @@ files:
150
151
  - lib/generators/denormalizer/install_generator.rb
151
152
  - lib/generators/denormalizer/templates/config.rb
152
153
  - lib/generators/denormalizer/templates/migrations/install_migration.rb.erb
154
+ - spec/association_denormalization_spec.rb
155
+ - spec/denormalize_all_spec.rb
153
156
  - spec/denormalizer_spec.rb
154
157
  - spec/dummy/Rakefile
155
158
  - spec/dummy/app/controllers/application_controller.rb
@@ -189,6 +192,7 @@ files:
189
192
  - spec/dummy/public/stylesheets/.gitkeep
190
193
  - spec/dummy/script/rails
191
194
  - spec/integration/navigation_spec.rb
195
+ - spec/method_denormalization_spec.rb
192
196
  - spec/spec_helper.rb
193
197
  homepage: http://github.com/jeremiahishere/denormalizer
194
198
  licenses:
@@ -203,7 +207,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
203
207
  requirements:
204
208
  - - ">="
205
209
  - !ruby/object:Gem::Version
206
- hash: -2066004463778552460
210
+ hash: 3695816084296706715
207
211
  segments:
208
212
  - 0
209
213
  version: "0"