activerecord-postgresql-extensions 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -4,7 +4,15 @@
4
4
  require 'rubygems'
5
5
  require 'rubygems/package_task'
6
6
  require 'rake/testtask'
7
- require 'rdoc/task'
7
+ require 'rake/rdoctask'
8
+
9
+ if RUBY_VERSION >= '1.9'
10
+ begin
11
+ gem 'psych'
12
+ rescue Exception => e
13
+ # it's okay, fall back on the bundled psych
14
+ end
15
+ end
8
16
 
9
17
  $:.push 'lib'
10
18
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.9
1
+ 0.0.10
@@ -4,14 +4,14 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{activerecord-postgresql-extensions}
8
- s.version = "0.0.9"
7
+ s.name = "activerecord-postgresql-extensions"
8
+ s.version = "0.0.10"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = [%q{J Smith}]
12
- s.date = %q{2011-07-14}
13
- s.description = %q{A whole bunch of extensions the ActiveRecord PostgreSQL adapter.}
14
- s.email = %q{code@zoocasa.com}
11
+ s.authors = ["J Smith"]
12
+ s.date = "2011-10-05"
13
+ s.description = "A whole bunch of extensions the ActiveRecord PostgreSQL adapter."
14
+ s.email = "code@zoocasa.com"
15
15
  s.extra_rdoc_files = [
16
16
  "README.rdoc"
17
17
  ]
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
30
30
  "lib/postgresql_extensions/postgresql_indexes.rb",
31
31
  "lib/postgresql_extensions/postgresql_languages.rb",
32
32
  "lib/postgresql_extensions/postgresql_permissions.rb",
33
+ "lib/postgresql_extensions/postgresql_roles.rb",
33
34
  "lib/postgresql_extensions/postgresql_rules.rb",
34
35
  "lib/postgresql_extensions/postgresql_schemas.rb",
35
36
  "lib/postgresql_extensions/postgresql_sequences.rb",
@@ -45,16 +46,17 @@ Gem::Specification.new do |s|
45
46
  "test/index_test.rb",
46
47
  "test/languages_test.rb",
47
48
  "test/permissions_test.rb",
49
+ "test/roles_test.rb",
48
50
  "test/rules_test.rb",
49
51
  "test/schemas_test.rb",
50
52
  "test/sequences_test.rb",
51
53
  "test/tables_test.rb",
52
54
  "test/test_helper.rb"
53
55
  ]
54
- s.homepage = %q{http://github.com/zoocasa/activerecord-postgresql-extensions}
55
- s.require_paths = [%q{lib}]
56
- s.rubygems_version = %q{1.8.5}
57
- s.summary = %q{A whole bunch of extensions the ActiveRecord PostgreSQL adapter.}
56
+ s.homepage = "http://github.com/zoocasa/activerecord-postgresql-extensions"
57
+ s.require_paths = ["lib"]
58
+ s.rubygems_version = "1.8.10"
59
+ s.summary = "A whole bunch of extensions the ActiveRecord PostgreSQL adapter."
58
60
 
59
61
  if s.respond_to? :specification_version then
60
62
  s.specification_version = 3
@@ -21,6 +21,7 @@ dirname = File.join(File.dirname(__FILE__), 'postgresql_extensions')
21
21
  postgresql_views
22
22
  postgresql_geometry
23
23
  postgresql_types
24
+ postgresql_roles
24
25
  foreign_key_associations
25
26
  }.each do |file|
26
27
  require File.join(dirname, file)
@@ -426,6 +426,43 @@ module ActiveRecord
426
426
  SQL
427
427
  end
428
428
 
429
+ def roles(name = nil)
430
+ query(<<-SQL, name).map { |row| row[0] }
431
+ SELECT rolname
432
+ FROM pg_roles
433
+ SQL
434
+ end
435
+
436
+ def role_exists?(name)
437
+ roles.include?(name)
438
+ end
439
+
440
+ # Sets the current database role/user. The :duration option can be set to
441
+ # :session or :local as described in the PostgreSQL docs.
442
+ def set_role(role, options = {})
443
+ duration = if options[:duration]
444
+ if [ :session, :local ].include?(options[:duration])
445
+ options[:duration].to_s.upcase
446
+ else
447
+ raise ArgumentError.new("The :duration option must be one of :session or :local.")
448
+ end
449
+ end
450
+
451
+ sql = 'SET '
452
+ sql << "#{duration} " if duration
453
+ sql << "ROLE #{quote_role(role)}"
454
+ execute(sql, "Setting current role")
455
+ end
456
+
457
+ def reset_role
458
+ execute('RESET ROLE')
459
+ end
460
+
461
+ def current_role
462
+ execute('SELECT current_role')
463
+ end
464
+ alias :current_user :current_role
465
+
429
466
  # Returns an Array of tables to ignore.
