denormalizer 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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"