updateable_views_inheritance 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +110 -0
  5. data/Rakefile +35 -0
  6. data/doc/template/horo.rb +613 -0
  7. data/lib/generators/updateable_views_inheritance_migration/USAGE +8 -0
  8. data/lib/generators/updateable_views_inheritance_migration/templates/migration.rb +17 -0
  9. data/lib/generators/updateable_views_inheritance_migration/uvi_migration_generator.rb +12 -0
  10. data/lib/updateable_views_inheritance.rb +5 -0
  11. data/lib/updateable_views_inheritance/active_record.rb +16 -0
  12. data/lib/updateable_views_inheritance/postgresql_adapter.rb +450 -0
  13. data/lib/updateable_views_inheritance/version.rb +3 -0
  14. data/tasks/updateable_views_inheritance_tasks.rake +19 -0
  15. data/test/app/models/bicycle.rb +3 -0
  16. data/test/app/models/boat.rb +3 -0
  17. data/test/app/models/car.rb +3 -0
  18. data/test/app/models/electric_locomotive.rb +3 -0
  19. data/test/app/models/electric_train.rb +3 -0
  20. data/test/app/models/locomotive.rb +3 -0
  21. data/test/app/models/maglev_locomotive.rb +3 -0
  22. data/test/app/models/maglev_train.rb +3 -0
  23. data/test/app/models/rack_locomotive.rb +3 -0
  24. data/test/app/models/rack_train.rb +3 -0
  25. data/test/app/models/railed_vehicle.rb +3 -0
  26. data/test/app/models/steam_locomotive.rb +3 -0
  27. data/test/app/models/steam_train.rb +3 -0
  28. data/test/app/models/train.rb +3 -0
  29. data/test/app/models/vehicle.rb +3 -0
  30. data/test/app/models/wheeled_vehicle.rb +3 -0
  31. data/test/config/database.yml +19 -0
  32. data/test/config/environment.rb +14 -0
  33. data/test/config/routes.rb +3 -0
  34. data/test/config/schema.rb +3 -0
  35. data/test/content_test.rb +66 -0
  36. data/test/database.yml +7 -0
  37. data/test/deep_hierarchy_test.rb +64 -0
  38. data/test/fixtures/bicycles.yml +6 -0
  39. data/test/fixtures/boats.yml +6 -0
  40. data/test/fixtures/cars.yml +12 -0
  41. data/test/fixtures/electric_locomotives.yml +6 -0
  42. data/test/fixtures/electric_trains.yml +7 -0
  43. data/test/fixtures/maglev_locomotives.yml +7 -0
  44. data/test/fixtures/maglev_trains.yml +8 -0
  45. data/test/fixtures/migrations/1_add_class_table_inheritance.rb +15 -0
  46. data/test/fixtures/migrations/2_create_with_default_table.rb +19 -0
  47. data/test/fixtures/migrations/3_create_with_explicit_table.rb +11 -0
  48. data/test/fixtures/migrations/4_create_deeper_hierarchy.rb +11 -0
  49. data/test/fixtures/migrations/5_default_column_values.rb +13 -0
  50. data/test/fixtures/migrations/6_single_table_inheritance_view.rb +10 -0
  51. data/test/fixtures/migrations/7_second_deep_hierarchy.rb +70 -0
  52. data/test/fixtures/migrations/8_second_single_table_inheritance_view.rb +10 -0
  53. data/test/fixtures/rack_trains.yml +7 -0
  54. data/test/fixtures/steam_locomotives.yml +7 -0
  55. data/test/fixtures/steam_trains.yml +8 -0
  56. data/test/migration_test.rb +30 -0
  57. data/test/schema_test.rb +179 -0
  58. data/test/single_table_inheritance.rb +141 -0
  59. data/test/test_helper.rb +80 -0
  60. data/updateable_views_inheritance.gemspec +26 -0
  61. metadata +219 -0