430
467
  def ignored_tables(name = nil)
431
468
  query(<<-SQL, name).map { |row| row[0] }
@@ -0,0 +1,127 @@
1
+
2
+ require 'active_record/connection_adapters/postgresql_adapter'
3
+
4
+ module ActiveRecord
5
+ class InvalidRoleAction < ActiveRecordError #:nodoc:
6
+ def initialize(action)
7
+ super("Invalid role action - #{action}")
8
+ end
9
+ end
10
+
11
+ module ConnectionAdapters
12
+ class PostgreSQLAdapter < AbstractAdapter
13
+ def create_role(name, options = {})
14
+ execute PostgreSQLRole.new(self, :create, name, options).to_sql
15
+ end
16
+ alias :create_user :create_role
17
+
18
+ def alter_role(name, options = {})
19
+ execute PostgreSQLRole.new(self, :alter, name, options).to_sql
20
+ end
21
+ alias :alter_user :alter_role
22
+
23
+ def drop_role(name, options = {})
24
+ sql = 'DROP ROLE '
25
+ sql << 'IF EXISTS ' if options[:if_exists]
26
+ sql << Array(name).collect { |r| quote_role(r) }.join(', ')
27
+ execute sql
28
+ end
29
+ alias :drop_user :drop_role
30
+ end
31
+
32
+ # This is a base class for PostgreSQLGrantPrivilege and
33
+ # PostgreSQLRevokePrivilege and is not meant to be used directly.
34
+ class PostgreSQLRole
35
+ attr_accessor :base, :action, :name, :options
36
+
37
+ def initialize(base, action, name, options = {}) #:nodoc:
38
+ assert_valid_action(action)
39
+
40
+ @base, @action, @name, @options = base, action, name, options
41
+ end
42
+
43
+ def to_sql #:nodoc:
44
+ sql = Array.new
45
+ if action == :create
46
+ sql << 'CREATE'
47
+ else
48
+ sql << 'ALTER'
49
+ end
50
+ sql << "ROLE #{base.quote_role(name)}"
51
+
52
+ if options[:superuser]
53
+ sql << 'SUPERUSER'
54
+ end
55
+
56
+ if options[:create_db]
57
+ sql << 'CREATEDB'
58
+ end
59
+
60
+ if options[:create_role]
61
+ sql << 'CREATEROLE'
62
+ end
63
+
64
+ if options.has_key?(:inherit) && !options[:inherit]
65
+ sql << 'NOINHERIT'
66
+ end
67
+
68
+ if options[:login]
69
+ sql << 'LOGIN'
70
+ end
71
+
72
+ if options[:connection_limit]
73
+ sql << "CONNECTION LIMIT #{options[:connection_limit].to_i}"
74
+ end
75
+
76
+ if options[:password]
77
+ if options.has_key?(:encrypted_password)
78
+ if options[:encrypted_password]
79
+ sql << 'ENCRYPTED'
80
+ else
81
+ sql << 'UNENCRYPTED'
82
+ end
83
+ end
84
+
85
+ sql << 'PASSWORD'
86
+ sql << base.quote(options[:password])
87
+ end
88
+
89
+ if options[:valid_until]
90
+ sql << 'VALID UNTIL'
91
+ timestamp = case options[:valid_until]
92
+ when Date, Time, DateTime
93
+ options[:valid_until].to_s(:sql)
94
+ else
95
+ options[:valid_until].to_s
96
+ end
97
+ sql << base.quote(timestamp)
98
+ end
99
+
100
+ if options[:in_role].present?
101
+ sql << 'IN ROLE'
102
+ sql << Array(options[:in_role]).collect { |r| base.quote_role(r) }.join(', ')
103
+ end
104
+
105
+ if options[:role].present?
106
+ sql << 'ROLE'
107
+ sql << Array(options[:role]).collect { |r| base.quote_role(r) }.join(', ')
108
+ end
109
+
110
+ if options[:admin].present?
111
+ sql << 'ADMIN'
112
+ sql << Array(options[:admin]).collect { |r| base.quote_role(r) }.join(', ')
113
+ end
114
+
115
+ sql.join(' ')
116
+ end
117
+ alias :to_s :to_sql
118
+
119
+ private
120
+ def assert_valid_action(action) #:nodoc:
121
+ if ![ :create, :alter ].include?(action)
122
+ raise ActiveRecord::InvalidRoleAction.new(action)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
data/test/adapter_test.rb CHANGED
@@ -50,4 +50,35 @@ class AdapterExtensionTests < Test::Unit::TestCase
50
50
  assert_equal(:integer, col.send(:simplified_type, 'integer'))
