denormalizer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG +6 -0
  4. data/Gemfile +23 -0
  5. data/Gemfile.lock +154 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.rdoc +76 -0
  8. data/Rakefile +49 -0
  9. data/VERSION +1 -0
  10. data/app/models/denormalizer/method_output.rb +9 -0
  11. data/lib/denormalizer/config.rb +30 -0
  12. data/lib/denormalizer/denormalize.rb +109 -0
  13. data/lib/denormalizer/engine.rb +4 -0
  14. data/lib/denormalizer/railtie.rb +13 -0
  15. data/lib/denormalizer.rb +2 -0
  16. data/lib/generators/denormalizer/install_generator.rb +41 -0
  17. data/lib/generators/denormalizer/templates/config.rb +3 -0
  18. data/lib/generators/denormalizer/templates/migrations/install_migration.rb.erb +20 -0
  19. data/spec/denormalizer_spec.rb +7 -0
  20. data/spec/dummy/Rakefile +7 -0
  21. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  22. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  23. data/spec/dummy/app/models/book.rb +15 -0
  24. data/spec/dummy/app/models/printing.rb +4 -0
  25. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  26. data/spec/dummy/config/application.rb +45 -0
  27. data/spec/dummy/config/boot.rb +10 -0
  28. data/spec/dummy/config/database.yml +22 -0
  29. data/spec/dummy/config/environment.rb +5 -0
  30. data/spec/dummy/config/environments/development.rb +26 -0
  31. data/spec/dummy/config/environments/production.rb +49 -0
  32. data/spec/dummy/config/environments/test.rb +35 -0
  33. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  34. data/spec/dummy/config/initializers/denormalizer.rb +3 -0
  35. data/spec/dummy/config/initializers/inflections.rb +10 -0
  36. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  37. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  38. data/spec/dummy/config/initializers/session_store.rb +8 -0
  39. data/spec/dummy/config/locales/en.yml +5 -0
  40. data/spec/dummy/config/routes.rb +58 -0
  41. data/spec/dummy/config.ru +4 -0
  42. data/spec/dummy/db/migrate/20120706021202_book.rb +21 -0
  43. data/spec/dummy/db/migrate/20120706125004_create_denormalizer_tables.rb +20 -0
  44. data/spec/dummy/db/schema.rb +41 -0
  45. data/spec/dummy/public/404.html +26 -0
  46. data/spec/dummy/public/422.html +26 -0
  47. data/spec/dummy/public/500.html +26 -0
  48. data/spec/dummy/public/favicon.ico +0 -0
  49. data/spec/dummy/public/javascripts/application.js +2 -0
  50. data/spec/dummy/public/javascripts/controls.js +965 -0
  51. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  52. data/spec/dummy/public/javascripts/effects.js +1123 -0
  53. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  54. data/spec/dummy/public/javascripts/rails.js +202 -0
  55. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  56. data/spec/dummy/script/rails +6 -0
  57. data/spec/integration/navigation_spec.rb +9 -0
  58. data/spec/spec_helper.rb +33 -0
  59. metadata +224 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/CHANGELOG ADDED
