asir_activerecord 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ lor
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ -color -f d
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in asir_activerecord.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Kurt Stephens
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.
@@ -0,0 +1,29 @@
1
+ # AsirActiverecord
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'asir_activerecord'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install asir_activerecord
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,27 @@
1
+
2
+ # YUCK! http://stackoverflow.com/questions/4755900/how-to-make-jruby-1-6-default-to-ruby-1-9
3
+ ENV['JRUBY_OPTS'] ||= '--1.9'
4
+
5
+ require "bundler/gem_tasks"
6
+
7
+ gem 'rspec'
8
+ require 'rspec/core/rake_task'
9
+
10
+ desc "Default => :test"
11
+ task :default => :test
12
+
13
+ desc "Run all tests"
14
+ task :test => [ :spec ]
15
+
16
+ desc "Run specs"
17
+ RSpec::Core::RakeTask.new(:spec) do |t|
18
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
19
+ # Put spec opts in a file named .rspec in root
20
+ end
21
+
22
+ desc "Generate code coverage"
23
+ RSpec::Core::RakeTask.new(:coverage) do |t|
24
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
25
+ t.rcov = true
26
+ t.rcov_opts = ['--exclude', 'spec']
27
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # -*- ruby -*-
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'asir_activerecord/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = "asir_activerecord"
9
+ gem.version = AsirActiverecord::VERSION
10
+ gem.authors = ["Kurt Stephens"]
11
+ gem.email = ["ks.ruby@kurtstephens.com"]
12
+ gem.description = %q{ASIR ActiveRecord Transport}
13
+ gem.summary = %q{Store ASIR Message and Result objects in ActiveRecord.}
14
+ gem.homepage = %q{http://github.com/kstephens/abstracting_services_in_ruby}
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency "asir", '>= 1.0.8'
22
+ gem.add_dependency "activerecord", '>= 3.0.0'
23
+ gem.add_development_dependency "pg", '>= 0.14.0'
24
+
25
+ gem.add_development_dependency 'rake', '>= 0.9.0'
26
+ gem.add_development_dependency 'rspec', '~> 2.12.0'
27
+ gem.add_development_dependency 'simplecov', '>= 0.1'
28
+ end
@@ -0,0 +1,16 @@
1
+ require 'asir'
2
+
3
+ require 'active_record'
4
+
5
+ module ASIR
6
+ class Coder
7
+ module ActiveRecord
8
+ MIGRATIONS = [ ]
9
+ end
10
+ end
11
+ end
12
+
13
+ require 'asir/coder/database'
14
+ require 'asir/coder/active_record/message_model'
15
+ require 'asir/coder/active_record/result_model'
16
+
@@ -0,0 +1,84 @@
1
+ require 'asir/coder/active_record'
2
+
3
+ module ASIR
4
+ class Coder
5
+ module ActiveRecord
6
+ class MessageModel < ::ActiveRecord::Base
7
+ class Migration < ::ActiveRecord::Migration
8
+ def self.table_name
9
+ :asir_messages
10
+ end
11
+ def self.class_table_name
12
+ :asir_classes
13
+ end
14
+ def change
15
+ create_table tn = self.class.class_table_name do | t |
16
+ t.integer :external_id
17
+ t.string :class_name
18
+ end
19
+ add_index tn, :class_name, :unique => true
20
+
21
+ create_table tn = self.class.table_name do | t |
22
+ t.integer :external_id
23
+ t.string :message_identifier, :null => false
24
+ t.string :receiver_class, :null => false # NORMALIZE?
25
+ t.string :message_type, :null => false, :size => 1
26
+ t.string :selector # NORMALIZE?
27
+ t.binary :additional_data
28
+ t.text :description # NORMALIZE?
29
+ t.float :delay
30
+ t.integer :one_way
31
+ t.binary :payload
32
+ t.timestamps
33
+ end
34
+ add_index tn, :external_id
35
+ add_index tn, :message_identifier, :unique => true
36
+ add_index tn, [ :receiver_class, :message_type ]
37
+ add_index tn, :selector
38
+ add_index tn, :description
39
+ add_index tn, :created_at
40
+ end
41
+ end
42
+ ActiveRecord::MIGRATIONS << Migration
43
+
44
+ self.table_name = Migration.table_name.to_s
45
+
46
+ attr_accessor :object, :original_object
47
+
48
+ has_one :result, :class_name => 'ASIR::Coder::ActiveRecord::ResultModel'
49
+
50
+ validates_uniqueness_of :message_identifier
51
+ validates_presence_of :receiver_class
52
+ validates_presence_of :message_type
53
+ validates_presence_of :selector
54
+ validates_presence_of :payload
55
+
56
+ before_save :prepare_for_save!
57
+ def prepare_for_save!
58
+ if message = self.object
59
+ self.external_id ||= original_object[:external_id]
60
+ self.message_identifier ||= message.identifier
61
+ x = original_object.message_kind
62
+ self.receiver_class = x[0].to_s # original_object.receiver_class.name.to_s
63
+ self.message_type = x[1].to_s
64
+ self.selector ||= message.selector.to_s
65
+ self.description ||= (original_object[:description] || original_object.description).to_s
66
+ self.payload ||= object_payload
67
+ end
68
+ if additional_data
69
+ raise TypeError, "additional_data is not a String" \
70
+ unless String === additional_data
71
+ end
72
+ end
73
+
74
+ after_save :update_original_object!
75
+ def update_original_object!
76
+ if original_object
77
+ original_object[:database_id] = self.id
78
+ end
79
+ end
80
+
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,82 @@
1
+ require 'asir'
2
+ require 'active_record/migration'
3
+ require 'active_record/base'
4
+
5
+ module ASIR
6
+ class Coder
7
+ module ActiveRecord
8
+ class ResultModel < ::ActiveRecord::Base
9
+ class Migration < ::ActiveRecord::Migration
10
+ def self.table_name
11
+ :asir_results
12
+ end
13
+ def change
14
+ create_table tn = self.class.table_name do | t |
15
+ t.integer :external_id
16
+ t.string :message_id, :null => false
17
+ t.string :result_class, :null => false # NORMALIZE?
18
+ t.string :exception_class # NORMALIZE?
19
+ t.text :exception_message
20
+ t.text :exception_backtrace
21
+ t.binary :additional_data
22
+ t.binary :payload
23
+ t.timestamps
24
+ end
25
+ add_index tn, :external_id
26
+ add_index tn, :message_id, :unique => true
27
+ add_index tn, :result_class
28
+ add_index tn, :exception_class
29
+ add_index tn, :exception_message
30
+ add_index tn, :created_at
31
+ end
32
+ end
33
+ ActiveRecord::MIGRATIONS << Migration
34
+
35
+ self.table_name = Migration.table_name.to_s
36
+
37
+ attr_accessor :object, :original_object, :message_object
38
+
39
+ belongs_to :message, :class_name => 'ASIR::Coder::ActiveRecord::MessageModel'
40
+
41
+ validates_uniqueness_of :message_id
42
+ validates_presence_of :message_id
43
+ validates_presence_of :result_class
44
+ validates_presence_of :payload
45
+
46
+ before_save :prepare_for_save!
47
+ def prepare_for_save!
48
+ if result = self.object
49
+ message = self.message_object || result.message
50
+ self.external_id ||= result[:external_id]
51
+ self.message_id ||= result[:message_id]
52
+ if message
53
+ self.external_id ||= message[:external_id]
54
+ self.message_id ||= message[:message_id]
55
+ end
56
+ self.result_class = result.result.class.name.to_s
57
+ if e = result.exception
58
+ e = EncapsulatedException.new(e) unless EncapsulatedException === e
59
+ self.exception_class = e.exception_class
60
+ self.exception_message = e.exception_message
61
+ self.exception_backtrace = (e.exception_backtrace * "\n") << "\n";
62
+ end
63
+ end
64
+ # self.message_id &&= self.message_id.to_i
65
+ # pp self
66
+ if additional_data
67
+ raise TypeError, "additional_data is not a String" \
68
+ unless String === additional_data
69
+ end
70
+ end
71
+
72
+ after_save :update_original_object!
73
+ def update_original_object!
74
+ if original_object
75
+ original_object[:database_id] = self.id
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,7 @@
1
+ require "asir_activerecord/version"
2
+
3
+ module AsirActiverecord
4
+ end
5
+
6
+ require 'asir'
7
+ require 'asir/coder/active_record'
@@ -0,0 +1,3 @@
1
+ module AsirActiverecord
2
+ VERSION = "1.0.8"
3
+ end
@@ -0,0 +1,145 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ require 'asir/coder/yaml'
4
+ require 'asir/coder/json'
5
+
6
+ describe "ASIR::Coder::ActiveRecord" do
7
+ attr_accessor :message, :result, :data, :object, :coder, :transport
8
+
9
+ before :each do
10
+ self.data = { }
11
+ self.object = ASIR::Test::TestObject.new(nil)
12
+ self.message = ASIR::Message.new(object, nil, nil, nil, nil)
13
+ message.create_identifier!
14
+
15
+ self.result = ASIR::Result.new(message, nil)
16
+
17
+ ActiveRecord::Base.
18
+ establish_connection({
19
+ :adapter => 'postgresql',
20
+ :host => '127.0.0.1',
21
+ :port => 5432,
22
+ :username => 'test',
23
+ :password => 'test',
24
+ :database => 'test',
25
+ })
26
+ # Probe for tables
27
+ begin
28
+ ASIR::Coder::ActiveRecord::MessageModel.find(:first)
29
+ rescue ActiveRecord::StatementInvalid => exc
30
+ if exc.message =~ /does not exist/
31
+ ASIR::Coder::ActiveRecord::MIGRATIONS.each do | m |
32
+ m.migrate(:up)
33
+ end
34
+ end
35
+ end
36
+ ASIR::Coder::ActiveRecord::MessageModel.delete_all
37
+ ASIR::Coder::ActiveRecord::ResultModel.delete_all
38
+
39
+ self.coder =
40
+ ASIR::Coder::Database.
41
+ new(
42
+ :message_model => ASIR::Coder::ActiveRecord::MessageModel,
43
+ :result_model => ASIR::Coder::ActiveRecord::ResultModel,
44
+ :payload_coder => ASIR::Coder::Yaml.new,
45
+ :additional_data_coder => ASIR::Coder::JSON.new,
46
+ )
47
+ end
48
+
49
+ context "with sample Message and Result" do
50
+ attr_accessor :m, :r
51
+
52
+ before :each do
53
+ message.selector = :instance_method!
54
+ message.arguments = [ 1, "two", :three, 4.0 ]
55
+ message[:external_id] = 1234
56
+ message[:foo] = "bar"
57
+
58
+ result.result = "A String Result"
59
+ end
60
+ context "with saved MessageModel" do
61
+ before :each do
62
+ self.m = coder.prepare.encode(message)
63
+ m.prepare_for_save!
64
+ # $stderr.puts m.inspect
65
+ m.save!
66
+ m.id.should > 0
67
+ message[:database_id].should == m.id
68
+ self.m = m.class.find(m.id)
69
+ # $stderr.puts m.payload
70
+ end
71
+
72
+ it 'should encode Message.' do
73
+ m.external_id.should == message[:external_id]
74
+ m.receiver_class.should == message.receiver.class.name
75
+ m.message_type.should == '#'
76
+ m.selector.should == message.selector.to_s
77
+ ad = coder.additional_data_coder.prepare.decode(m.additional_data)
78
+ ad.keys.size.should == 2
79
+ ad['external_id'].should == message[:external_id]
80
+ ad['foo'].should == message[:foo]
81
+ m.description.should == "#{message.receiver.class.name}\##{message.selector}"
82
+ m.delay.should == nil
83
+ m.one_way.should == nil
84
+ m.payload.class.should == String
85
+ end
86
+
87
+ it 'should decode Message.' do
88
+ message_ = coder.prepare.decode(m)
89
+ message_.receiver.class.should == message.receiver.class
90
+ message_.selector.should == message.selector
91
+ message_.arguments.should == message.arguments
92
+ message_.description.should == message.description
93
+ ad = message.additional_data.dup
94
+ ad.delete(:database_id).should == m.id
95
+ message_.additional_data.should == ad
96
+ end
97
+
98
+ context "with saved ResultModel." do
99
+ before :each do
100
+ result[:external_id] = 3456
101
+ result[:bar] = "A String for Result"
102
+ # result.message = nil # Simulate Transport#...
103
+ self.r = coder.prepare.encode(result)
104
+ r.prepare_for_save!
105
+ # $stderr.puts m.inspect
106
+ r.save!
107
+ r.id.should > 0
108
+ result[:database_id].should == r.id
109
+ self.r = r.class.find(r.id)
110
+ # $stderr.puts r.payload
111
+ end
112
+
113
+ it 'should encode Result.' do
114
+ r.message_id.to_i.should == m.id
115
+ r.external_id.should == 3456
116
+ r.result_class.should == "String"
117
+ r.exception_class.should == nil
118
+ r.exception_message.should == nil
119
+ r.exception_backtrace.should == nil
120
+ # Note: JSON does not support Symbols.
121
+ ad = coder.additional_data_coder.prepare.decode(r.additional_data)
122
+ ade = result.additional_data
123
+ ad.keys.size.should == 2
124
+ ad['bar'].should == ade[:bar]
125
+ ad['external_id'].should == ade[:external_id]
126
+ r.payload.class.should == String
127
+ end
128
+
129
+ it 'should decode Result.' do
130
+ result_ = coder.prepare.decode(r)
131
+ result_.result.class.should == result.result.class
132
+ # Note: YAML does support Symbols.
133
+ ad = result_.additional_data
134
+ ade = result.additional_data.dup
135
+ ade.delete(:database_id).should == r.id
136
+ ad.should == ade
137
+ end
138
+
139
+ it 'should capture Unforwardable exceptions.' do
140
+ end
141
+ end
142
+ end # context
143
+ end # context
144
+ end
145
+
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ $:.unshift File.expand_path('../../../asir/lib', __FILE__)
3
+ $:.unshift File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'asir_activerecord'
6
+
7
+ module ASIR
8
+ module Test
9
+ class TestError < ::Exception; end
10
+ class TestObject
11
+ include ASIR::Client
12
+ attr_accessor :spec, :arg, :cls, :msg, :transport, :message
13
+ def initialize spec
14
+ @spec = spec
15
+ end
16
+
17
+ def get_data!
18
+ @transport = ASIR::Transport.current
19
+ @message = @transport && @transport.message
20
+ end
21
+
22
+ def return_argument arg
23
+ get_data!
24
+ @arg = arg
25
+ arg
26
+ end
27
+
28
+ def raise_exception! cls, msg
29
+ get_data!
30
+ @cls = cls
31
+ @msg = msg
32
+ raise cls, msg
33
+ end
34
+ end
35
+ end
36
+ end
37
+
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asir_activerecord
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.8
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kurt Stephens
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: asir
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.8
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: 1.0.8
30
+ - !ruby/object:Gem::Dependency
31
+ name: activerecord
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.0.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 3.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: pg
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.14.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.14.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 0.9.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.9.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 2.12.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: 2.12.0
94
+ - !ruby/object:Gem::Dependency
95
+ name: simplecov
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0.1'
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.1'
110
+ description: ASIR ActiveRecord Transport
111
+ email:
112
+ - ks.ruby@kurtstephens.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - .rspec
119
+ - Gemfile
120
+ - LICENSE.txt
121
+ - README.md
122
+ - Rakefile
123
+ - asir_activerecord.gemspec
124
+ - lib/asir/coder/active_record.rb
125
+ - lib/asir/coder/active_record/message_model.rb
126
+ - lib/asir/coder/active_record/result_model.rb
127
+ - lib/asir_activerecord.rb
128
+ - lib/asir_activerecord/version.rb
129
+ - spec/active_record_spec.rb
130
+ - spec/spec_helper.rb
131
+ homepage: http://github.com/kstephens/abstracting_services_in_ruby
132
+ licenses: []
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ segments:
144
+ - 0
145
+ hash: 2428040061942589441
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ segments:
153
+ - 0
154
+ hash: 2428040061942589441
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 1.8.24
158
+ signing_key:
159
+ specification_version: 3
160
+ summary: Store ASIR Message and Result objects in ActiveRecord.
161
+ test_files:
162
+ - spec/active_record_spec.rb
163
+ - spec/spec_helper.rb