51
51
  assert_equal(nil, col.send(:simplified_type, 'complete_nonsense'))
52
52
  end
53
+
54
+ def test_set_role
55
+ ARBC.set_role('foo')
56
+ ARBC.set_role('foo', :duration => :local)
57
+ ARBC.set_role('foo', :duration => :session)
58
+
59
+ assert_equal([
60
+ %{SET ROLE "foo"},
61
+ %{SET LOCAL ROLE "foo"},
62
+ %{SET SESSION ROLE "foo"}
63
+ ], ARBC.statements)
64
+
65
+ assert_raise(ArgumentError) do
66
+ ARBC.set_role('foo', :duration => :nonsense)
67
+ end
68
+ end
69
+
70
+ def test_reset_role
71
+ ARBC.reset_role
72
+ assert_equal([ 'RESET ROLE' ], ARBC.statements)
73
+ end
74
+
75
+ def test_current_role
76
+ ARBC.current_role
77
+ ARBC.current_user
78
+
79
+ assert_equal([
80
+ 'SELECT current_role',
81
+ 'SELECT current_role'
82
+ ], ARBC.statements)
83
+ end
53
84
  end
@@ -6,11 +6,11 @@ class FunctionsTests < Test::Unit::TestCase
6
6
  include PostgreSQLExtensionsTestHelper
7
7
 
8
8
  def test_create_function
9
- Mig.create_function(:test, :integer, :integer, :sql) do
9
+ ARBC.create_function(:test, :integer, :integer, :sql) do
10
10
  "select 10;"
11
11
  end
12
12
 
