squirm 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -11,6 +11,7 @@ spec/reports
11
11
  test/tmp
12
12
  test/version_tmp
13
13
  tmp
14
+ coverage
14
15
 
15
16
  # YARD artifacts
16
17
  .yardoc
@@ -1,19 +1,18 @@
1
1
  Copyright (c) 2011 Norman Clarke and Business Vision S.A.
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining a copy
4
- of this software and associated documentation files (the "Software"), to deal
5
- in the Software without restriction, including without limitation the rights
6
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- copies of the Software, and to permit persons to whom the Software is
8
- furnished to do so, subject to the following conditions:
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
9
 
10
10
  The above copyright notice and this permission notice shall be included in all
11
11
  copies or substantial portions of the Software.
12
12
 
13
13
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
- SOFTWARE.
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -42,23 +42,11 @@ Here's a quick demo of how you might use it:
42
42
  id = create.call(email: "johndoe@example.com", name: "John Doe")
43
43
 
44
44
  In and of itself, Squirm offers very little, but is meant to be a basic building
45
- block for other libraries, such as [Squirm
45
+ block for other libraries, such as [Squirm Rails](https://github.com/bvision/squirm_rails),
46
+ which adds stored procedure support to Active Record, or [Squirm
46
47
  Model](https://github.com/bvision/squirm_model), which supplies an Active Model
47
48
  compatible ORM based on stored procedures.
48
49
 
49
- ## Using it with Rails
50
-
51
- Squirm comes with built-in support to make it work seamlessly with Active Record:
52
-
53
- class Person < ActiveRecord::Base
54
- procedure :say_hello
55
- end
56
-
57
- p = Person.find(23)
58
- p.say_hello
59
-
60
- More documentation coming soon.
61
-
62
50
  ## Author
63
51
 
64
52
  Norman Clarke <nclarke@bvision.com>
@@ -1,6 +1,7 @@
1
1
  require "squirm/core"
2
2
  require "squirm/pool"
3
3
  require "squirm/procedure"
4
+ require "squirm/executor"
4
5
 
5
6
  =begin
6
7
  Squirm is an experimental anti-ORM for database-loving programmers who want to
@@ -68,8 +69,6 @@ end
68
69
 
69
70
  module Kernel
70
71
  def Squirm(&block)
71
- Squirm.instance_eval(&block)
72
+ Squirm::Executor.eval(&block)
72
73
  end
73
- end
74
-
75
- require "squirm/rails" if defined? Rails
74
+ end
@@ -6,6 +6,8 @@ module Squirm
6
6
  # The core DSL used by Squirm.
7
7
  module Core
8
8
 
9
+ attr :pool
10
+
9
11
  # Establishes a connection pool.
10
12
  # @param [Hash] options The connection options
11
13
  # @option options [String] :pool Use the given pool rather than Squirm's.
@@ -34,8 +36,7 @@ module Squirm
34
36
  # Executes the query and passes the result to the block you specify.
35
37
  def exec(*args, &block)
36
38
  if current = Thread.current[:squirm_connection]
37
- conn = current.respond_to?(:raw_connection) ? current.raw_connection : current
38
- conn.exec(*args, &block)
39
+ current.exec(*args, &block)
39
40
  else
40
41
  use {|conn| conn.exec(*args, &block)}
41
42
  end
@@ -45,12 +46,6 @@ module Squirm
45
46
  Procedure.load(*args)
46
47
  end
47
48
 
48
- # Gets the connection pool.
49
- # @return [Squirm::Pool] The connection pool.
50
- def pool
51
- @pool if defined? @pool
52
- end
53
-
54
49
  # Performs a #use inside a transaction.
55
50
  def transaction
56
51
  use do |connection|
@@ -78,8 +73,7 @@ module Squirm
78
73
  conn_given = !!conn
79
74
  conn = conn_given ? conn : @pool.checkout
80
75
  begin
81
- Thread.current[:squirm_connection] = conn
82
- yield conn.respond_to?(:raw_connection) ? conn.raw_connection : conn
76
+ yield Thread.current[:squirm_connection] = conn
83
77
  ensure
84
78
  Thread.current[:squirm_connection] = nil
85
79
  @pool.checkin conn unless conn_given
@@ -0,0 +1,17 @@
1
+ module Squirm
2
+
3
+ # This class exists simply to provide a space in which to evaluate blocked
4
+ # passed to the Kernel.Squirm method.
5
+ class Executor
6
+ include Core
7
+
8
+ def self.eval(&block)
9
+ executor = new(Squirm.pool)
10
+ executor.instance_eval(&block)
11
+ end
12
+
13
+ def initialize(pool)
14
+ @pool = pool
15
+ end
16
+ end
17
+ end
@@ -163,14 +163,14 @@ module Squirm
163
163
  @hash = self.class.hashify(string)
164
164
  end
165
165
 
166
- # Formats arguments used to call the stored procedure.
166
+ # Formats the arguments used to call the stored procedure.
167
167
  #
168
- # When given a anything other than a hash, the arguments are returned
168
+ # When given anything other than a hash, the arguments are returned
169
169
  # without modification.
170
170
  #
171
- # When given a hash, the return value is an array or arguments in the
171
+ # When given a hash, the return value is an array of arguments in the
172
172
  # order needed when calling the procedure. Missing values are replaced by
173
- # nil.
173
+ # +nil+.
174
174
  #
175
175
  # @example
176
176
  # # Assume a stored procedure with a definition like the following:
@@ -1,3 +1,3 @@
1
1
  module Squirm
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -10,6 +10,26 @@ describe Squirm do
10
10
  assert_equal '"table"', Squirm.quote_ident("table")
11
11
  end
12
12
 
13
+ it "should be a module" do
14
+ assert Squirm.is_a? Module
15
+ end
16
+
17
+ it "should evaluate a block inside an Executor instance" do
18
+ assert_raises RuntimeError do
19
+ Squirm do
20
+ raise "SUCCESS" if self.class == Squirm::Executor
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#procedure" do
26
+ it "should get a procedure instance and load it" do
27
+ Squirm.connect $squirm_test_connection
28
+ proc = Squirm.procedure "date", args: "abstime", schema: "pg_catalog"
29
+ assert proc.kind_of? Squirm::Procedure
30
+ end
31
+ end
32
+
13
33
  describe "#connect" do
14
34
  it "should use a pool if given" do
15
35
  pool = OpenStruct.new
@@ -53,6 +73,13 @@ describe Squirm do
53
73
  end
54
74
  assert_nil Thread.current[:squirm_connection]
55
75
  end
76
+
77
+ it "should use connection if given as an argument" do
78
+ mock = Object.new
79
+ Squirm.use(mock) do |conn|
80
+ assert mock == conn
81
+ end
82
+ end
56
83
  end
57
84
 
58
85
  describe "#exec" do
@@ -93,24 +93,31 @@ describe Squirm::Procedure do
93
93
  end
94
94
 
95
95
  it "should load an overloaded functions if instance was initialized with :args" do
96
- assert Squirm::Procedure.new("date", :args => "abstime", :schema => "pg_catalog").load
96
+ assert Squirm::Procedure.new("date", args: "abstime", schema: "pg_catalog").load
97
97
  end
98
98
 
99
99
  end
100
100
 
101
+ describe "#to_proc" do
102
+ before {Squirm.connect $squirm_test_connection}
103
+
104
+ it "should return a proc which calls the procedure" do
105
+ proc = Squirm::Procedure.new("date", args: "abstime", schema: "pg_catalog").load.to_proc
106
+ proc.call("Jan 1, 2011") {|result| assert_instance_of PGresult, result}
107
+ end
108
+ end
109
+
101
110
  describe "#call" do
102
111
 
103
112
  before {Squirm.connect $squirm_test_connection}
104
113
 
105
114
  it "should yield the result to a block if given" do
106
- proc = Squirm::Procedure.new("date", :args => "abstime", :schema => "pg_catalog").load
107
- proc.call("Jan 1, 2011") do |result|
108
- assert_instance_of PGresult, result
109
- end
115
+ proc = Squirm::Procedure.new("date", args: "abstime", schema: "pg_catalog").load
116
+ proc.call("Jan 1, 2011") {|result| assert_instance_of PGresult, result}
110
117
  end
111
118
 
112
119
  it "should return the value of a single-row result" do
113
- proc = Squirm::Procedure.new("date", :args => "abstime", :schema => "pg_catalog").load
120
+ proc = Squirm::Procedure.new("date", args: "abstime", schema: "pg_catalog").load
114
121
  assert_equal "2011-01-01", proc.call("Jan 1, 2011")
115
122
  end
116
123
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squirm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-23 00:00:00.000000000 Z
12
+ date: 2011-12-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
16
- requirement: &70228168578720 !ruby/object:Gem::Requirement
16
+ requirement: &70292131700860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2.6'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70228168578720
24
+ version_requirements: *70292131700860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: pg
27
- requirement: &70228168571760 !ruby/object:Gem::Requirement
27
+ requirement: &70292131700180 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 0.11.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70228168571760
35
+ version_requirements: *70292131700180
36
36
  description: ! '"Squirm is an anti-ORM for database-loving programmers"'
37
37
  email:
38
38
  - norman@njclarke.com
@@ -47,14 +47,10 @@ files:
47
47
  - Rakefile
48
48
  - lib/squirm.rb
49
49
  - lib/squirm/core.rb
50
+ - lib/squirm/executor.rb
50
51
  - lib/squirm/pool.rb
51
52
  - lib/squirm/procedure.rb
52
53
  - lib/squirm/procedure.sql
53
- - lib/squirm/rails.rb
54
- - lib/squirm/rails/generator.rb
55
- - lib/squirm/rails/squirm.rake
56
- - lib/squirm/rails/stored_procedures.sql
57
- - lib/squirm/rails/unit_test.rb
58
54
  - lib/squirm/version.rb
59
55
  - spec/core_spec.rb
60
56
  - spec/helper.rb
@@ -1,54 +0,0 @@
1
- module Squirm
2
-
3
- # Support for working with procedures inside Active Record models. This exists
4
- # primarily to ensure that stored procedure calls are done inside the same
5
- # connection used by the AR model, to avoid transaction opacity issues that
6
- # could arise if AR and Squirm are used different connections.
7
- module ActiveRecord
8
- class Procedure < ::Squirm::Procedure
9
- attr_accessor :connector
10
-
11
- def call(*args, &block)
12
- Squirm.use(connector.call) do
13
- super
14
- end
15
- end
16
- end
17
-
18
- def self.included(model_class)
19
- model_class.extend ClassMethods
20
- end
21
-
22
- module ClassMethods
23
- def procedure(name, options = {}, &block)
24
- self.class_eval(<<-EOM, __FILE__, __LINE__ + 1)
25
- @@__squirm ||= {}
26
- @@__squirm[:#{name}] = Squirm::ActiveRecord::Procedure.new("#{name}")
27
- @@__squirm[:#{name}].connector = ->{connection}
28
- @@__squirm[:#{name}].load
29
- def #{options[:as] or name}(options = {})
30
- options[:id] ||= id if @@__squirm[:#{name}].arguments.hash.has_key?(:id)
31
- @@__squirm[:#{name}].call(options)
32
- end
33
- EOM
34
- end
35
- end
36
- end
37
-
38
- class Railtie < Rails::Railtie
39
- initializer "squirm.setup" do
40
- Squirm.connect pool: ::ActiveRecord::Base.connection_pool
41
- ::ActiveRecord::Base.send :include, Squirm::ActiveRecord
42
- end
43
-
44
- rake_tasks do
45
- load File.expand_path("../rails/squirm.rake", __FILE__)
46
- end
47
-
48
- generators do
49
- require File.expand_path("../rails/generator", __FILE__)
50
- end
51
-
52
- end
53
- end
54
-
@@ -1,11 +0,0 @@
1
- require "rails/generators"
2
-
3
- module Squirm
4
- class Install < ::Rails::Generators::Base
5
- source_root File.dirname(__FILE__)
6
- def install_functions
7
- copy_file "stored_procedures.sql", "db/stored_procedures.sql"
8
- copy_file "unit_test.rb", "test/unit/stored_procedures_test.rb"
9
- end
10
- end
11
- end
@@ -1,8 +0,0 @@
1
- namespace :db do
2
- namespace :schema do
3
- task :load do
4
- functions = File.read(Rails.root.join("db", "stored_procedures.sql"))
5
- ActiveRecord::Base.connection.execute functions
6
- end
7
- end
8
- end
@@ -1,11 +0,0 @@
1
- /*
2
- This is the stored_procedures.sql file used by Squirm. Define your Postgres
3
- stored procedures in this file and they will be loaded at the end of any calls
4
- to the db:schema:load Rake task.
5
- */
6
-
7
- CREATE OR REPLACE FUNCTION hello_world() RETURNS TEXT AS $$
8
- BEGIN
9
- RETURN 'hello world!';
10
- END;
11
- $$ LANGUAGE 'PLPGSQL'
@@ -1,10 +0,0 @@
1
- require 'test_helper'
2
-
3
- class StoredProceduresTest < ActiveSupport::TestCase
4
-
5
- test "hello world should emit a greeting" do
6
- procedure = Squirm.procedure "hello_world"
7
- assert_equal "hello world!", procedure.call
8
- end
9
-
10
- end