@@ -0,0 +1,6 @@
1
+ == unreleased changes
2
+
3
+ == 0.0.1
4
+
5
+ * Added mixin with denormalize_all, denormalize, and also_denormalize methods
6
+ * Added generator to create the migration and config
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", ">= 3.0.0"
4
+ # Add dependencies required to use your gem here.
5
+ # Example:
6
+ # gem "activesupport", ">= 2.3.5"
7
+
8
+ # Add dependencies to develop your gem here.
9
+ # Include everything needed to run rake, tests, features, etc.
10
+ group :development do
11
+ gem "capybara", ">= 0.4.0"
12
+ gem "sqlite3"
13
+
14
+ gem 'ruby-debug19'
15
+ gem "rspec", "~> 2.6.0"
16
+ gem "rspec-rails", "~>2.6.1"
17
+ gem "yard", "~> 0.6.0"
18
+ gem "database_cleaner"
19
+ gem "jeweler", "~> 1.6.3"
20
+
21
+ # hudson ci
22
+ gem "ci_reporter"
23
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,154 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.2.6)
5
+ actionpack (= 3.2.6)
6
+ mail (~> 2.4.4)
7
+ actionpack (3.2.6)
8
+ activemodel (= 3.2.6)
9
+ activesupport (= 3.2.6)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ journey (~> 1.0.1)
13
+ rack (~> 1.4.0)
14
+ rack-cache (~> 1.2)
15
+ rack-test (~> 0.6.1)
16
+ sprockets (~> 2.1.3)
17
+ activemodel (3.2.6)
18
+ activesupport (= 3.2.6)
19
+ builder (~> 3.0.0)
20
+ activerecord (3.2.6)
21
+ activemodel (= 3.2.6)
22
+ activesupport (= 3.2.6)
23
+ arel (~> 3.0.2)
24
+ tzinfo (~> 0.3.29)
25
+ activeresource (3.2.6)
26
+ activemodel (= 3.2.6)
27
+ activesupport (= 3.2.6)
28
+ activesupport (3.2.6)
29
+ i18n (~> 0.6)
30
+ multi_json (~> 1.0)
31
+ addressable (2.2.8)
32
+ archive-tar-minitar (0.5.2)
33
+ arel (3.0.2)
34
+ builder (3.0.0)
35
+ capybara (1.1.2)
36
+ mime-types (>= 1.16)
37
+ nokogiri (>= 1.3.3)
38
+ rack (>= 1.0.0)
39
+ rack-test (>= 0.5.4)
40
+ selenium-webdriver (~> 2.0)
41
+ xpath (~> 0.1.4)
42
+ childprocess (0.3.3)
43
+ ffi (~> 1.0.6)
44
+ ci_reporter (1.7.0)
45
+ builder (>= 2.1.2)
46
+ columnize (0.3.6)
47
+ database_cleaner (0.7.2)
48
+ diff-lcs (1.1.3)
49
+ erubis (2.7.0)
50
+ ffi (1.0.11)
51
+ git (1.2.5)
52
+ hike (1.2.1)
53
+ i18n (0.6.0)
54
+ jeweler (1.6.4)
55
+ bundler (~> 1.0)
56
+ git (>= 1.2.5)
57
+ rake
58
+ journey (1.0.4)
59
+ json (1.7.3)
60
+ libwebsocket (0.1.3)
61
+ addressable
62
+ linecache19 (0.5.12)
63
+ ruby_core_source (>= 0.1.4)
64
+ mail (2.4.4)
65
+ i18n (>= 0.4.0)
66
+ mime-types (~> 1.16)
67
+ treetop (~> 1.4.8)
68
+ mime-types (1.19)
69
+ multi_json (1.3.6)
70
+ nokogiri (1.5.5)
71
+ polyglot (0.3.3)
72
+ rack (1.4.1)
73
+ rack-cache (1.2)
74
+ rack (>= 0.4)
75
+ rack-ssl (1.3.2)
76
+ rack
77
+ rack-test (0.6.1)
78
+ rack (>= 1.0)
79
+ rails (3.2.6)
80
+ actionmailer (= 3.2.6)
81
+ actionpack (= 3.2.6)
82
+ activerecord (= 3.2.6)
83
+ activeresource (= 3.2.6)
84
+ activesupport (= 3.2.6)
85
+ bundler (~> 1.0)
86
+ railties (= 3.2.6)
87
+ railties (3.2.6)
88
+ actionpack (= 3.2.6)
89
+ activesupport (= 3.2.6)
90
+ rack-ssl (~> 1.3.2)
91
+ rake (>= 0.8.7)
92
+ rdoc (~> 3.4)
93
+ thor (< 2.0, >= 0.14.6)
94
+ rake (0.9.2.2)
95
+ rdoc (3.12)
96
+ json (~> 1.4)
97
+ rspec (2.6.0)
98
+ rspec-core (~> 2.6.0)
99
+ rspec-expectations (~> 2.6.0)
100
+ rspec-mocks (~> 2.6.0)
101
+ rspec-core (2.6.4)
102
+ rspec-expectations (2.6.0)
103
+ diff-lcs (~> 1.1.2)
104
+ rspec-mocks (2.6.0)
105
+ rspec-rails (2.6.1)
106
+ actionpack (~> 3.0)
107
+ activesupport (~> 3.0)
108
+ railties (~> 3.0)
109
+ rspec (~> 2.6.0)
110
+ ruby-debug-base19 (0.11.25)
111
+ columnize (>= 0.3.1)
112
+ linecache19 (>= 0.5.11)
113
+ ruby_core_source (>= 0.1.4)
114
+ ruby-debug19 (0.11.6)
115
+ columnize (>= 0.3.1)
116
+ linecache19 (>= 0.5.11)
117
+ ruby-debug-base19 (>= 0.11.19)
118
+ ruby_core_source (0.1.5)
119
+ archive-tar-minitar (>= 0.5.2)
120
+ rubyzip (0.9.9)
121
+ selenium-webdriver (2.24.0)
122
+ childprocess (>= 0.2.5)
123
+ libwebsocket (~> 0.1.3)
124
+ multi_json (~> 1.0)
125
+ rubyzip
126
+ sprockets (2.1.3)
127
+ hike (~> 1.2)
128
+ rack (~> 1.0)
129
+ tilt (!= 1.3.0, ~> 1.1)
130
+ sqlite3 (1.3.6)
131
+ thor (0.15.4)
132
+ tilt (1.3.3)
133
+ treetop (1.4.10)
134
+ polyglot
135
+ polyglot (>= 0.3.1)
136
+ tzinfo (0.3.33)
137
+ xpath (0.1.4)
138
+ nokogiri (~> 1.3)
139
+ yard (0.6.8)
140
+
141
+ PLATFORMS
142
+ ruby
143
+
144
+ DEPENDENCIES
145
+ capybara (>= 0.4.0)
146
+ ci_reporter
147
+ database_cleaner
148
+ jeweler (~> 1.6.3)
149
+ rails (>= 3.0.0)
150
+ rspec (~> 2.6.0)
151
+ rspec-rails (~> 2.6.1)
152
+ ruby-debug19
153
+ sqlite3
154
+ yard (~> 0.6.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Jeremiah Hemphill
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,76 @@
1
+ = denormalizer
2
+
3
+ Run and cache methods so they can be used later. Create chainable scopes using the cached outputs of the methods.
4
+
5
+ == Installation
6
+
7
+ Add to your Gemfile
8
+
9
+ gem "denormalizer"
10
+
11
+ Run the installer
12
+
13
+ rails generate denormalizer:install
14
+ rake db:migrate
15
+
16
+ Denormalize a method in a model. This will run the method and save the result every time the model is updated.
17
+
18
+ class Widget < ActiveRecord::Base
19
+ def active?
20
+ do_something_complex
21
+ end
22
+ denormalize :active?
23
+ end
24
+
25
+ Denormalize associations. This will run the denormalization method on each of the objects in the association.
26
+
27
+ class Item < ActiveRecord::Base
28
+ has_many :widgets
29
+ also_denormalize :widgets
30
+ end
31
+
32
+ Use the denormalized data
33
+
34
+ Book.denormalized_active
35
+ Book.denormalized_not_active
36
+
37
+ Book.first.denormalized_active? (coming soon)
38
+
39
+ == Thought Process
40
+
41
+ I am trying to avoid duplicating complex code in instance methods and scopes. Given this method,
42
+
43
+ def active?
44
+ received_at >= Time.now && items.expired.empty?
45
+ end
46
+
47
+ You have two choices to get all active records,
48
+
49
+ def self.active
50
+ all.select(&:active?)
51
+ end
52
+
53
+ scope :active, lambda { where(["widgets.received_at >= ?", Time.now]).where("(select count(*) from items where items.widget_id=widgets.id and (expired_at is null or expired_at >= ?)) = 0", Time.now]) }
54
+
55
+ The first minimizes code duplication but is not chainable and often slower than the pure sql version. The second solution is fast and chainable but requires two updates every time the active? criteria needs to be updated. Additionally, it requires an updated whenever the Item model's expired scope is updated.
56
+
57
+ == Todo
58
+
59
+ * Improve test coverage
60
+ * Add methods to directly access denormalized data from model instances
61
+
62
+ == Contributing to denormalizer
63
+
64
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
65
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
66
+ * Fork the project.
67
+ * Start a feature/bugfix branch.
68
+ * Commit and push until you are happy with your contribution.
69
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
70
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
71
+
72
+ == Copyright
73
+
74
+ Copyright (c) 2012 Jeremiah Hemphill. See LICENSE.txt for
75
+ further details.
76
+
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "denormalizer"
18
+ gem.homepage = "http://github.com/jeremiahishere/denormalizer"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Cache method outputs}
21
+ gem.description = %Q{Cache method outputs and automatically create chainable scopes based on their outputs}
22
+ gem.email = "jeremiah@cloudspace.com"
23
+ gem.authors = ["Jeremiah Hemphill"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rdoc/task'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "denormalizer #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,9 @@
1
+ class Denormalizer::MethodOutput < ActiveRecord::Base
2
+ set_table_name "denormalizer_method_outputs"
3
+
4
+ belongs_to :denormalized_object, :polymorphic => true
5
+ validates_presence_of :denormalized_object_type, :denormalized_object_id, :denormalized_object_method, :method_output
6
+
7
+ FalseOutput = 0
8
+ TrueOutput = 1
9
+ end
@@ -0,0 +1,30 @@
1
+ # this file was stolen from kaminari
2
+ require 'active_support/configurable'
3
+
4
+ module Denormalizer
5
+
6
+ # create new configs by passing a block with the config assignment
7
+ def self.configure(&block)
8
+ yield @config ||= Denormalizer::Configuration.new
9
+ end
10
+
11
+ def self.config
12
+ @config
13
+ end
14
+
15
+ # setup config data
16
+ class Configuration
17
+ include ActiveSupport::Configurable
18
+ # config_accessor :sample_config_key
19
+
20
+ def param_name
21
+ config.param_name.respond_to?(:call) ? config.param_name.call() : config.param_name
22
+ end
23
+ end
24
+
25
+ # setup default options
26
+ # this should match the generator config that goes in the initializer file
27
+ configure do |config|
28
+ # config.sample_config_key =' sample_config_value'
29
+ end
30
+ end
@@ -0,0 +1,109 @@
1
+ module Denormalizer
2
+ module Denormalize
3
+
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def denormalize_all
10
+ all.each do |o|
11
+ # this could easily be rewritten in a less stupid way
12
+ o.method_denormalization if self.respond_to? :denormalized_methods
13
+ o.association_denormalization if self.respond_to? :denormalized_associations
14
+ end
15
+ end
16
+
17
+ def denormalize(args)
18
+ # setup list of denormalized methods
19
+ mattr_accessor :denormalized_methods unless respond_to? :denormalized_methods
20
+ self.denormalized_methods = [] unless self.denormalized_methods.is_a?(Array)
21
+
22
+ # add association
23
+ has_many :denormalized_method_outputs, :class_name => 'Denormalizer::MethodOutput', :as => :denormalized_object, :dependent => :destroy
24
+
25
+ # add args to denormalized method list
26
+ args = [args] unless args.is_a?(Array)
27
+ self.denormalized_methods |= args
28
+
29
+ # create scopes
30
+ # note that at some point, we probably need to identify these as denormalized scopes (JH 7-5-2012)
31
+ # dn_method_name maybe
32
+ args.each do |method_name|
33
+ # setup true scope
34
+ true_attributes = {
35
+ "denormalizer_method_outputs.denormalized_object_method" => method_name.to_s,
36
+ "denormalizer_method_outputs.method_output" => Denormalizer::MethodOutput::TrueOutput
37
+ }
38
+ true_scope_name = "denormalized_#{method_name.to_s.gsub('?', '')}".to_sym
39
+ scope true_scope_name, lambda { joins(:denormalized_method_outputs).where(true_attributes)}
40
+
41
+ # setup false scope
42
+ false_attributes = {
43
+ "denormalizer_method_outputs.denormalized_object_method" => method_name.to_s,
44
+ "denormalizer_method_outputs.method_output" => Denormalizer::MethodOutput::FalseOutput
45
+ }
46
+ false_scope_name = "denormalized_not_#{method_name.to_s.gsub('?', '')}".to_sym
47
+ scope false_scope_name, lambda { joins(:denormalized_method_outputs).where(false_attributes)}
48
+ end
49
+
50
+ after_save :method_denormalization
51
+
52
+ include Denormalizer::Denormalize::InstanceMethods
53
+ end
54
+
55
+ def also_denormalize(args)
56
+ mattr_accessor :denormalized_associations unless respond_to? :denormalized_associations
57
+ self.denormalized_associations = [] unless self.denormalized_associations.is_a?(Array)
58
+
59
+ args = [args] unless args.is_a?(Array)
60
+ self.denormalized_associations |= args
61
+
62
+ after_save :association_denormalization
63
+
64
+ include Denormalizer::Denormalize::InstanceMethods
65
+ end
66
+ end
67
+
68
+ module InstanceMethods
69
+
70
+ def method_denormalization
71
+ # don't even try if a new record
72
+ if !new_record?
73
+ # iterate over the saved methods
74
+ self.denormalized_methods.each do |method_name|
75
+ # run the method and save the result
76
+ method_output = self.send(method_name) ? Denormalizer::MethodOutput::TrueOutput : Denormalizer::MethodOutput::FalseOutput
77
+
78
+ # 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
+ if saved_output.nil?
86
+ Denormalizer::MethodOutput.create(attributes.merge({ :method_output => method_output }))
87
+ else
88
+ saved_output.method_output = method_output
89
+ saved_output.save
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ def association_denormalization
96
+ self.denormalized_associations.each do |assoc_method|
97
+ assoc = self.send(assoc_method)
98
+ if assoc.is_a?(Array)
99
+ assoc.each do |a|
100
+ a.method_denormalization
101
+ end
102
+ else
103
+ assoc.method_denormalization
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,4 @@
1
+ module Denormalizer
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails'
2
+
3
+ require 'denormalizer/config'
4
+
5
+ module Denormalizer
6
+ class Railtie < ::Rails::Railtie
7
+ initializer 'denormalizer' do |app|
8
+ require "denormalizer/denormalize"
9
+ ActiveRecord::Base.send :include, Denormalizer::Denormalize
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,2 @@
1
+ require "denormalizer/railtie"
2
+ require "denormalizer/engine"
@@ -0,0 +1,41 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'active_record'
4
+ require 'rails/generators/active_record'
5
+
6
+ module Denormalizer
7
+ module Generators
8
+ class InstallGenerator < Rails::Generators::Base
9
+ include Rails::Generators::Migration
10
+
11
+ source_root File.expand_path(File.join(File.dirname(__FILE__), "templates"))
12
+
13
+ desc <<DESC
14
+ Description:
15
+ Copies over migrations and config for the denormalizer.
16
+ DESC
17
+
18
+ # Implement the required interface for Rails::Generators::Migration.
19
+ # thanks Kaminari gem for this bit of code
20
+ def self.next_migration_number(dirname) #:nodoc:
21
+ next_migration_number = current_migration_number(dirname) + 1
22
+ if ActiveRecord::Base.timestamped_migrations
23
+ [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
24
+ else
25
+ "%.3d" % next_migration_number
26
+ end
27
+ end
28
+
29
+ # Creates the config file
30
+ # Commented out until the config actually has information
31
+ def copy_config_file
32
+ copy_file "config.rb", "config/initializers/denormalizer.rb"
33
+ end
34
+
35
+ # Creates the migration
36
+ def copy_migration
37
+ migration_template "migrations/install_migration.rb.erb", "db/migrate/create_denormalizer_tables.rb"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ Denormalizer.configure do |config|
2
+ # config.sample_config_key =' sample_config_value'
3
+ end
@@ -0,0 +1,20 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :denormalizer_method_outputs do |t|
4
+ t.string :denormalized_object_type
5
+ t.integer :denormalized_object_id
6
+ t.string :denormalized_object_method
7
+ t.integer :method_output
8
+
9
+ t.timestamps
10
+ end
11
+ # used to get the result of a method from a single single object
12
+ add_index :denormalizer_method_outputs, [:denormalized_object_type, :denormalized_object_id, :denormalized_object_method], :name => "denormalized_method_object_pair"
13
+ # used to get all of the instances of a class with the same output for the given method
14
+ add_index :denormalizer_method_outputs, [:denormalized_object_type, :denormalized_object_method, :method_output], :name => "denormalized_method_type_output_triplet"
15
+ end
16
+
17
+ def self.down
18
+ drop_table :denormalizer_method_outputs
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Denormalizer do
4
+ it "should be valid" do
5
+ Denormalizer.should be_a(Module)
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,15 @@
1
+ class Book < ActiveRecord::Base
2
+ has_many :printings
3
+
4
+ validates_presence_of :name
5
+
6
+ def short_name?
7
+ name.length < 5
8
+ end
9
+ denormalize :short_name?
10
+
11
+ def printed?
12
+ !printings.empty?
13
+ end
14
+ denormalize :printed?
15
+ end
@@ -0,0 +1,4 @@
1
+ class Printing < ActiveRecord::Base
2
+ belongs_to :book
3
+ also_denormalize :book
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>