13
- Mig.create_function(:test, :integer, :integer, :sql, {
13
+ ARBC.create_function(:test, :integer, :integer, :sql, {
14
14
  :force => true,
15
15
  :delimiter => '$__$',
16
16
  :behavior => :immutable,
@@ -43,8 +43,8 @@ LANGUAGE "sql"
43
43
  end
44
44
 
45
45
  def test_drop_function
46
- Mig.drop_function(:test, :integer)
47
- Mig.drop_function(:test, :integer, :if_exists => true, :cascade => true)
46
+ ARBC.drop_function(:test, :integer)
47
+ ARBC.drop_function(:test, :integer, :if_exists => true, :cascade => true)
48
48
 
49
49
  assert_equal([
50
50
  "DROP FUNCTION \"test\"(integer)",
@@ -53,7 +53,7 @@ LANGUAGE "sql"
53
53
  end
54
54
 
55
55
  def test_rename_function
56
- Mig.rename_function(:test, 'integer, text', :foo)
56
+ ARBC.rename_function(:test, 'integer, text', :foo)
57
57
 
58
58
  assert_equal([
59
59
  "ALTER FUNCTION \"test\"(integer, text) RENAME TO \"foo\""
@@ -61,7 +61,7 @@ LANGUAGE "sql"
61
61
  end
62
62
 
63
63
  def test_alter_function_owner
64
- Mig.alter_function_owner(:test, 'integer, text', :admin)
64
+ ARBC.alter_function_owner(:test, 'integer, text', :admin)
65
65
 
66
66
  assert_equal([
67
67
  "ALTER FUNCTION \"test\"(integer, text) OWNER TO \"admin\""
@@ -69,7 +69,7 @@ LANGUAGE "sql"
69
69
  end
70
70
 
71
71
  def test_alter_function_schema
72
- Mig.alter_function_schema(:test, 'integer, text', :geospatial)
72
+ ARBC.alter_function_schema(:test, 'integer, text', :geospatial)
73
73
 
74
74
  assert_equal([
75
75
  "ALTER FUNCTION \"test\"(integer, text) SET SCHEMA \"geospatial\""
@@ -77,9 +77,9 @@ LANGUAGE "sql"
77
77
  end
78
78
 
79
79
  def test_alter_function
80
- Mig.alter_function('my_function', 'integer', :rename_to => 'another_function')
81
- Mig.alter_function('another_function', 'integer', :owner_to => 'jdoe')
82
- Mig.alter_function('my_function', 'integer') do |f|
80
+ ARBC.alter_function('my_function', 'integer', :rename_to => 'another_function')
81
+ ARBC.alter_function('another_function', 'integer', :owner_to => 'jdoe')
82
+ ARBC.alter_function('my_function', 'integer') do |f|
83
83
  f.rename_to 'another_function'
84
84
  f.owner_to 'jdoe'
85
85
  f.set_schema 'foo'
@@ -6,8 +6,8 @@ class LanguagesTests < Test::Unit::TestCase
6
6
  include PostgreSQLExtensionsTestHelper
7
7
 
8
8
  def test_create_language
9
- Mig.create_language(:foo)
10
- Mig.create_language(
9
+ ARBC.create_language(:foo)
10
+ ARBC.create_language(
11
11
  :foo,
12
12
  :trusted => true,
13
13
  :call_handler => 'plpgsql',
@@ -21,8 +21,8 @@ class LanguagesTests < Test::Unit::TestCase
21
21
  end
22
22
 
23
23
  def test_drop_language
24
- Mig.drop_language(:foo)
25
- Mig.drop_language(:foo, :if_exists => true, :cascade => true)
24
+ ARBC.drop_language(:foo)
25
+ ARBC.drop_language(:foo, :if_exists => true, :cascade => true)
26
26
 
27
27
  assert_equal([
28
28
  "DROP PROCEDURAL LANGUAGE \"foo\"",
@@ -31,7 +31,7 @@ class LanguagesTests < Test::Unit::TestCase
31
31
  end
32
32
 
33
33
  def test_alter_language_name
34
- Mig.alter_language_name(:foo, :bar)
34
+ ARBC.alter_language_name(:foo, :bar)
35
35
 
36
36
  assert_equal([
37
37
  "ALTER PROCEDURAL LANGUAGE \"foo\" RENAME TO \"bar\""
@@ -39,7 +39,7 @@ class LanguagesTests < Test::Unit::TestCase
39
39
  end
40
40
 
41
41
  def test_alter_language_owner
42
- Mig.alter_language_owner(:foo, :bar)
42
+ ARBC.alter_language_owner(:foo, :bar)
43
43
 
44
44
  assert_equal([
45
45
  "ALTER PROCEDURAL LANGUAGE \"foo\" OWNER TO \"bar\""
@@ -0,0 +1,63 @@
1
+
2
+ $: << File.dirname(__FILE__)
3
+ require 'test_helper'
4
+
5
+ class RolesTests < Test::Unit::TestCase
6
+ include PostgreSQLExtensionsTestHelper
7
+
8
+ def test_create_role
9
+ ARBC.create_role('foo')
10
+ ARBC.create_role('foo', {
11
+ :superuser => true,
12
+ :create_db => true,
13
+ :create_role => true,
14
+ :inherit => false,
15
+ :login => true,
16
+ :connection_limit => 10,
17
+ :password => 'testing',
18
+ :encrypted_password => true,
19
+ :valid_until => Date.parse('2011-10-12'),
20
+ :in_role => 'bar',
21
+ :role => 'baz',
22
+ :admin => 'blort'
23
+ })
24
+
25
+ assert_equal([
26
+ 'CREATE ROLE "foo"',
27
+ %{CREATE ROLE "foo" SUPERUSER CREATEDB CREATEROLE NOINHERIT LOGIN CONNECTION LIMIT 10 ENCRYPTED PASSWORD 'testing' VALID UNTIL '2011-10-12' IN ROLE "bar" ROLE "baz" ADMIN "blort"}
28
+ ], statements)
29
+ end
30
+
31
+ def test_alter_role
32
+ ARBC.alter_role('foo', {
33
+ :superuser => true,
34
+ :create_db => true,
35
+ :create_role => true,
36
+ :inherit => false,
37
+ :login => true,
38
+ :connection_limit => 10,
39
+ :password => 'testing',
40
+ :encrypted_password => true,
41
+ :valid_until => Date.parse('2011-10-12'),
42
+ :in_role => 'bar',
43
+ :role => 'baz',
44
+ :admin => 'blort'
45
+ })
46
+
47
+ assert_equal([
48
+ %{ALTER ROLE "foo" SUPERUSER CREATEDB CREATEROLE NOINHERIT LOGIN CONNECTION LIMIT 10 ENCRYPTED PASSWORD 'testing' VALID UNTIL '2011-10-12' IN ROLE "bar" ROLE "baz" ADMIN "blort"}
49
+ ], statements)
50
+ end
51
+
52
+ def test_drop_role
53
+ ARBC.drop_role('foo')
54
+ ARBC.drop_role(%w{ foo bar baz })
55
+ ARBC.drop_role(%w{ foo bar baz }, :if_exists => true)
56
+
57
+ assert_equal([
58
+ 'DROP ROLE "foo"',
59
+ 'DROP ROLE "foo", "bar", "baz"',
60
+ 'DROP ROLE IF EXISTS "foo", "bar", "baz"',
61
+ ], statements)
62
+ end
63
+ end
data/test/rules_test.rb CHANGED
@@ -6,10 +6,10 @@ class RulesTests < Test::Unit::TestCase
6
6
  include PostgreSQLExtensionsTestHelper
7
7
 
8
8
  def test_create_rule
9
- Mig.create_rule(
9
+ ARBC.create_rule(
10
10
  :ignore_root, :update, :users, :instead, :nothing, :conditions => 'user_id = 0'
11
11
  )
12
- Mig.create_rule(
12
+ ARBC.create_rule(
13
13
  :ignore_root, :update, :users, :instead, 'SELECT * FROM non_admins', {
14
14
  :force => true,
15
15
  :conditions => 'user_id > 0'
@@ -23,7 +23,7 @@ class RulesTests < Test::Unit::TestCase
23
23
  end
24
24
 
25
25
  def test_drop_rule
26
- Mig.drop_rule(:foo, :bar)
26
+ ARBC.drop_rule(:foo, :bar)
27
27
 
28
28
  assert_equal([
29
29
  "DROP RULE \"foo\" ON \"bar\"",
data/test/test_helper.rb CHANGED
@@ -8,8 +8,6 @@ require 'active_record'
8
8
  require 'test/unit'
9
9
  require File.join(File.dirname(__FILE__), *%w{ .. lib activerecord-postgresql-extensions })
10
10
 
11
- puts "Testing against ActiveRecord #{Gem.loaded_specs['activerecord'].version.to_s}"
12
-
13
11
  ActiveRecord::Base.configurations = {
14
12
  'arunit' => {
15
13
  :adapter => 'postgresql',
@@ -24,6 +22,11 @@ ActiveRecord::Base.establish_connection 'arunit'
24
22
 
25
23
  ARBC = ActiveRecord::Base.connection
26
24
 
25
+ puts "Testing against ActiveRecord #{Gem.loaded_specs['activerecord'].version.to_s}"
26
+ if postgresql_version = ARBC.query('SELECT version()').flatten.to_s
27
+ puts "PostgreSQL info from version(): #{postgresql_version}"
28
+ end
29
+
27
30
  class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
28
31
  def statements
29
32
  @statements ||= []
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-postgresql-extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-14 00:00:00.000000000Z
12
+ date: 2011-10-05 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A whole bunch of extensions the ActiveRecord PostgreSQL adapter.
15
15
  email: code@zoocasa.com
@@ -32,6 +32,7 @@ files:
32
32
  - lib/postgresql_extensions/postgresql_indexes.rb
33
33
  - lib/postgresql_extensions/postgresql_languages.rb
34
34
  - lib/postgresql_extensions/postgresql_permissions.rb
35
+ - lib/postgresql_extensions/postgresql_roles.rb
35
36
  - lib/postgresql_extensions/postgresql_rules.rb
36
37
  - lib/postgresql_extensions/postgresql_schemas.rb
37
38
  - lib/postgresql_extensions/postgresql_sequences.rb
@@ -47,6 +48,7 @@ files:
47
48
  - test/index_test.rb
48
49
  - test/languages_test.rb
49
50
  - test/permissions_test.rb
51
+ - test/roles_test.rb
50
52
  - test/rules_test.rb
51
53
  - test/schemas_test.rb
52
54
  - test/sequences_test.rb
@@ -72,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
74
  version: '0'
73
75
  requirements: []
74
76
  rubyforge_project:
75
- rubygems_version: 1.8.5
77
+ rubygems_version: 1.8.10
76
78
  signing_key:
77
79
  specification_version: 3
78
80
  summary: A whole bunch of extensions the ActiveRecord PostgreSQL adapter.