@@ -0,0 +1,3 @@
1
+ module Uvi
2
+ VERSION = "1.1.1"
3
+ end
@@ -0,0 +1,19 @@
1
+ namespace :updateable_views_inheritance do
2
+ desc 'Generate fixture for updateable_views_inheritance table in test/fixtures'
3
+ task :fixture => :environment do
4
+ table_name = 'updateable_views_inheritance'
5
+ f = File.new(File.expand_path("test/fixtures/#{table_name}.yml", Rails.root), "w+")
6
+ f.puts(ActiveRecord::Base.connection.select_all("SELECT * FROM #{table_name}").inject({}) { |hsh, record|
7
+ hsh.merge({record['child_aggregate_view'] => record})
8
+ }.to_yaml)
9
+ f.close
10
+ end
11
+
12
+ desc 'Generate migration to create special table for the updateable_views_inheritance gem'
13
+ task :setup => :environment do
14
+ raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations?
15
+ require 'rails_generator'
16
+ require 'rails_generator/scripts/generate'
17
+ Rails::Generator::Scripts::Generate.new.run(["updateable_views_inheritance_migration", ENV["MIGRATION"] || "AddUpdatebleViewsInheritance"])
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ class Bicycle < WheeledVehicle
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Boat < Vehicle
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Car < WheeledVehicle
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class ElectricLocomotive < Locomotive
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class ElectricTrain < Train
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Locomotive < ActiveRecord::Base
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class MaglevLocomotive < ElectricLocomotive
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class MaglevTrain < ElectricTrain
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class RackLocomotive < Locomotive
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class RackTrain < Train
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class RailedVehicle < Vehicle
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class SteamLocomotive < Locomotive
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class SteamTrain < Train
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Train < RailedVehicle
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class Vehicle < ActiveRecord::Base
2
+ self.inheritance_column = :vehicle_type
3
+ end
@@ -0,0 +1,3 @@
1
+ class WheeledVehicle < Vehicle
2
+
3
+ end
@@ -0,0 +1,19 @@
1
+ test:
2
+ adapter: sqlite3
3
+ dbfile: test.sqlite3.db
4
+
5
+ # adapter: sqlite
6
+ # dbfile: test.sqlite.db
7
+
8
+ # adapter: mysql
9
+ # host: localhost
10
+ # username:
11
+ # password:
12
+ # database: test
13
+
14
+ # adapter: postgresql
15
+ # host: localhost
16
+ # username:
17
+ # password:
18
+ # database: test
19
+
@@ -0,0 +1,14 @@
1
+
2
+ Rails::Initializer.run do |config|
3
+
4
+ config.cache_classes = true
5
+
6
+ config.whiny_nils = true
7
+
8
+ config.action_controller.consider_all_requests_local = true
9
+ config.action_controller.perform_caching = false
10
+
11
+ config.action_mailer.delivery_method = :test
12
+ config.action_mailer.perform_deliveries = true
13
+
14
+ end
@@ -0,0 +1,3 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ ActiveRecord::Schema.define(:version => 2) do
2
+
3
+ end
@@ -0,0 +1,66 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class ClassTableInheritanceContentTest < ActiveSupport::TestCase
4
+ def setup
5
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 5)
6
+ # order of fixtures is important for the test - last loaded should not be with max(id)
7
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :electric_locomotives)
8
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', :steam_locomotives)
9
+ end
10
+
11
+ def teardown
12
+ ActiveRecord::Fixtures.reset_cache
13
+ end
14
+
15
+ def test_find
16
+ locomotive = Locomotive.find(1)
17
+ assert locomotive.kind_of?(SteamLocomotive)
18
+ assert_equal %w(coal_consumption id max_speed name type water_consumption),
19
+ locomotive.attributes.keys.sort, "Could not instantiate properly child"
20
+ end
21
+
22
+ def test_exec_query
23
+ res = ActiveRecord::Base.connection.exec_query(%q{INSERT INTO electric_locomotives (electricity_consumption, max_speed, name, type) VALUES (40, 120, 'test', 'ElectricLocomotive') RETURNING id})
24
+ assert !res.rows.empty?
25
+ assert_equal 3, res.rows.first.first.to_i
26
+ end
27
+
28
+ def test_save_new
29
+ electric_locomotive = ElectricLocomotive.new(:name=> 'BoBo', :max_speed => 40, :electricity_consumption => 12)
30
+ assert electric_locomotive.save, "Couldn't save new"
31
+ assert electric_locomotive.id, "No id of saved object"
32
+ end
33
+
34
+ def test_reset_sequence_after_loading_fixture
35
+ steam_locomotive = SteamLocomotive.new(:name => 'Mogul', :max_speed => 120, :water_consumption => 12.3, :coal_consumption => 54.6)
36
+ assert steam_locomotive.save
37
+ mogul = Locomotive.find(steam_locomotive.id)
38
+ assert mogul.kind_of?(SteamLocomotive)
39
+ end
40
+
41
+ def test_update
42
+ steam_locomotive = Locomotive.find(1)
43
+ steam_locomotive.update_attributes( :name => 'Rocket')
44
+ steam_locomotive.reload
45
+ assert_equal 'Rocket', steam_locomotive.name
46
+ end
47
+
48
+ def test_delete_from_parent_relation
49
+ num_locomotives = Locomotive.count
50
+ num_steam_locomotives = SteamLocomotive.count
51
+ Locomotive.find(1).destroy
52
+ assert_equal num_locomotives - 1, Locomotive.count
53
+ assert_equal num_steam_locomotives - 1, SteamLocomotive.count
54
+ end
55
+
56
+ def test_delete_from_child_relation
57
+ num_locomotives = Locomotive.count
58
+ num_steam_locomotives = SteamLocomotive.count
59
+ SteamLocomotive.find(1).destroy
60
+ assert_equal num_locomotives - 1, Locomotive.count
61
+ assert_equal num_steam_locomotives - 1, SteamLocomotive.count
62
+ end
63
+
64
+
65
+
66
+ end
data/test/database.yml ADDED
@@ -0,0 +1,7 @@
1
+ postgresql:
2
+ adapter: postgresql
3
+ username: postgres
4
+ password: postgres
5
+ database: updateable_views_inheritance_test
6
+ min_messages: ERROR
7
+ prepared_statements: false
@@ -0,0 +1,64 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class DeepHierarchyTest < ActiveSupport::TestCase
4
+ def setup
5
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 8)
6
+ # order of fixtures is important for the test - last loaded should not be with max(id)
7
+ %w(boats electric_trains rack_trains steam_trains cars maglev_trains bicycles).each do |f|
8
+ ActiveRecord::Fixtures.create_fixtures(File.dirname(__FILE__) + '/fixtures/', f)
9
+ end
10
+ @connection = ActiveRecord::Base.connection
11
+ end
12
+
13
+ def teardown
14
+ ActiveRecord::Fixtures.reset_cache
15
+ end
16
+
17
+ def test_deeper_hierarchy
18
+ assert_equal [["boats"], ["railed_vehicles", ["trains", ["electric_trains", ["maglev_trains"]], ["rack_trains"], ["steam_trains"]]], ["wheeled_vehicles", ["bicycles"], ["cars"]]].sort,
19
+ @connection.send(:get_view_hierarchy_for, :vehicles).sort
20
+ end
21
+
22
+ def test_leaves_relations
23
+ hierarchy = @connection.send(:get_view_hierarchy_for, :vehicles)
24
+ assert_equal %w(boats bicycles cars maglev_trains rack_trains steam_trains).sort,
25
+ @connection.send(:get_leaves_relations, hierarchy).sort
26
+ end
27
+
28
+ def test_view_columns
29
+ assert_equal %w(id vehicle_type name number_of_wheels number_of_doors number_of_gears number_of_rails mast_number max_speed water_consumption coal_consumption electricity_consumption bidirectional narrow_gauge magnetic_field rail_system).sort,
30
+ @connection.columns(:all_vehicles).collect{|c| c.name}.sort
31
+ end
32
+
33
+ def test_single_table_inheritance_deeper_hierarchy_records_number
34
+ assert_equal Vehicle.count, @connection.select_value("SELECT count(*) FROM all_vehicles").to_i
35
+ assert_equal SteamTrain.count, @connection.select_value("SELECT count(*) FROM all_vehicles WHERE vehicle_type='SteamTrain'").to_i
36
+ assert_equal ElectricTrain.count - MaglevTrain.count, @connection.select_value("SELECT count(*) FROM all_vehicles WHERE vehicle_type='ElectricTrain'").to_i
37
+ assert_equal RackTrain.count, @connection.select_value("SELECT count(*) FROM all_vehicles WHERE vehicle_type='RackTrain'").to_i
38
+ assert_equal MaglevTrain.count, @connection.select_value("SELECT count(*) FROM all_vehicles WHERE vehicle_type='MaglevTrain'").to_i
39
+ assert_equal Car.count, @connection.select_value("SELECT count(*) FROM all_vehicles WHERE vehicle_type='Car'").to_i
40
+ assert_equal Bicycle.count, @connection.select_value("SELECT count(*) FROM all_vehicles WHERE vehicle_type='Bicycle'").to_i
41
+ assert_equal Boat.count, @connection.select_value("SELECT count(*) FROM all_vehicles WHERE vehicle_type='Boat'").to_i
42
+ end
43
+
44
+ def test_single_table_inheritance_deeper_hierarchy_contents
45
+ mag = MaglevTrain.find(:first)
46
+ assert_equal [mag.id.to_s, mag.name, mag.number_of_rails.to_s, mag.max_speed.to_s, mag.magnetic_field.to_s, (sprintf("%.2f",mag.electricity_consumption))], (@connection.query("SELECT id, name, number_of_rails, max_speed, magnetic_field, electricity_consumption FROM all_vehicles WHERE id=#{mag.id}").first)
47
+ end
48
+
49
+ class OrderColumnsInAggregateView < ActiveRecord::Migration
50
+ def self.up
51
+ rebuild_single_table_inheritance_view(:all_vehicles,:vehicles, %w(max_speed number_of_wheels id))
52
+ end
53
+ end
54
+
55
+ def test_single_table_inheritance_view_order_view_columns
56
+ OrderColumnsInAggregateView.up
57
+ assert_equal %w(max_speed number_of_wheels id),
58
+ (@connection.query("SELECT attname
59
+ FROM pg_class, pg_attribute
60
+ WHERE pg_class.relname = 'all_vehicles'
61
+ AND pg_class.oid = pg_attribute.attrelid
62
+ ORDER BY attnum").flatten)[0..2]
63
+ end
64
+ end
@@ -0,0 +1,6 @@
1
+ bmx:
2
+ id: 1
3
+ name: 'BMX'
4
+ vehicle_type: 'Bicycle'
5
+ number_of_wheels: 2
6
+ number_of_gears: 7
@@ -0,0 +1,6 @@
1
+ ship:
2
+ id: 7
3
+ name: 'Sea side'
4
+ vehicle_type: 'Boat'
5
+ mast_number: 3
6
+
@@ -0,0 +1,12 @@
1
+ volvo:
2
+ id: 2
3
+ name: 'Volvo'
4
+ vehicle_type: 'Car'
5
+ number_of_wheels: 4
6
+ number_of_doors: 4
7
+ jeep:
8
+ id: 8
9
+ name: 'Jeep'
10
+ vehicle_type: 'Car'
11
+ number_of_wheels: 4
12
+ number_of_doors: 4
@@ -0,0 +1,6 @@
1
+ gg1:
2
+ id: 2
3
+ name: 'GG1'
4
+ type: 'ElectricLocomotive'
5
+ max_speed: 160
6
+ electricity_consumption: 3660
@@ -0,0 +1,7 @@
1
+ gg1:
2
+ id: 5
3
+ name: 'GG1'
4
+ vehicle_type: 'ElectricTrain'
5
+ number_of_rails: 2
6
+ max_speed: 160
7
+ electricity_consumption: 3660
@@ -0,0 +1,7 @@
1
+ mag:
2
+ id: 8
3
+ name: 'MAG'
4
+ type: 'MaglevLocomotive'
5
+ max_speed: 120
6
+ electricity_consumption: 4660
7
+ magnetic_field: 1
@@ -0,0 +1,8 @@
1
+ mag:
2
+ id: 6
3
+ name: 'Mag'
4
+ vehicle_type: 'MaglevTrain'
5
+ number_of_rails: 2
6
+ max_speed: 120
7
+ electricity_consumption: 460
8
+ magnetic_field: 1
@@ -0,0 +1,15 @@
1
+ class AddClassTableInheritance < ActiveRecord::Migration
2
+ def self.up
3
+ create_table(:updateable_views_inheritance, :id => false) do |t|
4
+ t.column :parent_relation, :string
5
+ t.column :child_aggregate_view, :string
6
+ t.column :child_relation, :string
7
+ end
8
+
9
+ execute "ALTER TABLE updateable_views_inheritance ADD PRIMARY KEY (parent_relation, child_aggregate_view, child_relation)"
10
+ end
11
+
12
+ def self.down
13
+ drop_table :updateable_views_inheritance
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ class CreateWithDefaultTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :locomotives do |t|
4
+ t.column :name, :string
5
+ t.column :max_speed, :integer
6
+ t.column :type, :string
7
+ end
8
+
9
+ create_child(:steam_locomotives, :parent => :locomotives) do |t|
10
+ t.decimal :water_consumption, :precision => 6, :scale => 2
11
+ t.decimal :coal_consumption, :precision => 6, :scale => 2
12
+ end
13
+ end
14
+
15
+ def self.down
16
+ drop_child :steam_locomotives
17
+ drop_table :locomotives
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ class CreateWithExplicitTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_child(:electric_locomotives, :table => :raw_electric_locomotives, :parent => :locomotives) do |t|
4
+ t.decimal :electricity_consumption, :precision => 6, :scale => 2
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_child :electric_locomotives
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class CreateDeeperHierarchy < ActiveRecord::Migration
2
+ def self.up
3
+ create_child(:maglev_locomotives, :parent => :electric_locomotives) do |t|
4
+ t.column :magnetic_field, :integer
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ drop_child :maglev_locomotives
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ class DefaultColumnValues < ActiveRecord::Migration
2
+ def self.up
3
+ create_child(:rack_locomotives, :parent => :locomotives) do |t|
4
+ t.column :bidirectional, :boolean, :default => false
5
+ t.column :narrow_gauge, :boolean, :default => true
6
+ t.column :rail_system, :string, :default => 'Abt'
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_child :rack_locomotives
12
+ end
13
+ end