fx 0.1.0

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 (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +27 -0
  6. data/.yardopts +4 -0
  7. data/Appraisals +21 -0
  8. data/CONTRIBUTING.md +15 -0
  9. data/Gemfile +4 -0
  10. data/README.md +81 -0
  11. data/Rakefile +23 -0
  12. data/bin/appraisal +17 -0
  13. data/bin/console +14 -0
  14. data/bin/rake +17 -0
  15. data/bin/rspec +17 -0
  16. data/bin/setup +12 -0
  17. data/bin/yard +17 -0
  18. data/fx.gemspec +38 -0
  19. data/gemfiles/rails40.gemfile +8 -0
  20. data/gemfiles/rails40.gemfile.lock +111 -0
  21. data/gemfiles/rails41.gemfile +8 -0
  22. data/gemfiles/rails41.gemfile.lock +113 -0
  23. data/gemfiles/rails42.gemfile +8 -0
  24. data/gemfiles/rails42.gemfile.lock +130 -0
  25. data/gemfiles/rails50.gemfile +8 -0
  26. data/gemfiles/rails50.gemfile.lock +126 -0
  27. data/lib/fx.rb +21 -0
  28. data/lib/fx/adapters/postgres.rb +142 -0
  29. data/lib/fx/adapters/postgres/connection.rb +16 -0
  30. data/lib/fx/adapters/postgres/functions.rb +55 -0
  31. data/lib/fx/adapters/postgres/triggers.rb +56 -0
  32. data/lib/fx/command_recorder.rb +29 -0
  33. data/lib/fx/command_recorder/arguments.rb +43 -0
  34. data/lib/fx/command_recorder/function.rb +30 -0
  35. data/lib/fx/command_recorder/trigger.rb +30 -0
  36. data/lib/fx/configuration.rb +38 -0
  37. data/lib/fx/definition.rb +36 -0
  38. data/lib/fx/function.rb +24 -0
  39. data/lib/fx/schema_dumper.rb +15 -0
  40. data/lib/fx/schema_dumper/function.rb +29 -0
  41. data/lib/fx/schema_dumper/trigger.rb +29 -0
  42. data/lib/fx/statements.rb +16 -0
  43. data/lib/fx/statements/function.rb +105 -0
  44. data/lib/fx/statements/trigger.rb +133 -0
  45. data/lib/fx/trigger.rb +24 -0
  46. data/lib/fx/version.rb +4 -0
  47. data/lib/generators.rb +11 -0
  48. data/lib/generators/fx/function/USAGE +9 -0
  49. data/lib/generators/fx/function/function_generator.rb +98 -0
  50. data/lib/generators/fx/function/templates/db/migrate/create_function.erb +5 -0
  51. data/lib/generators/fx/function/templates/db/migrate/update_function.erb +5 -0
  52. data/lib/generators/fx/trigger/USAGE +18 -0
  53. data/lib/generators/fx/trigger/templates/db/migrate/create_trigger.erb +5 -0
  54. data/lib/generators/fx/trigger/templates/db/migrate/update_trigger.erb +5 -0
  55. data/lib/generators/fx/trigger/trigger_generator.rb +108 -0
  56. data/spec/acceptance/user_manages_functions_spec.rb +37 -0
  57. data/spec/acceptance/user_manages_triggers_spec.rb +51 -0
  58. data/spec/acceptance_helper.rb +61 -0
  59. data/spec/dummy/.gitignore +16 -0
  60. data/spec/dummy/Rakefile +6 -0
  61. data/spec/dummy/bin/bundle +3 -0
  62. data/spec/dummy/bin/rails +4 -0
  63. data/spec/dummy/bin/rake +4 -0
  64. data/spec/dummy/config.ru +4 -0
  65. data/spec/dummy/config/application.rb +15 -0
  66. data/spec/dummy/config/boot.rb +5 -0
  67. data/spec/dummy/config/database.yml +9 -0
  68. data/spec/dummy/config/environment.rb +5 -0
  69. data/spec/dummy/db/migrate/.keep +0 -0
  70. data/spec/features/functions/migrations_spec.rb +65 -0
  71. data/spec/features/functions/revert_spec.rb +75 -0
  72. data/spec/features/triggers/migrations_spec.rb +56 -0
  73. data/spec/features/triggers/revert_spec.rb +95 -0
  74. data/spec/fx/adapters/postgres_spec.rb +149 -0
  75. data/spec/fx/command_recorder/arguments_spec.rb +41 -0
  76. data/spec/fx/command_recorder_spec.rb +171 -0
  77. data/spec/fx/configuration_spec.rb +21 -0
  78. data/spec/fx/definition_spec.rb +111 -0
  79. data/spec/fx/schema_dumper/function_spec.rb +22 -0
  80. data/spec/fx/schema_dumper/trigger_spec.rb +40 -0
  81. data/spec/fx/statements/function_spec.rb +103 -0
  82. data/spec/fx/statements/trigger_spec.rb +132 -0
  83. data/spec/generators/fx/function/function_generator_spec.rb +34 -0
  84. data/spec/generators/fx/trigger/trigger_generator_spec.rb +47 -0
  85. data/spec/spec_helper.rb +21 -0
  86. data/spec/support/definition_helpers.rb +37 -0
  87. data/spec/support/generator_setup.rb +11 -0
  88. data/spec/support/migration_helpers.rb +17 -0
  89. metadata +334 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 07cc76f1310a1982698708c2022bbfae7853263a
4
+ data.tar.gz: a598bd9efd102a6d8b2789379c46f865a4319f86
5
+ SHA512:
6
+ metadata.gz: b9b0b8012f86bb96300811e6e7f3eaf0ae03f437da774bb8751759cd7c3546556d5bd3ed195410e97db0a808f55e118c88deca1887d570bd6752308aabd254b0
7
+ data.tar.gz: 022f693c2da994f7204e6320b4bf73b606df63d8d2c5a9f28bce6cb596d035ce949f2c39a3b6111aa6f926079a5b1b67ed73cd989b7ec1567aa5b3d2113a0e74
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1 @@
1
+ 2.3
@@ -0,0 +1,27 @@
1
+ addons:
2
+ postgresql: "9.4"
3
+ before_install:
4
+ - "echo '--colour' > ~/.rspec"
5
+ - "echo 'gem: --no-document' > ~/.gemrc"
6
+ - git config --global user.name "Travis CI"
7
+ - git config --global user.email "travis-ci@example.com"
8
+ branches:
9
+ only:
10
+ - master
11
+ install:
12
+ - travis_retry bin/setup
13
+ language:
14
+ - ruby
15
+ notifications:
16
+ email: false
17
+ rvm:
18
+ - 2.3.1
19
+ gemfile:
20
+ - gemfiles/rails40.gemfile
21
+ - gemfiles/rails41.gemfile
22
+ - gemfiles/rails42.gemfile
23
+ - gemfiles/rails50.gemfile
24
+ matrix:
25
+ exclude:
26
+ - rvm: 2.1.8
27
+ gemfile: gemfiles/rails50.gemfile
@@ -0,0 +1,4 @@
1
+ --hide-api private
2
+ --exclude templates
3
+ --markup markdown
4
+ --markup-provider redcarpet
@@ -0,0 +1,21 @@
1
+ appraise "rails40" do
2
+ gem "activerecord", "~> 4.0.0"
3
+ gem "railties", "~> 4.0.0"
4
+ end
5
+
6
+ appraise "rails41" do
7
+ gem "activerecord", "~> 4.1.0"
8
+ gem "railties", "~> 4.1.0"
9
+ end
10
+
11
+ appraise "rails42" do
12
+ gem "activerecord", "~> 4.2.0"
13
+ gem "railties", "~> 4.2.0"
14
+ end
15
+
16
+ if RUBY_VERSION > "2.2.0"
17
+ appraise "rails50" do
18
+ gem "activerecord", "~> 5.0"
19
+ gem "railties", "~> 5.0"
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # Contributing
2
+
3
+ 1. Fork the repository.
4
+ 2. Run `bin/setup`, which will install dependencies and create the dummy
5
+ application database.
6
+ 3. Run `bin/appraisal rake` to verify that the tests pass against all
7
+ supported versions of Rails.
8
+ 4. Make your change with new passing tests, following the existing style.
9
+ 5. Write a [good commit message], push your fork, and submit a pull request.
10
+
11
+ [good commit message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
12
+
13
+ Others will give constructive feedback. This is a time for discussion and
14
+ improvements, and making the necessary changes will be required before we can
15
+ merge the contribution.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fx.gemspec
4
+ gemspec
@@ -0,0 +1,81 @@
1
+ # F(x)
2
+
3
+ F(x) adds methods to `ActiveRecord::Migration` to create and manage database
4
+ functions and triggers in Rails.
5
+
6
+ Using F(x), you can bring the power of SQL functions and triggers to your Rails
7
+ application without having to switch your schema format to SQL. F(x) provides
8
+ a convention for versioning functions and triggers that keeps your migration
9
+ history consistent and reversible and avoids having to duplicate SQL strings
10
+ across migrations. As an added bonus, you define the structure of your function
11
+ in a SQL file, meaning you get full SQL syntax highlighting in the editor of
12
+ your choice and can easily test your SQL in the database console during
13
+ development.
14
+
15
+ F(x) ships with support for PostgreSQL. The adapter is configurable (see
16
+ `Fx::Configuration`) and has a minimal interface (see
17
+ `Fx::Adapters::Postgres`) that other gems can provide.
18
+
19
+ ## Great, how do I create a trigger and a function?
20
+
21
+ You've got this great idea for a trigger you'd like to call
22
+ `uppercase_users_name`. You can create the migration and the corresponding
23
+ definition file with the following command:
24
+
25
+ ```sh
26
+ % rails generate fx:trigger uppercase_users_name
27
+ create db/triggers/uppercase_users_name_v01.sql
28
+ create db/migrate/[TIMESTAMP]_create_trigger_uppercase_users_name.rb
29
+ ```
30
+
31
+ Edit the `db/triggers/uppercase_users_name_v01.sql` file with the SQL statement
32
+ that defines your trigger. In our example, this might look something like this:
33
+
34
+ ```sql
35
+ CREATE TRIGGER uppercase_users_name
36
+ BEFORE INSERT ON users
37
+ FOR EACH ROW
38
+ EXECUTE PROCEDURE uppercase_users_name();
39
+ ```
40
+
41
+ As you see, we execute a function called `uppercase_users_name` before each
42
+ `INSERT` on the `users` table, which is a function we don't have yet.
43
+
44
+ ```sh
45
+ % rails generate fx:function uppercase_users_name
46
+ create db/functions/uppercase_users_name_v01.sql
47
+ create db/migrate/[TIMESTAMP]_create_function_uppercase_users_name.rb
48
+ ```
49
+
50
+ The generated migrations contains `create_function` and `create_trigger`
51
+ statements. The migration is reversible and the schema will be dumped into your
52
+ `schema.rb` file.
53
+
54
+ ```sh
55
+ % rake db:migrate
56
+ ```
57
+
58
+ ## Cool, but what if I need to change a trigger or function?
59
+
60
+ Here's where F(x) really shines. Run that same function generator once more:
61
+
62
+ ```sh
63
+ % rails generate fx:function uppercase_users_name
64
+ create db/functions/uppercase_users_name_v02.sql
65
+ create db/migrate/[TIMESTAMP]_update_function_uppercase_users_name_to_version_2.rb
66
+ ```
67
+
68
+ F(x) detected that we already had an existing `uppercase_users_name` function at
69
+ version 1, created a copy of that definition as version 2, and created a
70
+ migration to update to the version 2 schema. All that's left for you to do is
71
+ tweak the schema in the new definition and run the `update_function` migration.
72
+
73
+ ## I don't need this trigger or function anymore. Make it go away.
74
+
75
+ F(x) gives you `drop_trigger` and `drop_function` too:
76
+
77
+ ```ruby
78
+ def change
79
+ drop_function :uppercase_users_name, revert_to_version: 2
80
+ end
81
+ ```
@@ -0,0 +1,23 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ namespace :dummy do
5
+ require_relative "spec/dummy/config/application"
6
+ Dummy::Application.load_tasks
7
+ end
8
+
9
+ task(:spec).clear
10
+ desc "Run specs other than spec/acceptance"
11
+ RSpec::Core::RakeTask.new("spec") do |task|
12
+ task.exclude_pattern = "spec/acceptance/**/*_spec.rb"
13
+ task.verbose = false
14
+ end
15
+
16
+ desc "Run acceptance specs in spec/acceptance"
17
+ RSpec::Core::RakeTask.new("spec:acceptance") do |task|
18
+ task.pattern = "spec/acceptance/**/*_spec.rb"
19
+ task.verbose = false
20
+ end
21
+
22
+ desc "Run the specs and acceptance tests"
23
+ task default: %w(spec spec:acceptance)
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'appraisal' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("appraisal", "appraisal")
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "fx"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rake' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rake", "rake")
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
@@ -0,0 +1,12 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ gem install bundler --conservative
6
+ bundle check || bundle install
7
+
8
+ if [ -z "$CI" ]; then
9
+ bundle exec appraisal install
10
+ fi
11
+
12
+ bundle exec rake dummy:db:create
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'yard' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("yard", "yard")
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "fx/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fx"
8
+ spec.version = Fx::VERSION
9
+ spec.authors = ["Teo Ljungberg"]
10
+ spec.email = ["teo@teoljungberg.com"]
11
+ spec.summary = %q{Support for database functions and triggers in Rails migrations}
12
+ spec.description = <<-DESCRIPTION
13
+ Adds methods to ActiveRecord::Migration to create and manage database functions
14
+ and triggers in Rails
15
+ DESCRIPTION
16
+ spec.homepage = "https://github.com/teoljungberg/fx"
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.test_files = spec.files.grep(%r{^spec/})
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency "appraisal"
24
+ spec.add_development_dependency "bundler", '>= 1.5'
25
+ spec.add_development_dependency "database_cleaner"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec", '>= 3.3'
28
+ spec.add_development_dependency "pg"
29
+ spec.add_development_dependency "pry"
30
+ spec.add_development_dependency "ammeter", '>= 1.1.3'
31
+ spec.add_development_dependency "yard"
32
+ spec.add_development_dependency "redcarpet"
33
+
34
+ spec.add_dependency "activerecord", '>= 4.0.0'
35
+ spec.add_dependency "railties", '>= 4.0.0'
36
+
37
+ spec.required_ruby_version = "~> 2.1"
38
+ end
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 4.0.0"
6
+ gem "railties", "~> 4.0.0"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,111 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ fx (0.1.0)
5
+ activerecord (>= 4.0.0)
6
+ railties (>= 4.0.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionpack (4.0.13)
12
+ activesupport (= 4.0.13)
13
+ builder (~> 3.1.0)
14
+ erubis (~> 2.7.0)
15
+ rack (~> 1.5.2)
16
+ rack-test (~> 0.6.2)
17
+ activemodel (4.0.13)
18
+ activesupport (= 4.0.13)
19
+ builder (~> 3.1.0)
20
+ activerecord (4.0.13)
21
+ activemodel (= 4.0.13)
22
+ activerecord-deprecated_finders (~> 1.0.2)
23
+ activesupport (= 4.0.13)
24
+ arel (~> 4.0.0)
25
+ activerecord-deprecated_finders (1.0.4)
26
+ activesupport (4.0.13)
27
+ i18n (~> 0.6, >= 0.6.9)
28
+ minitest (~> 4.2)
29
+ multi_json (~> 1.3)
30
+ thread_safe (~> 0.1)
31
+ tzinfo (~> 0.3.37)
32
+ ammeter (1.1.3)
33
+ activesupport (>= 3.0)
34
+ railties (>= 3.0)
35
+ rspec-rails (>= 2.2)
36
+ appraisal (2.1.0)
37
+ bundler
38
+ rake
39
+ thor (>= 0.14.0)
40
+ arel (4.0.2)
41
+ builder (3.1.4)
42
+ coderay (1.1.1)
43
+ database_cleaner (1.5.3)
44
+ diff-lcs (1.2.5)
45
+ erubis (2.7.0)
46
+ i18n (0.7.0)
47
+ method_source (0.8.2)
48
+ minitest (4.7.5)
49
+ multi_json (1.12.1)
50
+ pg (0.18.4)
51
+ pry (0.10.3)
52
+ coderay (~> 1.1.0)
53
+ method_source (~> 0.8.1)
54
+ slop (~> 3.4)
55
+ rack (1.5.5)
56
+ rack-test (0.6.3)
57
+ rack (>= 1.0)
58
+ railties (4.0.13)
59
+ actionpack (= 4.0.13)
60
+ activesupport (= 4.0.13)
61
+ rake (>= 0.8.7)
62
+ thor (>= 0.18.1, < 2.0)
63
+ rake (11.1.2)
64
+ redcarpet (3.3.4)
65
+ rspec (3.4.0)
66
+ rspec-core (~> 3.4.0)
67
+ rspec-expectations (~> 3.4.0)
68
+ rspec-mocks (~> 3.4.0)
69
+ rspec-core (3.4.4)
70
+ rspec-support (~> 3.4.0)
71
+ rspec-expectations (3.4.0)
72
+ diff-lcs (>= 1.2.0, < 2.0)
73
+ rspec-support (~> 3.4.0)
74
+ rspec-mocks (3.4.1)
75
+ diff-lcs (>= 1.2.0, < 2.0)
76
+ rspec-support (~> 3.4.0)
77
+ rspec-rails (3.4.2)
78
+ actionpack (>= 3.0, < 4.3)
79
+ activesupport (>= 3.0, < 4.3)
80
+ railties (>= 3.0, < 4.3)
81
+ rspec-core (~> 3.4.0)
82
+ rspec-expectations (~> 3.4.0)
83
+ rspec-mocks (~> 3.4.0)
84
+ rspec-support (~> 3.4.0)
85
+ rspec-support (3.4.1)
86
+ slop (3.6.0)
87
+ thor (0.19.1)
88
+ thread_safe (0.3.5)
89
+ tzinfo (0.3.49)
90
+ yard (0.8.7.6)
91
+
92
+ PLATFORMS
93
+ ruby
94
+
95
+ DEPENDENCIES
96
+ activerecord (~> 4.0.0)
97
+ ammeter (>= 1.1.3)
98
+ appraisal
99
+ bundler (>= 1.5)
100
+ database_cleaner
101
+ fx!
102
+ pg
103
+ pry
104
+ railties (~> 4.0.0)
105
+ rake
106
+ redcarpet
107
+ rspec (>= 3.3)
108
+ yard
109
+
110
+ BUNDLED WITH
111
+ 1.12.4