updateable_views_inheritance 1.1.1

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.
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