pg_morph 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +119 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +62 -0
  6. data/Rakefile +8 -0
  7. data/docs/pg_morph.png +0 -0
  8. data/lib/pg_morph/adapter.rb +39 -0
  9. data/lib/pg_morph/naming.rb +37 -0
  10. data/lib/pg_morph/polymorphic.rb +158 -0
  11. data/lib/pg_morph/railtie.rb +11 -0
  12. data/lib/pg_morph/version.rb +3 -0
  13. data/lib/pg_morph.rb +16 -0
  14. data/pg_morph.gemspec +31 -0
  15. data/spec/dummy/.rspec +1 -0
  16. data/spec/dummy/Rakefile +6 -0
  17. data/spec/dummy/app/models/.keep +0 -0
  18. data/spec/dummy/app/models/comment.rb +3 -0
  19. data/spec/dummy/app/models/like.rb +3 -0
  20. data/spec/dummy/app/models/post.rb +3 -0
  21. data/spec/dummy/bin/bundle +3 -0
  22. data/spec/dummy/bin/rails +4 -0
  23. data/spec/dummy/bin/rake +4 -0
  24. data/spec/dummy/config/application.rb +24 -0
  25. data/spec/dummy/config/boot.rb +4 -0
  26. data/spec/dummy/config/database.yml +8 -0
  27. data/spec/dummy/config/database.yml.example +8 -0
  28. data/spec/dummy/config/environment.rb +5 -0
  29. data/spec/dummy/config/environments/test.rb +36 -0
  30. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  31. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  32. data/spec/dummy/config/initializers/inflections.rb +16 -0
  33. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  34. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  35. data/spec/dummy/config/initializers/session_store.rb +3 -0
  36. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  37. data/spec/dummy/config/locales/en.yml +23 -0
  38. data/spec/dummy/config/routes.rb +56 -0
  39. data/spec/dummy/config.ru +4 -0
  40. data/spec/dummy/db/migrate/20140401124656_create_comments.rb +9 -0
  41. data/spec/dummy/db/migrate/20140401124705_create_posts.rb +9 -0
  42. data/spec/dummy/db/migrate/20140401124727_create_likes.rb +10 -0
  43. data/spec/dummy/db/schema.rb +38 -0
  44. data/spec/dummy/db/seeds.rb +7 -0
  45. data/spec/pg_morph/adapter_integration_spec.rb +89 -0
  46. data/spec/pg_morph/adapter_spec.rb +31 -0
  47. data/spec/pg_morph/naming_spec.rb +29 -0
  48. data/spec/pg_morph/polymorphic_integration_spec.rb +86 -0
  49. data/spec/pg_morph/polymorphic_spec.rb +98 -0
  50. data/spec/spec_helper.rb +16 -0
  51. metadata +246 -0
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4
+ # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5
+
6
+ # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7
+ # Rails.backtrace_cleaner.remove_silencers!
@@ -0,0 +1,4 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Configure sensitive parameters which will be filtered from the log file.
4
+ Rails.application.config.filter_parameters += [:password]
@@ -0,0 +1,16 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new inflection rules using the following format. Inflections
4
+ # are locale specific, and you may define rules for as many different
5
+ # locales as you wish. All of these examples are active by default:
6
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
7
+ # inflect.plural /^(ox)$/i, '\1en'
8
+ # inflect.singular /^(ox)en/i, '\1'
9
+ # inflect.irregular 'person', 'people'
10
+ # inflect.uncountable %w( fish sheep )
11
+ # end
12
+
13
+ # These inflection rules are supported but not enabled by default:
14
+ # ActiveSupport::Inflector.inflections(:en) do |inflect|
15
+ # inflect.acronym 'RESTful'
16
+ # end
@@ -0,0 +1,5 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Add new mime types for use in respond_to blocks:
4
+ # Mime::Type.register "text/richtext", :rtf
5
+ # Mime::Type.register_alias "text/html", :iphone
@@ -0,0 +1,12 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Your secret key is used for verifying the integrity of signed cookies.
4
+ # If you change this key, all old signed cookies will become invalid!
5
+
6
+ # Make sure the secret is at least 30 characters and all random,
7
+ # no regular words or you'll be exposed to dictionary attacks.
8
+ # You can use `rake secret` to generate a secure secret key.
9
+
10
+ # Make sure your secret_key_base is kept private
11
+ # if you're sharing your code publicly.
12
+ Dummy::Application.config.secret_key_base = 'b2e679b42a15ee93bd8344916b0a91c888b96a1707b76675e5b6c51b7849c7a41b461cc18ffff1ea9ce025d2bf9f902db938339285a7d66af630dc9a7b9b6eff'
@@ -0,0 +1,3 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
@@ -0,0 +1,14 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # This file contains settings for ActionController::ParamsWrapper which
4
+ # is enabled by default.
5
+
6
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
+ ActiveSupport.on_load(:action_controller) do
8
+ wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
9
+ end
10
+
11
+ # To enable root element in JSON for ActiveRecord objects.
12
+ # ActiveSupport.on_load(:active_record) do
13
+ # self.include_root_in_json = true
14
+ # end
@@ -0,0 +1,23 @@
1
+ # Files in the config/locales directory are used for internationalization
2
+ # and are automatically loaded by Rails. If you want to use locales other
3
+ # than English, add the necessary files in this directory.
4
+ #
5
+ # To use the locales, use `I18n.t`:
6
+ #
7
+ # I18n.t 'hello'
8
+ #
9
+ # In views, this is aliased to just `t`:
10
+ #
11
+ # <%= t('hello') %>
12
+ #
13
+ # To use a different locale, set it with `I18n.locale`:
14
+ #
15
+ # I18n.locale = :es
16
+ #
17
+ # This would use the information in config/locales/es.yml.
18
+ #
19
+ # To learn more, please read the Rails Internationalization guide
20
+ # available at http://guides.rubyonrails.org/i18n.html.
21
+
22
+ en:
23
+ hello: "Hello world"
@@ -0,0 +1,56 @@
1
+ Dummy::Application.routes.draw do
2
+ # The priority is based upon order of creation: first created -> highest priority.
3
+ # See how all your routes lay out with "rake routes".
4
+
5
+ # You can have the root of your site routed with "root"
6
+ # root 'welcome#index'
7
+
8
+ # Example of regular route:
9
+ # get 'products/:id' => 'catalog#view'
10
+
11
+ # Example of named route that can be invoked with purchase_url(id: product.id)
12
+ # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
13
+
14
+ # Example resource route (maps HTTP verbs to controller actions automatically):
15
+ # resources :products
16
+
17
+ # Example resource route with options:
18
+ # resources :products do
19
+ # member do
20
+ # get 'short'
21
+ # post 'toggle'
22
+ # end
23
+ #
24
+ # collection do
25
+ # get 'sold'
26
+ # end
27
+ # end
28
+
29
+ # Example resource route with sub-resources:
30
+ # resources :products do
31
+ # resources :comments, :sales
32
+ # resource :seller
33
+ # end
34
+
35
+ # Example resource route with more complex sub-resources:
36
+ # resources :products do
37
+ # resources :comments
38
+ # resources :sales do
39
+ # get 'recent', on: :collection
40
+ # end
41
+ # end
42
+
43
+ # Example resource route with concerns:
44
+ # concern :toggleable do
45
+ # post 'toggle'
46
+ # end
47
+ # resources :posts, concerns: :toggleable
48
+ # resources :photos, concerns: :toggleable
49
+
50
+ # Example resource route within a namespace:
51
+ # namespace :admin do
52
+ # # Directs /admin/products/* to Admin::ProductsController
53
+ # # (app/controllers/admin/products_controller.rb)
54
+ # resources :products
55
+ # end
56
+ end
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Rails.application
@@ -0,0 +1,9 @@
1
+ class CreateComments < ActiveRecord::Migration
2
+ def change
3
+ create_table :comments do |t|
4
+ t.string :content
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class CreatePosts < ActiveRecord::Migration
2
+ def change
3
+ create_table :posts do |t|
4
+ t.string :content
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class CreateLikes < ActiveRecord::Migration
2
+ def change
3
+ create_table :likes do |t|
4
+ t.string :likeable_type
5
+ t.integer :likeable_id
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20140401124727) do
15
+
16
+ # These are extensions that must be enabled in order to support this database
17
+ enable_extension "plpgsql"
18
+
19
+ create_table "comments", force: true do |t|
20
+ t.string "content"
21
+ t.datetime "created_at"
22
+ t.datetime "updated_at"
23
+ end
24
+
25
+ create_table "likes", force: true do |t|
26
+ t.string "likeable_type"
27
+ t.integer "likeable_id"
28
+ t.datetime "created_at"
29
+ t.datetime "updated_at"
30
+ end
31
+
32
+ create_table "posts", force: true do |t|
33
+ t.string "content"
34
+ t.datetime "created_at"
35
+ t.datetime "updated_at"
36
+ end
37
+
38
+ end
@@ -0,0 +1,7 @@
1
+ # This file should contain all the record creation needed to seed the database with its default values.
2
+ # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3
+ #
4
+ # Examples:
5
+ #
6
+ # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7
+ # Mayor.create(name: 'Emanuel', city: cities.first)
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe PgMorph::Adapter do
4
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
5
+ include PgMorph::Adapter
6
+
7
+ def run(query)
8
+ ActiveRecord::Base.connection.select_value(query)
9
+ end
10
+ end
11
+
12
+ before do
13
+ @adapter = ActiveRecord::Base.connection
14
+ @comments_polymorphic = PgMorph::Polymorphic.new(:likes, :comments, column: :likeable)
15
+ @posts_polymorphic = PgMorph::Polymorphic.new(:likes, :posts, column: :likeable)
16
+ begin
17
+ Like.destroy_all
18
+ Comment.destroy_all
19
+ @adapter.remove_polymorphic_foreign_key(:likes, :comments, column: :likeable)
20
+ @adapter.remove_polymorphic_foreign_key(:likes, :posts, column: :likeable)
21
+ rescue
22
+ end
23
+ end
24
+
25
+ after do
26
+ begin
27
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
28
+ rescue
29
+ end
30
+ end
31
+
32
+ describe '#add_polymorphic_foreign_key' do
33
+ it 'creates proxy table' do
34
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
35
+
36
+ expect(@adapter.run('SELECT id FROM likes_comments')).to be_nil
37
+ end
38
+ end
39
+
40
+ describe '#remove_polymorphic_foreign_key' do
41
+ it 'removes proxy table' do
42
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
43
+ expect(@adapter.run('SELECT id FROM likes_comments')).to be_nil
44
+
45
+ @adapter.remove_polymorphic_foreign_key(:likes, :comments, column: :likeable)
46
+
47
+ -> { @adapter.run('SELECT id FROM likes_comments') }
48
+ .should raise_error ActiveRecord::StatementInvalid
49
+ end
50
+ end
51
+
52
+ describe 'assertions to a partition' do
53
+ it 'works properly' do
54
+ # new record inserted correctly
55
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
56
+ comment = Comment.create(content: 'comment')
57
+ like = Like.create(likeable: comment)
58
+
59
+ expect(Like.count).to eq(1)
60
+ expect(like.id).to eq(Like.last.id)
61
+
62
+ # new record with more partition tables inserted correctly
63
+ @adapter.add_polymorphic_foreign_key(:likes, :posts, column: :likeable)
64
+ post = Post.create(content: 'content')
65
+ like2 = Like.create(likeable: post)
66
+
67
+ expect(Like.count).to eq(2)
68
+ expect(like2.id).to eq(Like.last.id)
69
+
70
+ # after removing partition row not inserted
71
+ like.destroy
72
+ expect(Like.count).to eq(1)
73
+ @adapter.remove_polymorphic_foreign_key(:likes, :comments, column: :likeable)
74
+
75
+ -> { Like.create(likeable: comment) }
76
+ .should raise_error ActiveRecord::StatementInvalid
77
+
78
+ # if no partitions row inserted correctly
79
+ like2.destroy
80
+ expect(Like.count).to eq(0)
81
+ @adapter.remove_polymorphic_foreign_key(:likes, :posts, column: :likeable)
82
+ like4 = Like.create(likeable: post)
83
+
84
+ expect(Like.count).to eq(1)
85
+ expect(like4.id).to eq(Like.last.id)
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe PgMorph::Adapter do
4
+ class FakeAdapter
5
+ include PgMorph::Adapter
6
+
7
+ def execute(sql, name = nil)
8
+ sql_statements << sql
9
+ sql
10
+ end
11
+
12
+ def sql_statements
13
+ @sql_statements || []
14
+ end
15
+ end
16
+
17
+ before do
18
+ @adapter = FakeAdapter.new
19
+ @connection = ActiveRecord::Base.connection
20
+ end
21
+
22
+ it 'add_polymorphic_foreign_key for non postgres adapter' do
23
+ expect { @adapter.add_polymorphic_foreign_key :likes, :posts, column: :likeable }
24
+ .to raise_error PgMorph::Exception
25
+ end
26
+
27
+ it 'remove_polymorphic_foreign_key for non postgres adapter' do
28
+ expect { @adapter.remove_polymorphic_foreign_key :likes, :posts, column: :likeable }
29
+ .to raise_error PgMorph::Exception
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe PgMorph::Naming do
4
+
5
+ Fake = Struct.new(:parent_table, :child_table, :column_name) do
6
+ include PgMorph::Naming
7
+ end
8
+
9
+ before do
10
+ @fake = Fake.new(:foos, :bars, :baz)
11
+ end
12
+
13
+ it { expect(@fake.type).to eq('Bar') }
14
+
15
+ it { expect(@fake.column_name_type).to eq('baz_type') }
16
+
17
+ it { expect(@fake.column_name_id).to eq('baz_id') }
18
+
19
+ it { expect(@fake.proxy_table).to eq('foos_bars') }
20
+
21
+ it { expect(@fake.before_insert_fun_name).to eq('foos_baz_fun') }
22
+
23
+ it { expect(@fake.before_insert_trigger_name).to eq('foos_baz_insert_trigger') }
24
+
25
+ it { expect(@fake.after_insert_fun_name).to eq('delete_from_foos_master_fun') }
26
+
27
+ it { expect(@fake.after_insert_trigger_name).to eq('foos_after_insert_trigger') }
28
+
29
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe PgMorph::Polymorphic do
4
+ ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
5
+ include PgMorph::Adapter
6
+
7
+ def run(query)
8
+ ActiveRecord::Base.connection.select_value(query)
9
+ end
10
+ end
11
+
12
+ before do
13
+ @adapter = ActiveRecord::Base.connection
14
+ @comments_polymorphic = PgMorph::Polymorphic.new(:likes, :comments, column: :likeable)
15
+ @posts_polymorphic = PgMorph::Polymorphic.new(:likes, :posts, column: :likeable)
16
+ begin
17
+ Like.destroy_all
18
+ Comment.destroy_all
19
+ @adapter.remove_polymorphic_foreign_key(:likes, :comments, column: :likeable)
20
+ @adapter.remove_polymorphic_foreign_key(:likes, :posts, column: :likeable)
21
+ rescue
22
+ end
23
+ end
24
+
25
+ describe '#create_trigger_body' do
26
+ before do
27
+ @adapter.stub(:raise_unless_postgres)
28
+ end
29
+
30
+ it 'raises error for updating trigger with duplicated partition' do
31
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
32
+
33
+ -> { @comments_polymorphic.send(:create_trigger_body) }
34
+ .should raise_error PG::Error
35
+ end
36
+
37
+ it 'updates trigger with new partition' do
38
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
39
+
40
+ @posts_polymorphic.send(:create_trigger_body).squeeze(' ').should == %Q{
41
+ IF (NEW.likeable_type = 'Comment') THEN
42
+ INSERT INTO likes_comments VALUES (NEW.*);
43
+ ELSIF (NEW.likeable_type = 'Post') THEN
44
+ INSERT INTO likes_posts VALUES (NEW.*);
45
+ }.squeeze(' ')
46
+ end
47
+ end
48
+
49
+ describe '#create_before_insert_trigger_sql' do
50
+ it 'returns sql' do
51
+ @comments_polymorphic.create_before_insert_trigger_sql.squeeze(' ').should == %Q{
52
+ DROP TRIGGER IF EXISTS likes_likeable_insert_trigger ON likes;
53
+ CREATE TRIGGER likes_likeable_insert_trigger
54
+ BEFORE INSERT ON likes
55
+ FOR EACH ROW EXECUTE PROCEDURE likes_likeable_fun();
56
+ }.squeeze(' ')
57
+ end
58
+ end
59
+
60
+ describe '#remove_partition_table' do
61
+ it 'returns sql' do
62
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
63
+
64
+ @comments_polymorphic.remove_partition_table.squeeze(' ').should == %Q{ DROP TABLE IF EXISTS likes_comments; }
65
+ end
66
+ end
67
+
68
+ describe 'remove_after_insert_trigger_sql' do
69
+ it 'returns sql' do
70
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
71
+
72
+ @comments_polymorphic.remove_after_insert_trigger_sql.squeeze(' ').should == %Q{
73
+ DROP TRIGGER likes_after_insert_trigger ON likes;
74
+ DROP FUNCTION delete_from_likes_master_fun();
75
+ }.squeeze(' ')
76
+ end
77
+
78
+ it 'returns empty string if there are more partitions' do
79
+ @adapter.add_polymorphic_foreign_key(:likes, :comments, column: :likeable)
80
+ @adapter.add_polymorphic_foreign_key(:likes, :posts, column: :likeable)
81
+
82
+ @comments_polymorphic.remove_after_insert_trigger_sql.squeeze(' ').should == ''
83
+ end
84
+ end
85
+
86
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ describe PgMorph::Polymorphic do
4
+ before do
5
+ @polymorphic = PgMorph::Polymorphic.new(:foos, :bars, column: :baz)
6
+ end
7
+
8
+ subject { @polymorphic }
9
+
10
+ it { expect(@polymorphic.column_name).to eq(:baz) }
11
+
12
+ it { expect(@polymorphic.parent_table).to eq(:foos) }
13
+
14
+ it { expect(@polymorphic.child_table).to eq(:bars) }
15
+
16
+ describe '#create_proxy_table_sql' do
17
+ it do
18
+ @polymorphic.create_proxy_table_sql.squeeze(' ').should == %Q{
19
+ CREATE TABLE foos_bars (
20
+ CHECK (baz_type = 'Bar'),
21
+ PRIMARY KEY (id),
22
+ FOREIGN KEY (baz_id) REFERENCES bars(id)
23
+ ) INHERITS (foos);
24
+ }.squeeze(' ')
25
+ end
26
+ end
27
+
28
+ describe '#create_before_insert_trigger_fun_sql' do
29
+ it '' do
30
+ @polymorphic.should_receive(:before_insert_trigger_content)
31
+
32
+ @polymorphic.create_before_insert_trigger_fun_sql
33
+ end
34
+ end
35
+
36
+ describe '#create_trigger_body' do
37
+ it 'returns proper sql for new trigger' do
38
+ @polymorphic.send(:create_trigger_body).squeeze(' ').should == %Q{
39
+ IF (NEW.baz_type = 'Bar') THEN
40
+ INSERT INTO foos_bars VALUES (NEW.*);
41
+ }.squeeze(' ')
42
+ end
43
+ end
44
+
45
+ describe '#before_insert_trigger_content' do
46
+ it '' do
47
+ @polymorphic.send(:before_insert_trigger_content) { 'my block' }.squeeze(' ').should == %Q{
48
+ CREATE OR REPLACE FUNCTION foos_baz_fun() RETURNS TRIGGER AS $$
49
+ BEGIN
50
+ my block
51
+ ELSE
52
+ RAISE EXCEPTION 'Wrong \"baz_type\"=\"%\" used. Create proper partition table and update foos_baz_fun function', NEW.baz_type;
53
+ END IF;
54
+ RETURN NEW;
55
+ END; $$ LANGUAGE plpgsql;
56
+ }.squeeze(' ')
57
+ end
58
+ end
59
+
60
+ describe '#create_after_insert_trigger_fun_sql' do
61
+ it do
62
+ @polymorphic.create_after_insert_trigger_fun_sql.squeeze(' ').should == %Q{
63
+ CREATE OR REPLACE FUNCTION delete_from_foos_master_fun() RETURNS TRIGGER AS $$
64
+ BEGIN
65
+ DELETE FROM ONLY foos WHERE id = NEW.id;
66
+ RETURN NEW;
67
+ END; $$ LANGUAGE plpgsql;
68
+ }.squeeze(' ')
69
+ end
70
+ end
71
+
72
+ describe '#create_after_insert_trigger_sql' do
73
+ it do
74
+ @polymorphic.create_after_insert_trigger_sql.squeeze(' ').should == %Q{
75
+ DROP TRIGGER IF EXISTS foos_after_insert_trigger ON foos;
76
+ CREATE TRIGGER foos_after_insert_trigger
77
+ AFTER INSERT ON foos
78
+ FOR EACH ROW EXECUTE PROCEDURE delete_from_foos_master_fun();
79
+ }.squeeze(' ')
80
+ end
81
+ end
82
+
83
+ describe '#remove_before_insert_trigger_sql' do
84
+ it 'raise error if no function' do
85
+ -> { @polymorphic.remove_before_insert_trigger_sql }
86
+ .should raise_error PG::Error
87
+ end
88
+
89
+ it 'returns proper sql for single child table' do
90
+ @polymorphic.stub(:get_function).with('foos_baz_fun').and_return('')
91
+
92
+ @polymorphic.remove_before_insert_trigger_sql.squeeze(' ').should == %Q{
93
+ DROP TRIGGER foos_baz_insert_trigger ON foos;
94
+ DROP FUNCTION foos_baz_fun();
95
+ }.squeeze(' ')
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,16 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+ require File.expand_path("../dummy/config/environment", __FILE__)
3
+ require 'rspec/rails'
4
+ require 'rspec/autorun'
5
+
6
+ Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
7
+
8
+ RSpec.configure do |config|
9
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
10
+
11
+ config.use_transactional_fixtures = true
12
+
13
+ config.infer_base_class_for_anonymous_controllers = false
14
+
15
+ config.order = "random"
16
+ end