tphases 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ Gemfile.lock
21
+ .idea
22
+
23
+ spec/fixtures/database.sqlite3
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tphases.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Charles Finkel
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # TPhases
2
+
3
+ TPhases (Transactional Phases) is a support framework that helps you build your Rails request life cycles into read-only, write-only, and no-transaction-allowed phases.
4
+
5
+ The way it accomplishes this is with the methods `TPhases.read_phase`, `TPhases.write_phase` and `TPhases.no_transactions_phase` which take blocks. Here is a simple example inside of a controller action:
6
+
7
+ ```ruby
8
+ class BarsController < ApplicationController
9
+
10
+ def update
11
+ TPhases.read_phase do
12
+ @bar = Bar.find(params[:id])
13
+ end
14
+
15
+ TPhases.write_phase do
16
+ @bar.update_attributes(params[:bar])
17
+ end
18
+
19
+ TPhases.no_transactions_phase do
20
+ process(@bar)
21
+ redirect_to @bar
22
+ end
23
+ end
24
+ end
25
+ ```
26
+
27
+ ** Currently supports ActiveRecord only. Planned support includes Memcached, Redis, MongoDB, and more.
28
+
29
+ ## Installation
30
+
31
+ Add this line to your application's Gemfile:
32
+
33
+ gem 'tphases'
34
+
35
+ And then execute:
36
+
37
+ $ bundle
38
+
39
+ Or install it yourself as:
40
+
41
+ $ gem install tphases
42
+
43
+ Somewhere in the initialization process of your app, call
44
+
45
+ TPhases.initiate!
46
+
47
+ ## Usage
48
+
49
+ ### In production:
50
+ The `read_phase`, `write_phase`, and `no_transaction_phase` methods simply yield to the block given.
51
+
52
+ ### In development:
53
+
54
+ #### `read_phase`
55
+ throws an exception if a database transaction is attempted within its block which is a write. This is known as a "read transactional violation".
56
+
57
+ #### `write_phase`
58
+ throws an exception if a database transaction is attempted within its block which is a read. This is a write transactional violation.
59
+
60
+ #### `no_transactions_phase`
61
+ throws an exception if any database transaction is attempted within its block.
62
+
63
+ ### In test:
64
+ If a transactional violation occurs in a TPhase, the code will continue to run, but the test will fail at the end citing the list of transactional violations that occurred.
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,41 @@
1
+ module TPhases
2
+ module Config
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ # allow for configuration of TPhases
7
+ def configure(&block)
8
+ yield config
9
+ end
10
+
11
+ private
12
+ # the config
13
+ # sets default value `mode` value based on presence of Rails and environment type
14
+ # the default setting is the safest, :pass_through, which means TPhases does nothing.
15
+ def config
16
+ @config ||= begin
17
+
18
+ default_mode = begin
19
+ if defined? Rails
20
+ case Rails.env
21
+ when 'production', 'staging', 'demo'
22
+ :pass_through
23
+ when 'development'
24
+ :exceptions
25
+ when 'test'
26
+ :collect
27
+ else
28
+ :pass_through
29
+ end
30
+ else
31
+ :pass_through
32
+ end
33
+ end
34
+
35
+ Struct.new(:mode).new(default_mode)
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ module TPhases
2
+ module Initialization
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ # initiates TPhases. Any overrides to config mode need to be made prior to running this.
7
+ def initiate!
8
+ case config.mode
9
+ when :pass_through
10
+ require 'tphases/modes/pass_through_mode'
11
+ include TPhases::Modes::PassThroughMode
12
+ when :exceptions
13
+ require 'tphases/modes/exceptions_mode'
14
+ include TPhases::Modes::ExceptionsMode
15
+ when :collect
16
+ require 'tphases/modes/collect_mode'
17
+ include TPhases::Modes::CollectMode
18
+ else
19
+ raise "TPhases mode must be one of :pass_through, :exceptions, or :collect, but instead is #{config.mode}"
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,60 @@
1
+ require 'tphases/transactional_violation'
2
+ require 'tphases/modes/helpers/transactional_violations_helper'
3
+
4
+ # the default 'test' mode, Collect Mode collects incidents of
5
+ # immediately inside of a TPhase block if a transactional violation occurs
6
+ module TPhases
7
+ module Modes
8
+ module CollectMode
9
+ extend ActiveSupport::Concern
10
+ include Helpers::TransactionalViolationsHelper
11
+
12
+ included do
13
+ add_rspec_after! if defined?(RSpec)
14
+ @violations = []
15
+ end
16
+
17
+
18
+ module ClassMethods
19
+ attr_accessor :violations
20
+
21
+ private
22
+ def write_violation_action(sql, call_stack)
23
+ violations << { :type => :write, :call_stack => call_stack, :sql => sql }
24
+ end
25
+
26
+ def read_violation_action(sql, call_stack)
27
+ violations << { :type => :read, :call_stack => call_stack, :sql => sql }
28
+ end
29
+
30
+ def no_transactions_violation_action(sql, call_stack)
31
+ violations << { :type => :no_transactions, :call_stack => call_stack, :sql => sql }
32
+ end
33
+
34
+ # adds an after block for all rspec tests that cause them to fail if any transactional violations are present
35
+ def add_rspec_after!
36
+ RSpec.configure do |config|
37
+ config.after(:each) do
38
+ begin
39
+ unless TPhases.violations.empty?
40
+ #fail "This spec had #{TPhases.violations.count} transactional violations: \n\t#{TPhases.violations.map(&:inspect).join("\n\t")}"
41
+ fail <<-FAILURE_MESSAGE
42
+ This spec had #{TPhases.violations.count} transactional violations:
43
+ #{TPhases.violations.each_with_index.map do |violation,index|
44
+ "#{index}: Violation Type: #{violation[:type]},\nSQL: #{violation[:sql]}\nCall Stack:\n\t#{violation[:call_stack].join("\n\t")}"
45
+ end.join("\n*********************************************************\n")}
46
+ end
47
+ FAILURE_MESSAGE
48
+ end
49
+ ensure
50
+ # reset violations list:
51
+ TPhases.violations = []
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,30 @@
1
+ require 'tphases/transactional_violation'
2
+ require 'tphases/modes/helpers/transactional_violations_helper'
3
+
4
+ # the default 'development' mode, Exceptions Mode means that an exception will be raised
5
+ # immediately inside of a TPhase block if a transactional violation occurs
6
+ module TPhases
7
+ module Modes
8
+ module ExceptionsMode
9
+ extend ActiveSupport::Concern
10
+ include Helpers::TransactionalViolationsHelper
11
+
12
+ module ClassMethods
13
+ private
14
+
15
+ def write_violation_action(sql, caller)
16
+ raise TransactionalViolation.new "#{sql} ran inside of a 'write_phase' block."
17
+ end
18
+
19
+ def read_violation_action(sql, caller)
20
+ raise TransactionalViolation.new "#{sql} ran inside of a 'read_phase' block."
21
+ end
22
+
23
+ def no_transactions_violation_action(sql, caller)
24
+ raise TransactionalViolation.new "#{sql} ran inside of a 'no_transactions_phase' block."
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,133 @@
1
+ require 'active_support/notifications'
2
+ require 'active_support/version'
3
+
4
+ module TPhases
5
+ module Modes
6
+ module Helpers
7
+
8
+ # this helper is included by the CollectMode and the ExceptionsMode modules.
9
+ # methods expected to be implemented by those modes are #write_violation_action, #read_violation_action, and
10
+ # #no_transactions_violation_action
11
+ module TransactionalViolationsHelper
12
+ extend ActiveSupport::Concern
13
+
14
+ included do
15
+ define_phase_methods!
16
+ end
17
+
18
+ private
19
+ module ClassMethods
20
+
21
+ # if version of activesupport is 3.2.1, it has the subscribed method. else, it doesn't
22
+ def define_phase_methods!
23
+ if ActiveSupport::VERSION::MAJOR > 3
24
+ define_phase_methods_with_subscribed_method!
25
+ elsif ActiveSupport::VERSION::MAJOR == 3
26
+ if ActiveSupport::VERSION::MINOR > 2
27
+ define_phase_methods_with_subscribed_method!
28
+ elsif ActiveSupport::VERSION::MINOR == 2
29
+ if ActiveSupport::VERSION::TINY >= 1
30
+ define_phase_methods_with_subscribed_method!
31
+ else
32
+ define_phase_methods_without_subscribed_method!
33
+ end
34
+ else
35
+ define_phase_methods_without_subscribed_method!
36
+ end
37
+ else
38
+ define_phase_methods_without_subscribed_method!
39
+ end
40
+ end
41
+
42
+ # adds methods using the subscribed method
43
+ def define_phase_methods_with_subscribed_method!
44
+ define_singleton_method(:read_phase) do |&block|
45
+ ActiveSupport::Notifications.subscribed(read_phase_subscription_callback, "sql.active_record", &block)
46
+ end
47
+
48
+ define_singleton_method(:write_phase) do |&block|
49
+ ActiveSupport::Notifications.subscribed(write_phase_subscription_callback, "sql.active_record", &block)
50
+ end
51
+
52
+ define_singleton_method(:no_transactions_phase) do |&block|
53
+ ActiveSupport::Notifications.subscribed(no_transactions_phase_subscription_callback, "sql.active_record", &block)
54
+ end
55
+ end
56
+
57
+ def define_phase_methods_without_subscribed_method!
58
+ define_singleton_method(:read_phase) do |&block|
59
+ begin
60
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record", &read_phase_subscription_callback)
61
+ block.call
62
+ ensure
63
+ ActiveSupport::Notifications.unsubscribe(subscriber)
64
+ end
65
+ end
66
+
67
+ define_singleton_method(:write_phase) do |&block|
68
+ begin
69
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record", &write_phase_subscription_callback)
70
+ block.call
71
+ ensure
72
+ ActiveSupport::Notifications.unsubscribe(subscriber)
73
+ end
74
+ end
75
+
76
+ define_singleton_method(:no_transactions_phase) do |&block|
77
+ begin
78
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record", &no_transactions_phase_subscription_callback)
79
+ block.call
80
+ ensure
81
+ ActiveSupport::Notifications.unsubscribe(subscriber)
82
+ end
83
+ end
84
+ end
85
+
86
+ # the set of blocks that run when an ActiveSupport notification is fired on sql.active_record
87
+ # each call *_violation_action methods which are defined in the implementing module
88
+
89
+ def write_phase_subscription_callback
90
+ Proc.new do |name, date, date2, sha, args|
91
+ if write_transactional_violation?(args[:sql])
92
+ write_violation_action(args[:sql], caller)
93
+ end
94
+ end
95
+ end
96
+
97
+ def read_phase_subscription_callback
98
+ Proc.new do |name, date, date2, sha, args|
99
+ if read_transactional_violation?(args[:sql])
100
+ read_violation_action(args[:sql], caller)
101
+ end
102
+ end
103
+ end
104
+
105
+ def no_transactions_phase_subscription_callback
106
+ Proc.new do |name, date, date2, sha, args|
107
+ no_transactions_violation_action(args[:sql], caller)
108
+ end
109
+ end
110
+
111
+ READ_QUERIES = %w{update commit insert delete}
112
+ WRITE_QUERIES = %w{show select}
113
+
114
+ # determines if this query is a read transactional violation (if it is anything besides a read)
115
+ def read_transactional_violation?(sql)
116
+ READ_QUERIES.include?(first_word(sql))
117
+ end
118
+
119
+ # determines if this query is a write transactional violation (if it is anything besides a write)
120
+ def write_transactional_violation?(sql)
121
+ WRITE_QUERIES.include?(first_word(sql))
122
+ end
123
+
124
+ def first_word(str)
125
+ str.split(' ').first.downcase
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,22 @@
1
+ # the default 'production' mode, PassThrough mode does nothing but called the yielded block
2
+ module TPhases
3
+ module Modes
4
+ module PassThroughMode
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def read_phase
9
+ yield
10
+ end
11
+
12
+ def write_phase
13
+ yield
14
+ end
15
+
16
+ def no_transactions_phase
17
+ yield
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ class TransactionalViolation < StandardError
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ module Tphases
2
+ VERSION = "0.1.2"
3
+ end
data/lib/tphases.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'active_support/concern'
2
+ require "tphases/version"
3
+ require "tphases/config"
4
+ require "tphases/initialization"
5
+
6
+ module TPhases
7
+ include TPhases::Config
8
+ include TPhases::Initialization
9
+ end
Binary file
@@ -0,0 +1,4 @@
1
+ adapter: sqlite3
2
+ database: spec/fixtures/database.sqlite3
3
+ pool: 5
4
+ timeout: 5000
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+ require 'tphases/modes/collect_mode'
4
+
5
+ describe TPhases::Modes::CollectMode do
6
+ subject { Module.new { include TPhases::Modes::CollectMode } }
7
+
8
+ include_context "setup mode specs"
9
+
10
+ describe '.no_transactions_phase' do
11
+ it "should add to the violations list for all violations" do
12
+ expect {
13
+ subject.no_transactions_phase do
14
+ ActiveRecord::Base.connection.select_all(read_sql)
15
+ end
16
+ }.to change { subject.send(:violations).size }.from(0).to(1)
17
+ end
18
+
19
+ it "should add multiple violations if there are multiple" do
20
+ expect {
21
+ subject.no_transactions_phase do
22
+ ActiveRecord::Base.connection.select_all(read_sql)
23
+ ActiveRecord::Base.connection.select_all(write_sql)
24
+ end
25
+ }.to change { subject.send(:violations).size }.from(0).to(2)
26
+ end
27
+ end
28
+
29
+ describe '.read_phase' do
30
+ it "should not add a violation for read transactions" do
31
+ expect {
32
+ subject.read_phase do
33
+ ActiveRecord::Base.connection.select_all(read_sql)
34
+ end
35
+ }.to_not change { subject.send(:violations).size }
36
+ end
37
+ it "should add a violation for write transactions" do
38
+ expect {
39
+ subject.read_phase do
40
+ ActiveRecord::Base.connection.select_all(write_sql)
41
+ end
42
+ }.to change { subject.send(:violations).size }.from(0).to(1)
43
+
44
+ end
45
+ end
46
+
47
+ describe '.write_phase' do
48
+ it "should not add a violation for write transactions" do
49
+ expect {
50
+ subject.write_phase do
51
+ ActiveRecord::Base.connection.select_all(write_sql)
52
+ end
53
+ }.to_not change { subject.send(:violations).size }
54
+ end
55
+ it "should add a violation for read transactions" do
56
+ expect {
57
+ subject.write_phase do
58
+ ActiveRecord::Base.connection.select_all(read_sql)
59
+ end
60
+ }.to change { subject.send(:violations).size }.from(0).to(1)
61
+
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+ require 'tphases/modes/exceptions_mode'
4
+
5
+ describe TPhases::Modes::ExceptionsMode do
6
+ subject { Module.new { include TPhases::Modes::ExceptionsMode } }
7
+
8
+ include_context "setup mode specs"
9
+
10
+ describe '.no_transactions_phase' do
11
+ it "should throw an exception disallow read and write transactions from running in this phase" do
12
+ expect {
13
+ subject.no_transactions_phase do
14
+ ActiveRecord::Base.connection.select_all(read_sql)
15
+ end
16
+ }.to raise_error(ActiveRecord::StatementInvalid, "TransactionalViolation: #{read_sql} ran inside of a 'no_transactions_phase' block.: #{read_sql}")
17
+
18
+ expect {
19
+ subject.no_transactions_phase do
20
+ ActiveRecord::Base.connection.select_all(write_sql)
21
+ end
22
+ }.to raise_error(ActiveRecord::StatementInvalid, "TransactionalViolation: #{write_sql} ran inside of a 'no_transactions_phase' block.: #{write_sql}")
23
+ end
24
+ end
25
+
26
+ describe '.read_phase' do
27
+ it "should allow read transactions" do
28
+ expect {
29
+ subject.read_phase do
30
+ ActiveRecord::Base.connection.select_all(read_sql)
31
+ end
32
+ }.to_not raise_error
33
+ end
34
+ it "should disallow write transactions" do
35
+ expect {
36
+ subject.read_phase do
37
+ ActiveRecord::Base.connection.select_all(write_sql)
38
+ end
39
+ }.to raise_error(ActiveRecord::StatementInvalid, "TransactionalViolation: #{write_sql} ran inside of a 'read_phase' block.: #{write_sql}")
40
+
41
+ end
42
+ end
43
+
44
+ describe '.write_phase' do
45
+ it "should allow write transactions" do
46
+ expect {
47
+ subject.write_phase do
48
+ ActiveRecord::Base.connection.select_all(write_sql)
49
+ end
50
+ }.to_not raise_error
51
+ end
52
+ it "should disallow read transactions" do
53
+ expect {
54
+ subject.write_phase do
55
+ ActiveRecord::Base.connection.select_all(read_sql)
56
+ end
57
+ }.to raise_error(ActiveRecord::StatementInvalid, "TransactionalViolation: #{read_sql} ran inside of a 'write_phase' block.: #{read_sql}")
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'tphases/modes/helpers/transactional_violations_helper'
3
+
4
+ describe TPhases::Modes::Helpers::TransactionalViolationsHelper do
5
+ describe TPhases::Modes::Helpers::TransactionalViolationsHelper do
6
+ subject { Module.new { include TPhases::Modes::Helpers::TransactionalViolationsHelper } }
7
+
8
+ let(:write_queries) {
9
+ [
10
+ "UPDATE `users` SET `email` = 'woifjwe@owiejf.com' WHERE `users`.`id` = 1",
11
+ "INSERT INTO tablename (col1, col2) VALUES('data1', 'data2' )",
12
+ "COMMIT",
13
+ "DELETE FROM example WHERE age='15'"
14
+ ]
15
+ }
16
+ let(:read_queries) {
17
+ [
18
+ "select * from foobar",
19
+ "show variables like 'version'"
20
+ ]
21
+ }
22
+
23
+ describe "#read_transactional_violation?" do
24
+ it "should detect correctly" do
25
+ read_queries.each { |read_query| expect(subject.send(:read_transactional_violation?, read_query)).to eq(false) }
26
+ write_queries.each { |write_query| expect(subject.send(:read_transactional_violation?, write_query)).to eq(true) }
27
+ end
28
+ end
29
+
30
+ describe " #write_transactional_violation?" do
31
+ it "should detect correctly" do
32
+ read_queries.each { |read_query| expect(subject.send(:write_transactional_violation?, read_query)).to be_true }
33
+ write_queries.each { |write_query| expect(subject.send(:write_transactional_violation?, write_query)).to be_false }
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+ require 'tphases/modes/pass_through_mode'
4
+
5
+ describe TPhases::Modes::PassThroughMode do
6
+ subject { Module.new { include TPhases::Modes::PassThroughMode } }
7
+
8
+ include_context "setup mode specs"
9
+
10
+ describe '.no_transactions_phase, .read_phase, .write_phase' do
11
+ it "should allow anything" do
12
+ subject.no_transactions_phase do
13
+ ActiveRecord::Base.connection.select_all(read_sql)
14
+ ActiveRecord::Base.connection.select_all(write_sql)
15
+ end
16
+
17
+ subject.write_phase do
18
+ ActiveRecord::Base.connection.select_all(read_sql)
19
+ ActiveRecord::Base.connection.select_all(write_sql)
20
+ end
21
+
22
+ subject.read_phase do
23
+ ActiveRecord::Base.connection.select_all(read_sql)
24
+ ActiveRecord::Base.connection.select_all(write_sql)
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ LIB_ROOT = File.expand_path(File.dirname(__FILE__) + "/..")
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # Require this file using `require "spec_helper"` to ensure that it is only
6
+ # loaded once.
7
+ #
8
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
9
+ RSpec.configure do |config|
10
+ config.treat_symbols_as_metadata_keys_with_true_values = true
11
+ config.run_all_when_everything_filtered = true
12
+ config.filter_run :focus
13
+
14
+ # Run specs in random order to surface order dependencies. If you find an
15
+ # order dependency and want to debug it, you can fix the order by providing
16
+ # the seed, which is printed after each run.
17
+ # --seed 1234
18
+ config.order = 'random'
19
+ end
20
+
21
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
22
+
23
+ require File.join(File.expand_path('../../', __FILE__), 'lib', 'tphases')
@@ -0,0 +1,12 @@
1
+ shared_context "setup mode specs" do
2
+
3
+ before do
4
+ dbconfig = YAML::load(File.open(LIB_ROOT + '/spec/fixtures/database.yml'))
5
+ dbconfig['database'] = LIB_ROOT + '/' + dbconfig['database']
6
+ ActiveRecord::Base.establish_connection(dbconfig)
7
+ end
8
+
9
+ let(:read_sql) { 'select * from posts' }
10
+ let(:write_sql) { "insert into posts values ('foobaz')" }
11
+
12
+ end
data/test_script.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'pry'
2
+ require 'active_record'
3
+ dbconfig = YAML::load(File.open('spec/fixtures/database.yml'))
4
+ ActiveRecord::Base.establish_connection(dbconfig)
5
+ puts ActiveRecord::Base.connection.select_all('select * from posts')
data/tphases.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tphases/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "tphases"
8
+ gem.version = Tphases::VERSION
9
+ gem.authors = ["Charles Finkel"]
10
+ gem.email = ["charles.finkel@gmail.com"]
11
+
12
+ description = %q{TPhases (Transactional Phases) is a support framework that helps you build your Rails request life cycles into read-only and write-only phases.}
13
+ gem.description = description
14
+ gem.summary = description
15
+ gem.homepage = "https://github.com/charleseff/tphases"
16
+
17
+ gem.files = `git ls-files`.split($/)
18
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ["lib"]
21
+
22
+ gem.add_dependency 'activesupport'
23
+
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'debugger'
26
+ gem.add_development_dependency 'sqlite3'
27
+ gem.add_development_dependency 'activerecord'
28
+ gem.add_development_dependency 'pry'
29
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tphases
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Charles Finkel
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: debugger
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: sqlite3
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: activerecord
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: pry
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: TPhases (Transactional Phases) is a support framework that helps you
111
+ build your Rails request life cycles into read-only and write-only phases.
112
+ email:
113
+ - charles.finkel@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .rspec
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - lib/tphases.rb
125
+ - lib/tphases/config.rb
126
+ - lib/tphases/initialization.rb
127
+ - lib/tphases/modes/collect_mode.rb
128
+ - lib/tphases/modes/exceptions_mode.rb
129
+ - lib/tphases/modes/helpers/transactional_violations_helper.rb
130
+ - lib/tphases/modes/pass_through_mode.rb
131
+ - lib/tphases/transactional_violation.rb
132
+ - lib/tphases/version.rb
133
+ - spec/fixtures/database.sqlite3
134
+ - spec/fixtures/database.yml
135
+ - spec/lib/tphases/modes/collect_mode_spec.rb
136
+ - spec/lib/tphases/modes/exceptions_mode_spec.rb
137
+ - spec/lib/tphases/modes/helpers/transactional_violations_helper_spec.rb
138
+ - spec/lib/tphases/modes/pass_through_mode_spec.rb
139
+ - spec/spec_helper.rb
140
+ - spec/support/setup_modes_specs_context.rb
141
+ - test_script.rb
142
+ - tphases.gemspec
143
+ homepage: https://github.com/charleseff/tphases
144
+ licenses: []
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ none: false
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 1.8.24
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: TPhases (Transactional Phases) is a support framework that helps you build
167
+ your Rails request life cycles into read-only and write-only phases.
168
+ test_files:
169
+ - spec/fixtures/database.sqlite3
170
+ - spec/fixtures/database.yml
171
+ - spec/lib/tphases/modes/collect_mode_spec.rb
172
+ - spec/lib/tphases/modes/exceptions_mode_spec.rb
173
+ - spec/lib/tphases/modes/helpers/transactional_violations_helper_spec.rb
174
+ - spec/lib/tphases/modes/pass_through_mode_spec.rb
175
+ - spec/spec_helper.rb
176
+ - spec/support/setup_modes_specs_context.rb