procbuddy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+