required_scopes 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +29 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +277 -0
- data/Rakefile +6 -0
- data/lib/required_scopes.rb +17 -0
- data/lib/required_scopes/active_record/base.rb +235 -0
- data/lib/required_scopes/active_record/relation.rb +121 -0
- data/lib/required_scopes/active_record/version_compatibility.rb +157 -0
- data/lib/required_scopes/errors.rb +48 -0
- data/lib/required_scopes/version.rb +3 -0
- data/required_scopes.gemspec +56 -0
- data/spec/required_scopes/helpers/database_helper.rb +174 -0
- data/spec/required_scopes/helpers/system_helpers.rb +98 -0
- data/spec/required_scopes/system/associations_system_spec.rb +150 -0
- data/spec/required_scopes/system/base_scope_system_spec.rb +71 -0
- data/spec/required_scopes/system/basic_system_spec.rb +121 -0
- data/spec/required_scopes/system/inheritance_system_spec.rb +67 -0
- data/spec/required_scopes/system/methods_system_spec.rb +312 -0
- data/spec/required_scopes/system/static_scopes_system_spec.rb +31 -0
- metadata +141 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'required_scopes/errors'
|
3
|
+
require 'required_scopes/active_record/version_compatibility'
|
4
|
+
|
5
|
+
# This file simply adds a few small methods to ::ActiveRecord::Relation to allow tracking which scope categories have
|
6
|
+
# been satisfied on a relation.
|
7
|
+
::ActiveRecord::Relation.class_eval do
|
8
|
+
# Call this method inline, exactly as you would any class-defined scope, to indicate that a particular category
|
9
|
+
# or categories have been satisfied. It's really intended for use in a class method, but both of these will
|
10
|
+
# work:
|
11
|
+
#
|
12
|
+
# class User < ActiveRecord::Base
|
13
|
+
# must_scope_by :client, :deleted
|
14
|
+
#
|
15
|
+
# class << self
|
16
|
+
# def active_for_client_named(client_name)
|
17
|
+
# client_id = CLIENT_MAP[client_name]
|
18
|
+
# where(:client_id => client_id).where(:deleted => false).scope_categories_satisfied(:client)
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# User.active_for_client_named('foo').first
|
24
|
+
# User.where(:client_id => client_id).where(:deleted => false).scope_categories_satisfied(:client, :deleted).first
|
25
|
+
def scope_categories_satisfied(*categories, &block)
|
26
|
+
categories = categories.flatten
|
27
|
+
|
28
|
+
new_scope = if categories.length == 0
|
29
|
+
self
|
30
|
+
else
|
31
|
+
out = clone
|
32
|
+
out.scope_categories_satisfied!(categories)
|
33
|
+
out
|
34
|
+
end
|
35
|
+
|
36
|
+
if block
|
37
|
+
new_scope.scoping(&block)
|
38
|
+
else
|
39
|
+
new_scope
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Alias for #scope_categories_satisfied.
|
44
|
+
def scope_category_satisfied(category, &block)
|
45
|
+
scope_categories_satisfied(category, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Tells this Relation that one or more categories have been satisfied.
|
49
|
+
def scope_categories_satisfied!(categories)
|
50
|
+
categories = categories.flatten
|
51
|
+
|
52
|
+
@satisfied_scope_categories ||= [ ]
|
53
|
+
@satisfied_scope_categories |= categories
|
54
|
+
end
|
55
|
+
|
56
|
+
# Tells this Relation that _all_ categories have been satisfied.
|
57
|
+
def all_scope_categories_satisfied!
|
58
|
+
scope_categories_satisfied!(required_scope_categories)
|
59
|
+
end
|
60
|
+
|
61
|
+
def all_scope_categories_satisfied(&block)
|
62
|
+
scope_categories_satisfied(required_scope_categories, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the set of scope categories that have been satisfied.
|
66
|
+
def satisfied_scope_categories
|
67
|
+
@satisfied_scope_categories ||= [ ]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Overrides #merge to merge the information about which scope categories have been satisfied, too.
|
71
|
+
def merge(other_relation)
|
72
|
+
super.scope_categories_satisfied(satisfied_scope_categories | other_relation.satisfied_scope_categories)
|
73
|
+
end
|
74
|
+
|
75
|
+
delegate :required_scope_categories, :to => :klass
|
76
|
+
|
77
|
+
|
78
|
+
private
|
79
|
+
# Raises an exception if there is at least one required scope category that has not yet been satisfied.
|
80
|
+
# +triggering_method+ is the name of the method called that triggered this check; we include this in the error
|
81
|
+
# we raise.
|
82
|
+
def ensure_categories_satisfied!(triggering_method)
|
83
|
+
required_categories = required_scope_categories
|
84
|
+
missing_categories = required_categories - satisfied_scope_categories
|
85
|
+
|
86
|
+
if missing_categories.length > 0
|
87
|
+
# We return a special exception for the category +:base+, because we want to give a simpler, cleaner error
|
88
|
+
# message for users who are just using the #base_scope_required! syntactic sugar instead of the full categories
|
89
|
+
# system.
|
90
|
+
# $stderr.puts "RAISING AT: #{caller.join("\n ")}"
|
91
|
+
if missing_categories == [ :base ]
|
92
|
+
raise RequiredScopes::Errors::BaseScopeNotSatisfiedError.new(klass, self, triggering_method)
|
93
|
+
else
|
94
|
+
raise RequiredScopes::Errors::RequiredScopeCategoriesNotSatisfiedError.new(
|
95
|
+
klass, self, triggering_method, required_categories, satisfied_scope_categories)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Override certain key methods in ActiveRecord::Relation to make sure they check for category satisfaction before
|
101
|
+
# running.
|
102
|
+
[ :exec_queries, :perform_calculation, :update_all, :delete_all, :exists?, :pluck ].each do |method_name|
|
103
|
+
method_base_name = method_name
|
104
|
+
method_suffix = ""
|
105
|
+
|
106
|
+
if method_base_name.to_s =~ /^(.*?)([\?\!])$/
|
107
|
+
method_base_name = $1
|
108
|
+
method_suffix = $2
|
109
|
+
end
|
110
|
+
|
111
|
+
with_name = "#{method_base_name}_with_scope_categories_check#{method_suffix}"
|
112
|
+
without_name = "#{method_base_name}_without_scope_categories_check#{method_suffix}"
|
113
|
+
|
114
|
+
define_method(with_name) do |*args, &block|
|
115
|
+
ensure_categories_satisfied!(method_name) unless RequiredScopes::ActiveRecord::VersionCompatibility.is_association_relation?(self)
|
116
|
+
send(without_name, *args, &block)
|
117
|
+
end
|
118
|
+
|
119
|
+
alias_method_chain method_name, :scope_categories_check
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module RequiredScopes
|
2
|
+
module ActiveRecord
|
3
|
+
module VersionCompatibility
|
4
|
+
class << self
|
5
|
+
delegate :is_association_relation?, :supports_references_method?, :apply_version_specific_fixes!,
|
6
|
+
:supports_find_by?, :relation_method_for_ignoring_scopes, :supports_load?, :supports_take?,
|
7
|
+
:supports_ids?, :supports_spawn?, :supports_bang_methods?, :supports_references?,
|
8
|
+
:supports_unscope?, :supports_none?, :supports_distinct?, :to => :impl
|
9
|
+
|
10
|
+
private
|
11
|
+
def impl
|
12
|
+
@impl ||= if ::ActiveRecord::VERSION::MAJOR == 4
|
13
|
+
ActiveRecord4.new
|
14
|
+
elsif ::ActiveRecord::VERSION::MAJOR == 3
|
15
|
+
ActiveRecord3.new
|
16
|
+
else
|
17
|
+
raise "RequiredScopes does not support ActiveRecord version #{ActiveRecord::VERSION::STRING} currently."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class ActiveRecord4
|
23
|
+
def is_association_relation?(relation)
|
24
|
+
relation.kind_of?(::ActiveRecord::AssociationRelation)
|
25
|
+
end
|
26
|
+
|
27
|
+
def supports_references_method?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def apply_version_specific_fixes!
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def supports_find_by?
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def supports_load?
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def supports_take?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def supports_ids?
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def supports_spawn?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def supports_bang_methods?
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
def supports_references?
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def supports_unscope?
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def supports_none?
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
def supports_distinct?
|
72
|
+
true
|
73
|
+
end
|
74
|
+
|
75
|
+
def relation_method_for_ignoring_scopes
|
76
|
+
:all
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class ActiveRecord3
|
81
|
+
def is_association_relation?(relation)
|
82
|
+
false
|
83
|
+
end
|
84
|
+
|
85
|
+
def supports_references_method?
|
86
|
+
false
|
87
|
+
end
|
88
|
+
|
89
|
+
def apply_version_specific_fixes!
|
90
|
+
::ActiveRecord::Associations::Association.class_eval do
|
91
|
+
def target_scope_with_required_scopes_removed
|
92
|
+
out = target_scope_without_required_scopes_removed
|
93
|
+
out.all_scope_categories_satisfied!
|
94
|
+
out
|
95
|
+
end
|
96
|
+
|
97
|
+
alias_method_chain :target_scope, :required_scopes_removed
|
98
|
+
end
|
99
|
+
|
100
|
+
::ActiveRecord::Base.class_eval do
|
101
|
+
def destroy_with_required_scopes_removed
|
102
|
+
self.class.all_scope_categories_satisfied do
|
103
|
+
destroy_without_required_scopes_removed
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
alias_method_chain :destroy, :required_scopes_removed
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def supports_find_by?
|
112
|
+
false
|
113
|
+
end
|
114
|
+
|
115
|
+
def supports_load?
|
116
|
+
false
|
117
|
+
end
|
118
|
+
|
119
|
+
def supports_take?
|
120
|
+
false
|
121
|
+
end
|
122
|
+
|
123
|
+
def supports_ids?
|
124
|
+
false
|
125
|
+
end
|
126
|
+
|
127
|
+
def supports_spawn?
|
128
|
+
false
|
129
|
+
end
|
130
|
+
|
131
|
+
def supports_bang_methods?
|
132
|
+
false
|
133
|
+
end
|
134
|
+
|
135
|
+
def supports_references?
|
136
|
+
false
|
137
|
+
end
|
138
|
+
|
139
|
+
def supports_unscope?
|
140
|
+
false
|
141
|
+
end
|
142
|
+
|
143
|
+
def supports_none?
|
144
|
+
false
|
145
|
+
end
|
146
|
+
|
147
|
+
def supports_distinct?
|
148
|
+
false
|
149
|
+
end
|
150
|
+
|
151
|
+
def relation_method_for_ignoring_scopes
|
152
|
+
:relation
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module RequiredScopes
|
2
|
+
module Errors
|
3
|
+
# The parent of all errors raised by RequiredScopes.
|
4
|
+
class Base < StandardError; end
|
5
|
+
|
6
|
+
# Raised if you try to execute an operation on a model or relation without having satisfied one or more
|
7
|
+
# scopes.
|
8
|
+
class RequiredScopeCategoriesNotSatisfiedError < Base
|
9
|
+
attr_reader :model_class, :current_relation, :triggering_method, :required_categories, :satisfied_categories, :missing_categories
|
10
|
+
|
11
|
+
def initialize(model_class, current_relation, triggering_method, required_categories, satisfied_categories)
|
12
|
+
@model_class = model_class
|
13
|
+
@current_relation = current_relation
|
14
|
+
@triggering_method = triggering_method
|
15
|
+
@required_categories = required_categories
|
16
|
+
@satisfied_categories = satisfied_categories
|
17
|
+
@missing_categories = @required_categories - @satisfied_categories
|
18
|
+
|
19
|
+
super(build_message)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def build_message
|
24
|
+
%{Model #{model_class.name} requires that you apply scope(s) satisfying the following
|
25
|
+
categories before you use it: #{missing_categories.sort_by(&:to_s).join(", ")}.
|
26
|
+
|
27
|
+
Satisfy these categories by including scopes in your query that are tagged with
|
28
|
+
:satisfies => <category name>, for each of the categories.}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Raised if you try to execute an operation on a model or relation without having satisfied the base scope.
|
33
|
+
# (We use this instead of RequiredScopeCategoriesNotSatisfiedError, above, simply to make the error message
|
34
|
+
# simpler and more comprehensible to users who only are using the "base scope" syntactic sugar.)
|
35
|
+
class BaseScopeNotSatisfiedError < RequiredScopeCategoriesNotSatisfiedError
|
36
|
+
def initialize(model_class, current_relation, triggering_method)
|
37
|
+
super(model_class, current_relation, triggering_method, [ :base ], [ ])
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def build_message
|
42
|
+
%{Model #{model_class.name} requires specification of a base scope before using it in a query
|
43
|
+
or other such operation. (Base scopes are those declared with #base_scope rather than just #scope,
|
44
|
+
or class methods that include #base_scope_satisfied.)}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'required_scopes/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "required_scopes"
|
8
|
+
s.version = RequiredScopes::VERSION
|
9
|
+
s.authors = ["Andrew Geweke"]
|
10
|
+
s.email = ["andrew@geweke.org"]
|
11
|
+
s.description = %q{Don't let developers forget about critical scopes for queries.}
|
12
|
+
s.summary = %q{Don't let developers forget about critical scopes for queries.}
|
13
|
+
s.homepage = "https://github.com/ageweke/required_scopes"
|
14
|
+
s.license = "MIT"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split($/)
|
17
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
s.add_development_dependency "rake"
|
23
|
+
s.add_development_dependency "rspec", "~> 2.14"
|
24
|
+
|
25
|
+
if (RUBY_VERSION =~ /^1\.9\./ || RUBY_VERSION =~ /^2\./) && ((! defined?(RUBY_ENGINE)) || (RUBY_ENGINE != 'jruby'))
|
26
|
+
s.add_development_dependency "pry"
|
27
|
+
s.add_development_dependency "pry-debugger"
|
28
|
+
s.add_development_dependency "pry-stack_explorer"
|
29
|
+
end
|
30
|
+
|
31
|
+
ar_version = ENV['REQUIRED_SCOPES_AR_TEST_VERSION']
|
32
|
+
ar_version = ar_version.strip if ar_version
|
33
|
+
|
34
|
+
version_spec = case ar_version
|
35
|
+
when nil then [ ">= 3.0", "<= 4.99.99" ]
|
36
|
+
when 'master' then nil
|
37
|
+
else [ "=#{ar_version}" ]
|
38
|
+
end
|
39
|
+
|
40
|
+
if version_spec
|
41
|
+
s.add_dependency("activerecord", *version_spec)
|
42
|
+
end
|
43
|
+
|
44
|
+
s.add_dependency "activesupport", ">= 3.0", "<= 4.99.99"
|
45
|
+
|
46
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'spec', 'required_scopes', 'helpers', 'database_helper'))
|
47
|
+
database_gem_name = RequiredScopes::Helpers::DatabaseHelper.maybe_database_gem_name
|
48
|
+
|
49
|
+
# Ugh. Later versions of the 'mysql2' gem are incompatible with AR 3.0.x; so, here, we explicitly trap that case
|
50
|
+
# and use an earlier version of that Gem.
|
51
|
+
if database_gem_name && database_gem_name == 'mysql2' && ar_version && ar_version =~ /^3\.0\./
|
52
|
+
s.add_development_dependency('mysql2', '~> 0.2.0')
|
53
|
+
else
|
54
|
+
s.add_development_dependency(database_gem_name)
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
module RequiredScopes
|
2
|
+
module Helpers
|
3
|
+
class DatabaseHelper
|
4
|
+
class InvalidDatabaseConfigurationError < StandardError; end
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def maybe_database_gem_name
|
8
|
+
begin
|
9
|
+
dh = new
|
10
|
+
dh.database_gem_name
|
11
|
+
rescue InvalidDatabaseConfigurationError => idce
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
config # make sure we raise on instantiation if configuration is invalid
|
19
|
+
end
|
20
|
+
|
21
|
+
def database_type
|
22
|
+
case database_gem_name
|
23
|
+
when /mysql/i then :mysql
|
24
|
+
when /sqlite/i then :sqlite
|
25
|
+
when /pg/i, /postgres/i then :postgres
|
26
|
+
else raise "Unknown database type for Gem name: #{database_gem_name.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup_activerecord!
|
31
|
+
require 'active_record'
|
32
|
+
require config[:require]
|
33
|
+
::ActiveRecord::Base.establish_connection(config[:config])
|
34
|
+
|
35
|
+
require 'logger'
|
36
|
+
require 'stringio'
|
37
|
+
@logs = StringIO.new
|
38
|
+
::ActiveRecord::Base.logger = Logger.new(@logs)
|
39
|
+
|
40
|
+
if config[:config][:adapter] == 'sqlite3'
|
41
|
+
sqlite_version = ::ActiveRecord::Base.connection.send(:sqlite_version).instance_variable_get("@version").inspect rescue "unknown"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def table_name(name)
|
46
|
+
"rec_spec_#{name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def database_gem_name
|
50
|
+
config[:database_gem_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def config
|
55
|
+
config_from_config_file || travis_ci_config_from_environment || invalid_config_file!
|
56
|
+
end
|
57
|
+
|
58
|
+
def config_from_config_file
|
59
|
+
return nil unless File.exist?(config_file_path)
|
60
|
+
require config_file_path
|
61
|
+
|
62
|
+
return nil unless defined?(REQUIRED_SCOPES_SPEC_DATABASE_CONFIG)
|
63
|
+
return nil unless REQUIRED_SCOPES_SPEC_DATABASE_CONFIG.kind_of?(Hash)
|
64
|
+
|
65
|
+
return nil unless REQUIRED_SCOPES_SPEC_DATABASE_CONFIG[:require]
|
66
|
+
return nil unless REQUIRED_SCOPES_SPEC_DATABASE_CONFIG[:database_gem_name]
|
67
|
+
|
68
|
+
return nil unless REQUIRED_SCOPES_SPEC_DATABASE_CONFIG
|
69
|
+
REQUIRED_SCOPES_SPEC_DATABASE_CONFIG
|
70
|
+
end
|
71
|
+
|
72
|
+
def travis_ci_config_from_environment
|
73
|
+
dbtype = (ENV['REQUIRED_SCOPES_TRAVIS_CI_DATABASE_TYPE'] || '').strip.downcase
|
74
|
+
is_jruby = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
75
|
+
|
76
|
+
if is_jruby
|
77
|
+
case dbtype
|
78
|
+
when 'mysql'
|
79
|
+
{
|
80
|
+
:require => 'activerecord-jdbcmysql-adapter',
|
81
|
+
:database_gem_name => 'activerecord-jdbcmysql-adapter',
|
82
|
+
:config => {
|
83
|
+
:adapter => 'jdbcmysql',
|
84
|
+
:database => 'myapp_test',
|
85
|
+
:username => 'travis',
|
86
|
+
:encoding => 'utf8'
|
87
|
+
}
|
88
|
+
}
|
89
|
+
when 'postgres', 'postgresql'
|
90
|
+
{
|
91
|
+
:require => 'activerecord-jdbcpostgresql-adapter',
|
92
|
+
:database_gem_name => 'activerecord-jdbcpostgresql-adapter',
|
93
|
+
:config => {
|
94
|
+
:adapter => 'jdbcpostgresql',
|
95
|
+
:database => 'myapp_test',
|
96
|
+
:username => 'postgres'
|
97
|
+
}
|
98
|
+
}
|
99
|
+
when 'sqlite'
|
100
|
+
{
|
101
|
+
:require => 'activerecord-jdbcsqlite3-adapter',
|
102
|
+
:database_gem_name => 'activerecord-jdbcsqlite3-adapter',
|
103
|
+
:config => {
|
104
|
+
:adapter => 'jdbcsqlite3',
|
105
|
+
:database => ':memory:'
|
106
|
+
}
|
107
|
+
}
|
108
|
+
when '', nil then nil
|
109
|
+
else
|
110
|
+
raise "Unknown Travis CI database type: #{dbtype.inspect}"
|
111
|
+
end
|
112
|
+
else
|
113
|
+
case dbtype
|
114
|
+
when 'postgres', 'postgresql'
|
115
|
+
{
|
116
|
+
:require => 'pg',
|
117
|
+
:database_gem_name => 'pg',
|
118
|
+
:config => {
|
119
|
+
:adapter => 'postgresql',
|
120
|
+
:database => 'myapp_test',
|
121
|
+
:username => 'postgres',
|
122
|
+
:min_messages => 'WARNING'
|
123
|
+
}
|
124
|
+
}
|
125
|
+
when 'mysql'
|
126
|
+
{
|
127
|
+
:require => 'mysql2',
|
128
|
+
:database_gem_name => 'mysql2',
|
129
|
+
:config => {
|
130
|
+
:adapter => 'mysql2',
|
131
|
+
:database => 'myapp_test',
|
132
|
+
:username => 'travis',
|
133
|
+
:encoding => 'utf8'
|
134
|
+
}
|
135
|
+
}
|
136
|
+
when 'sqlite'
|
137
|
+
{
|
138
|
+
:require => 'sqlite3',
|
139
|
+
:database_gem_name => 'sqlite3',
|
140
|
+
:config => {
|
141
|
+
:adapter => 'sqlite3',
|
142
|
+
:database => ':memory:',
|
143
|
+
:timeout => 500
|
144
|
+
}
|
145
|
+
}
|
146
|
+
when '', nil then nil
|
147
|
+
else
|
148
|
+
raise "Unknown Travis CI database type: #{dbtype.inspect}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def config_file_path
|
154
|
+
@config_file_path ||= File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_database_config.rb'))
|
155
|
+
end
|
156
|
+
|
157
|
+
def invalid_config_file!
|
158
|
+
raise Errno::ENOENT, %{In order to run specs for required_scopes, you need to create a file at:
|
159
|
+
|
160
|
+
#{config_file_path}
|
161
|
+
|
162
|
+
...that defines a top-level REQUIRED_SCOPES_SPEC_DATABASE_CONFIG hash, with members:
|
163
|
+
|
164
|
+
:require => 'name_of_adapter_to_require',
|
165
|
+
:database_gem_name => 'name_of_gem_for_adapter',
|
166
|
+
:config => { ...whatever ActiveRecord::Base.establish_connection should be passed... }
|
167
|
+
|
168
|
+
Alternatively, if you're running under Travis CI, you can set the environment variable
|
169
|
+
REQUIRED_SCOPES_TRAVIS_CI_DATABASE_TYPE to 'postgres', 'mysql', or 'sqlite', and it will
|
170
|
+
use the correct configuration for testing on Travis CI.}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|