procbuddy 0.0.1

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.
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+ 0.0.1 - Released August 11, 2011
2
+ * Initial release
data/README ADDED
@@ -0,0 +1,46 @@
1
+ == Rails SQL Procs
2
+
3
+ Library which adds SQL Stored Procedures to Rails. Adds create_proc and drop_proc to the ActiveRecord::ConnectionAdapters::AbstractAdapter (which makes them available to migrations) and adds support for dumping procs in the ActiveRecord::SchemaDumper.
4
+
5
+ == Installation
6
+
7
+ To install:
8
+
9
+ gem install procbuddy
10
+
11
+ Then add the following to your Rails config/environment.rb:
12
+
13
+ require_gem 'procbuddy'
14
+ require 'procbuddy'
15
+
16
+ == Usage
17
+
18
+ You can then use create_proc and drop_proc in your migrations. For example:
19
+
20
+ class CreateLameProc < ActiveRecord::Migration
21
+ def self.up
22
+ create_proc :lameness, <<EOSQL
23
+ SELECT 1 + 1 as lame
24
+ EOSQL
25
+ end
26
+
27
+ def self.down
28
+ drop_proc :lameness
29
+ end
30
+ end
31
+
32
+ This extension also adds support for procs in the ActiveRecord::SchemaDumper class.
33
+
34
+ The following drivers are supported:
35
+
36
+ SQL Server
37
+
38
+ == Known Issues
39
+
40
+ * Drivers not mentioned above are not supported.
41
+
42
+ If you find any issues please send an email to stewbawka@gmail.com .
43
+
44
+ == Contributing
45
+
46
+ If you would like to implement stored procedure support for other adapters then please drop me an email. Better yet, write up the adapter modifications and send them to me. :-)
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "procbuddy"
5
+ gemspec.summary = "sql stored procedures in migrations"
6
+ gemspec.description = "Provide create_proc and drop_proc in migrations. Also extends SchemaDumper to clue in about procs"
7
+ gemspec.email = "stewbawka@gmail.com"
8
+ gemspec.homepage = "http://blog.stewbawka.com""
9
+ gemspec.authors = ["Stuart Wade"]
10
+ end
11
+ Jeweler::GemcutterTasks.new
12
+ rescue LoadError
13
+ puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
14
+ end
@@ -0,0 +1,14 @@
1
+ module Procbuddy
2
+ module ConnectionAdapters #:nodoc:
3
+ # Abstract definition of a View
4
+ class ProcDefinition
5
+ attr_accessor :name, :sql
6
+
7
+ def initialize(base, name, sql)
8
+ @base = base
9
+ @name = name
10
+ @sql = sql
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ module Procbuddy
2
+ module ConnectionAdapters # :nodoc:
3
+ module SchemaStatements
4
+ # Create a proc.
5
+ def create_proc(name, sql, options={})
6
+ if supports_procs?
7
+ proc_definition = ProcDefinition.new(self, name, sql)
8
+
9
+ if options[:force]
10
+ drop_proc(name) rescue nil
11
+ end
12
+
13
+ create_sql = "CREATE PROCEDURE "
14
+ create_sql << "#{name}"
15
+ create_sql << proc_definition.sql
16
+ execute create_sql
17
+ end
18
+ end
19
+
20
+ # Drop a proc.
21
+ def drop_proc(name, options={})
22
+ if supports_procs?
23
+ drop_sql = "DROP PROCEDURE #{name}"
24
+ execute drop_sql
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class AbstractAdapter
4
+ # Subclasses should override and return true if they support triggers.
5
+ def supports_procs?
6
+ return false
7
+ end
8
+
9
+ # Get a list of all triggers for the current database
10
+ def procs(name = nil)
11
+ raise NotImplementedError, "procs is an abstract method"
12
+ end
13
+
14
+ # Get the code for the specified trigger
15
+ def proc_code(proc, name=nil)
16
+ raise NotImplementedError, "proc_code is an abstract method"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class MysqlAdapter
4
+ # Returns true as this adapter supports views.
5
+ def supports_views?
6
+ true
7
+ end
8
+
9
+ def tables(name = nil) #:nodoc:
10
+ tables = []
11
+ execute("SHOW TABLE STATUS", name).each { |row| tables << row[0] if row[17] != 'VIEW' }
12
+ tables
13
+ end
14
+
15
+ def views(name = nil) #:nodoc:
16
+ views = []
17
+ execute("SHOW TABLE STATUS", name).each { |row| views << row[0] if row[17] == 'VIEW' }
18
+ views
19
+ end
20
+
21
+ # Get the view select statement for the specified table.
22
+ def view_select_statement(view, name=nil)
23
+ row = execute("SHOW CREATE VIEW #{view}", name).each do |row|
24
+ return convert_statement(row[1]) if row[0] == view
25
+ end
26
+ raise "No view called #{view} found"
27
+ end
28
+
29
+ private
30
+ def convert_statement(s)
31
+ s.gsub!(/.* AS (select .*)/, '\1')
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,36 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class SQLServerAdapter
4
+ # Returns true as this adapter supports views.
5
+ def supports_procs?
6
+ true
7
+ end
8
+
9
+ # Returns all the trigger names from the currently connected schema.
10
+ def procs(name = nil)
11
+ select_values("SELECT name FROM sysobjects WHERE type = 'P'", name)
12
+ end
13
+
14
+ def proc_sp_helptext(proc, name=nil)
15
+ q =<<-ENDSQL
16
+ SELECT OBJECT_DEFINITION(OBJECT_ID('#{trigger}'));
17
+ ENDSQL
18
+
19
+ proc_def = select_value(q, name)
20
+
21
+ if !proc_def.blank?
22
+ return proc_def
23
+ else
24
+ raise "No proc called #{proc} found"
25
+ end
26
+
27
+ end
28
+
29
+ def proc_code(proc, name=nil)
30
+ proc_def = proc_sp_helptext(proc, name)
31
+ proc_def.sub(/^CREATE PROCEDURE \w+\s+/, '')
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,66 @@
1
+ module ActiveRecord
2
+ class SchemaDumper
3
+
4
+ # A list of triggers which should not be dumped to the schema.
5
+ # Acceptable values are strings as well as regexp.
6
+ # This setting is only used if ActiveRecord::Base.schema_format == :ruby
7
+ cattr_accessor :ignore_procs
8
+ @@ignore_procs = []
9
+
10
+ def trailer_with_procs(stream)
11
+ # do nothing...we'll call this later
12
+ end
13
+ alias_method_chain :trailer, :triggers
14
+
15
+ # Add procs to the end of the dump stream
16
+ def dump_with_procs(stream)
17
+ dump_without_procs(stream)
18
+ begin
19
+ if @connection.supports_procs?
20
+ procs(stream)
21
+ end
22
+ rescue => e
23
+ ActiveRecord::Base.logger.error "Unable to dump procs: #{e}"
24
+ end
25
+ trailer_without_procs(stream)
26
+ stream
27
+ end
28
+ alias_method_chain :dump, :procs
29
+
30
+ # Add procs to the stream
31
+ def procs(stream)
32
+ @connection.procs.sort.each do |t|
33
+ next if ["schema_info", ignore_procs].flatten.any? do |ignored|
34
+ case ignored
35
+ when String: t == ignored
36
+ when Regexp: t =~ ignored
37
+ else
38
+ raise StandardError, 'ActiveRecord::SchemaDumper.ignore_procs accepts an array of String and / or Regexp values.'
39
+ end
40
+ end
41
+ proc(t, stream)
42
+ end
43
+ end
44
+
45
+ # Add the specified proc to the stream
46
+ def proc(proc, stream)
47
+ begin
48
+ t = StringIO.new
49
+ t.print " proc_code = <<EOSQL\n"
50
+ t.print @connection.proc_code(proc)
51
+ t.print "EOSQL\n"
52
+ t.print " create_proc(#{proc.to_sym.inspect}, "
53
+ t.print "proc_code, "
54
+ t.print ":force => true)\n"
55
+ t.rewind
56
+ stream.print t.read
57
+ rescue => e
58
+ stream.puts "# Could not dump proc #{proc.inspect} because of following #{e.class}"
59
+ stream.puts "# #{e.message}"
60
+ stream.puts "# #{e.trace}"
61
+ end
62
+
63
+ stream
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,9 @@
1
+ module Procbuddy
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/procbuddy.rb ADDED
@@ -0,0 +1,55 @@
1
+ # Procbuddy is based the rails_sql_views gem developped by Anthony Eden
2
+ # I have included his original copyright notice since this gem is derivative of his work.
3
+ #
4
+ #--
5
+ # Copyright (c) 2006 Anthony Eden
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #++
26
+
27
+ $:.unshift(File.dirname(__FILE__)) unless
28
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
29
+
30
+ require 'rubygems'
31
+
32
+ #unless Kernel.respond_to?(:gem)
33
+ # Kernel.send :alias_method, :gem, :require_gem
34
+ #end
35
+
36
+ unless defined?(ActiveRecord)
37
+ begin
38
+ $:.unshift(File.dirname(__FILE__) + "/../../activerecord/lib")
39
+ require 'active_record'
40
+ rescue LoadError
41
+ gem 'activerecord'
42
+ end
43
+ end
44
+
45
+ #require 'core_ext/module'
46
+
47
+ require 'procbuddy/connection_adapters/abstract/schema_definitions'
48
+ require 'procbuddy/connection_adapters/abstract/schema_statements'
49
+ #require 'procbuddy/connection_adapters/mysql_adapter'
50
+ require 'procbuddy/connection_adapters/sqlserver_adapter'
51
+ require 'procbuddy/schema_dumper'
52
+
53
+ class ActiveRecord::ConnectionAdapters::AbstractAdapter
54
+ include Procbuddy::ConnectionAdapters::SchemaStatements
55
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: procbuddy
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Stuart Wade
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-11 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Provide create_proc and drop_proc in migrations. Also extends SchemaDumper to clue in about stored procedures
23
+ email: stewbawka@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/procbuddy/version.rb
32
+ - lib/procbuddy/schema_dumper.rb
33
+ - lib/procbuddy/connection_adapters/mysql_adapter.rb
34
+ - lib/procbuddy/connection_adapters/sqlserver_adapter.rb
35
+ - lib/procbuddy/connection_adapters/abstract_adapter.rb
36
+ - lib/procbuddy/connection_adapters/abstract/schema_statements.rb
37
+ - lib/procbuddy/connection_adapters/abstract/schema_definitions.rb
38
+ - lib/procbuddy.rb
39
+ - CHANGELOG
40
+ - Rakefile
41
+ - README
42
+ has_rdoc: true
43
+ homepage: http://blog.stewbawka.com
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 19
66
+ segments:
67
+ - 1
68
+ - 3
69
+ - 4
70
+ version: 1.3.4
71
+ requirements: []
72
+
73
+ rubyforge_project: procbuddy
74
+ rubygems_version: 1.5.3
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: sql stored procedures in migrations
78
+ test_files: []
79
+