remote_db 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 897782b1480916843610989aeab9f14c1709090e
4
- data.tar.gz: fbb1d2b9d1d22335a7a72fe7bbd8461131e0c744
3
+ metadata.gz: 667d1745cc359f830957af95e1528e639c7fea55
4
+ data.tar.gz: c2f1d5197e58042fdbcc760c638440dceb0c5c2b
5
5
  SHA512:
6
- metadata.gz: 29bce29570019e4e55d7ecdadf7bffdde33caddab0bbf428ce3c105caa1dc45d5bad6b5f39503ab653a3999a1b9af5f97f3bd9ff0326f5206ae07528ba910e99
7
- data.tar.gz: d6e08127decae61c17ed6bcbac541de4dcb5e461817f2ff3a31fc24da6448613a0626393b0d8c04653b96bfdcb12cf6ad9ae2e7d3c4200b36881628a5906fe5d
6
+ metadata.gz: 0af7222de66fc8405b753d6bbe7269915571e871f012521939fb7d544755dd41fe0012f9dc07552256e59777b99b99f1d21e057f175ff23fa5ed42d73d2d6409
7
+ data.tar.gz: dd258c4a4234fef195cfa4f5250d096c7aa877e3902a75d540ba23f92b309ef0b7ef9d8f0ac8c4e2b7585dbdacaefcb6a5408433b30be12d0abefa0282ba03fb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/CHANGELOG.md CHANGED
@@ -1,7 +1,13 @@
1
- ## v0.0.1
1
+ ## v0.0.5
2
2
 
3
- * Initial release.
3
+ * Models can now be reloaded.
4
+ * In test environment, models can temporarily be switch to read-write mode.
5
+ * Added tests
6
+
7
+ ## v0.0.4
4
8
 
5
- ## v0.0.2
9
+ * Fix bug with AR 4, where AR classes must be named.
6
10
 
7
- * Fix bug with AR 4, where AR class must be named.
11
+ ## v0.0.1
12
+
13
+ * Initial release.
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ remote_db (0.0.4)
5
+ activerecord (>= 3.0)
6
+ activesupport (>= 3.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (4.2.1)
12
+ activesupport (= 4.2.1)
13
+ builder (~> 3.1)
14
+ activerecord (4.2.1)
15
+ activemodel (= 4.2.1)
16
+ activesupport (= 4.2.1)
17
+ arel (~> 6.0)
18
+ activesupport (4.2.1)
19
+ i18n (~> 0.7)
20
+ json (~> 1.7, >= 1.7.7)
21
+ minitest (~> 5.1)
22
+ thread_safe (~> 0.3, >= 0.3.4)
23
+ tzinfo (~> 1.1)
24
+ arel (6.0.0)
25
+ builder (3.2.2)
26
+ diff-lcs (1.2.5)
27
+ i18n (0.7.0)
28
+ json (1.8.2)
29
+ minitest (5.5.1)
30
+ rspec (3.2.0)
31
+ rspec-core (~> 3.2.0)
32
+ rspec-expectations (~> 3.2.0)
33
+ rspec-mocks (~> 3.2.0)
34
+ rspec-core (3.2.0)
35
+ rspec-support (~> 3.2.0)
36
+ rspec-expectations (3.2.0)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.2.0)
39
+ rspec-mocks (3.2.0)
40
+ diff-lcs (>= 1.2.0, < 2.0)
41
+ rspec-support (~> 3.2.0)
42
+ rspec-support (3.2.1)
43
+ sqlite3 (1.3.10)
44
+ thread_safe (0.3.5)
45
+ tzinfo (1.2.2)
46
+ thread_safe (~> 0.1)
47
+
48
+ PLATFORMS
49
+ ruby
50
+
51
+ DEPENDENCIES
52
+ remote_db!
53
+ rspec
54
+ sqlite3
@@ -3,6 +3,8 @@ module RemoteDb
3
3
  module Configurable
4
4
  extend ActiveSupport::Concern
5
5
 
6
+ class ForbiddenActionException < Exception; end
7
+
6
8
  module ClassMethods
7
9
  def configure(config_hash = nil)
8
10
  if config_hash
@@ -21,14 +23,32 @@ module RemoteDb
21
23
  @configuration ||= RemoteDb::Configuration.new
22
24
  end
23
25
 
24
- def load_models!
25
- define_base_record
26
+ def without_readonly
27
+ raise ForbiddenActionException unless configuration.environment == :test
28
+
29
+ load_models!(readonly: false)
30
+ yield
31
+ load_models!(readonly: true)
32
+ end
33
+
34
+ def load_models!(options = { readonly: true })
35
+ clear_old_models
36
+ define_base_record(options)
26
37
  send(:require_models) if respond_to?(:require_models)
27
38
  end
28
39
 
29
40
  private
41
+
42
+ def clear_old_models
43
+ if self.const_defined? 'BaseRecord'
44
+ self.const_get('BaseRecord').clear_all_connections!
45
+ end
46
+ (self.constants - [:VERSION, :ClassMethods, :ForbiddenActionException]).each do |const|
47
+ self.send :remove_const, const
48
+ end
49
+ end
30
50
 
31
- def define_base_record
51
+ def define_base_record(options)
32
52
  module_name = self.name
33
53
  connection_spec = configuration.connection_spec
34
54
  klass = Class.new(ActiveRecord::Base) do
@@ -41,7 +61,9 @@ module RemoteDb
41
61
  establish_connection(connection_spec)
42
62
 
43
63
  # Force model to be ready-only
44
- include Concerns::ReadOnlyModel
64
+ if options[:readonly]
65
+ include Concerns::ReadOnlyModel
66
+ end
45
67
 
46
68
  # Scope which columns are exposed
47
69
  include Concerns::RestrictedColumns
@@ -6,17 +6,17 @@ module RemoteDb
6
6
  class ForbiddenColumnException < Exception; end
7
7
 
8
8
  included do
9
- def read_attribute_with_safety(name)
9
+ def _read_attribute_with_safety(name)
10
10
  original_db_column = self.class.original_columns.include?(name.to_sym)
11
11
  visible_db_column = self.class.visible_columns.include? (name.to_sym)
12
12
 
13
13
  if (original_db_column && visible_db_column) || !original_db_column
14
- read_attribute_without_safety(name)
14
+ _read_attribute_without_safety(name)
15
15
  else
16
16
  raise ForbiddenColumnException, "Column #{name} is not allowed for access."
17
17
  end
18
18
  end
19
- alias_method_chain :read_attribute, :safety
19
+ alias_method_chain :_read_attribute, :safety
20
20
  end
21
21
 
22
22
  module ClassMethods
@@ -6,6 +6,7 @@ module RemoteDb
6
6
  attr_accessor :username
7
7
  attr_accessor :password
8
8
  attr_accessor :database
9
+ attr_accessor :environment
9
10
 
10
11
  def connection_spec
11
12
  {
@@ -1,3 +1,3 @@
1
1
  module RemoteDb
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
data/remote_db.gemspec CHANGED
@@ -16,4 +16,7 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.add_runtime_dependency 'activesupport', '>= 3.0'
18
18
  spec.add_runtime_dependency 'activerecord' , '>= 3.0'
19
+
20
+ spec.add_development_dependency 'rspec'
21
+ spec.add_development_dependency 'sqlite3'
19
22
  end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+ require 'test_db/test_db'
3
+
4
+ describe RemoteDb do
5
+ let(:connection_spec) do
6
+ {
7
+ 'adapter' => 'sqlite3',
8
+ 'database' => 'test_database.sqlite3',
9
+ 'pool' => 250,
10
+ 'username' => 'root',
11
+ 'password' => 'password',
12
+ 'host' => '127.0.0.1'
13
+ }
14
+ end
15
+
16
+ describe 'configuring the gem' do
17
+ it 'should allow to set and read database settings' do
18
+ expect(TestDb.configuration.adapter).to be_nil
19
+ expect(TestDb.configuration.pool).to be_nil
20
+ expect(TestDb.configuration.host).to be_nil
21
+ expect(TestDb.configuration.username).to be_nil
22
+ expect(TestDb.configuration.password).to be_nil
23
+ expect(TestDb.configuration.database).to be_nil
24
+
25
+ TestDb.configure(connection_spec)
26
+
27
+ expect(TestDb.configuration.adapter).to eq(connection_spec['adapter'])
28
+ expect(TestDb.configuration.pool).to eq(connection_spec['pool'])
29
+ expect(TestDb.configuration.host).to eq(connection_spec['host'])
30
+ expect(TestDb.configuration.username).to eq(connection_spec['username'])
31
+ expect(TestDb.configuration.password).to eq(connection_spec['password'])
32
+ expect(TestDb.configuration.database).to eq(connection_spec['database'])
33
+ end
34
+
35
+ it 'should allow retrieve connection specifications' do
36
+ TestDb.configure(connection_spec)
37
+ expect(TestDb.configuration.connection_spec).to eq({
38
+ adapter: connection_spec['adapter'],
39
+ pool: connection_spec['pool'],
40
+ host: connection_spec['host'],
41
+ username: connection_spec['username'],
42
+ password: connection_spec['password'],
43
+ database: connection_spec['database']
44
+ })
45
+ end
46
+ end
47
+
48
+ describe 'Loading models when the database settings are not valid' do
49
+ before do
50
+ TestDb.configure({adapter: nil, host: nil, username: nil, password: nil, database: nil})
51
+ end
52
+
53
+ it 'should throw an exception, and not load models' do
54
+ expect {
55
+ TestDb.load_models!
56
+ }.to raise_error
57
+ end
58
+ end
59
+
60
+ describe 'Loading models when the database settings are valid' do
61
+ before do
62
+ TestDb.configure(connection_spec)
63
+ TestDb.prepare_test_db!
64
+ end
65
+
66
+ after do
67
+ TestDb.cleanup_test_db!
68
+ end
69
+
70
+ it 'should not throw any exceptions, and load models' do
71
+ expect(TestDb.constants.include? :Person).to be_falsey
72
+ TestDb.load_models!
73
+ expect(TestDb.constants.include? :Person).to be_truthy
74
+ end
75
+
76
+ context 'when the models are loaded' do
77
+ before do
78
+ TestDb.load_models!
79
+ end
80
+
81
+ it 'should allow querying models' do
82
+ expect(TestDb::Person.count).to eq(1)
83
+ person = TestDb::Person.first
84
+
85
+ expect(person.id).to eq(1)
86
+ expect(person.first_name).to eq('John')
87
+ end
88
+
89
+ it 'should not allow creating or updating new models' do
90
+ person = TestDb::Person.first
91
+ person.first_name = 'Bob'
92
+
93
+ expect {
94
+ person.save
95
+ }.to raise_error(ActiveRecord::ReadOnlyRecord)
96
+
97
+ expect {
98
+ person.destroy
99
+ }.to raise_error(ActiveRecord::ReadOnlyRecord)
100
+
101
+ expect {
102
+ TestDb::Person.create(first_name: 'Bob')
103
+ }.to raise_error(ActiveRecord::ReadOnlyRecord)
104
+
105
+ expect {
106
+ TestDb::Person.destroy_all
107
+ }.to raise_error(ActiveRecord::ReadOnlyRecord)
108
+ end
109
+
110
+ it 'should not allow accessing hidden columns' do
111
+ person = TestDb::Person.first
112
+ expect {
113
+ puts person.last_name
114
+ }.to raise_error(RemoteDb::Concerns::RestrictedColumns::ForbiddenColumnException)
115
+
116
+ expect {
117
+ puts person[:last_name]
118
+ }.to raise_error(RemoteDb::Concerns::RestrictedColumns::ForbiddenColumnException)
119
+ end
120
+
121
+ context '#without_readonly' do
122
+ context 'when not specifying a environment' do
123
+ it 'should raise an error' do
124
+ expect {
125
+ TestDb.without_readonly do
126
+ TestDb::Person.create(first_name: 'Bob')
127
+ end
128
+ }.to raise_error(RemoteDb::Concerns::Configurable::ForbiddenActionException)
129
+ end
130
+ end
131
+
132
+ context 'when not specifying a test environment' do
133
+ before do
134
+ TestDb.configuration.environment = :development
135
+ end
136
+
137
+ it 'should raise an error' do
138
+ expect {
139
+ TestDb.without_readonly do
140
+ TestDb::Person.create(first_name: 'Bob')
141
+ end
142
+ }.to raise_error(RemoteDb::Concerns::Configurable::ForbiddenActionException)
143
+ end
144
+ end
145
+
146
+ context 'when using a test environment' do
147
+ before do
148
+ TestDb.configuration.environment = :test
149
+ end
150
+
151
+ it 'should not raise an error' do
152
+ expect(TestDb::Person.count).to eq(1)
153
+ TestDb.without_readonly do
154
+ TestDb::Person.create(first_name: 'Bob')
155
+ end
156
+ expect(TestDb::Person.count).to eq(2)
157
+ expect(TestDb::Person.first.first_name).to eq('John')
158
+ expect(TestDb::Person.last.first_name).to eq('Bob')
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,91 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # The settings below are suggested to provide a good initial experience
44
+ # with RSpec, but feel free to customize to your heart's content.
45
+ =begin
46
+ # These two settings work together to allow you to limit a spec run
47
+ # to individual examples or groups you care about by tagging them with
48
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
+ # get run.
50
+ config.filter_run :focus
51
+ config.run_all_when_everything_filtered = true
52
+
53
+ # Limits the available syntax to the non-monkey patched syntax that is
54
+ # recommended. For more details, see:
55
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
56
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
57
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
58
+ config.disable_monkey_patching!
59
+
60
+ # This setting enables warnings. It's recommended, but in some cases may
61
+ # be too noisy due to issues in dependencies.
62
+ config.warnings = true
63
+
64
+ # Many RSpec users commonly either run the entire suite or an individual
65
+ # file, and it's useful to allow more verbose output when running an
66
+ # individual spec file.
67
+ if config.files_to_run.one?
68
+ # Use the documentation formatter for detailed output,
69
+ # unless a formatter has already been configured
70
+ # (e.g. via a command-line flag).
71
+ config.default_formatter = 'doc'
72
+ end
73
+
74
+ # Print the 10 slowest examples and example groups at the
75
+ # end of the spec run, to help surface which specs are running
76
+ # particularly slow.
77
+ config.profile_examples = 10
78
+
79
+ # Run specs in random order to surface order dependencies. If you find an
80
+ # order dependency and want to debug it, you can fix the order by providing
81
+ # the seed, which is printed after each run.
82
+ # --seed 1234
83
+ config.order = :random
84
+
85
+ # Seed global randomization in this process using the `--seed` CLI option.
86
+ # Setting this allows you to use `--seed` to deterministically reproduce
87
+ # test failures related to randomization by passing the same `--seed` value
88
+ # as the one that triggered the failure.
89
+ Kernel.srand config.seed
90
+ =end
91
+ end
@@ -0,0 +1,6 @@
1
+ module TestDb
2
+ class Person < BaseRecord
3
+ self.table_name = 'persons'
4
+ self.table_columns = [:id, :first_name]
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ require 'sqlite3'
2
+
3
+ require 'remote_db'
4
+
5
+ module TestDb
6
+ include RemoteDb::Concerns::Configurable
7
+
8
+ def self.require_models
9
+ load File.join([File.dirname(__FILE__), 'person.rb'])
10
+ end
11
+
12
+ def self.prepare_test_db!
13
+ db_file = configuration.database
14
+ db = SQLite3::Database.new db_file
15
+ db.execute 'CREATE TABLE IF NOT EXISTS persons (id INTEGER PRIMARY KEY, first_name TEXT, last_name TEXT)'
16
+ db.execute "INSERT INTO persons(id, first_name, last_name) VALUES (1, 'John', 'Smith')"
17
+ end
18
+
19
+ def self.cleanup_test_db!
20
+ db_file = configuration.database
21
+ if db_file && File.exists?(db_file)
22
+ File.unlink(db_file)
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remote_db
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Omar Skalli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-26 00:00:00.000000000 Z
11
+ date: 2015-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  description: ''
42
70
  email:
43
71
  - omar@zenpayroll.com
@@ -46,8 +74,10 @@ extensions: []
46
74
  extra_rdoc_files: []
47
75
  files:
48
76
  - ".gitignore"
77
+ - ".rspec"
49
78
  - CHANGELOG.md
50
79
  - Gemfile
80
+ - Gemfile.lock
51
81
  - README.md
52
82
  - lib/remote_db.rb
53
83
  - lib/remote_db/concerns/configurable.rb
@@ -56,6 +86,10 @@ files:
56
86
  - lib/remote_db/configuration.rb
57
87
  - lib/remote_db/version.rb
58
88
  - remote_db.gemspec
89
+ - spec/concerns/configurable_spec.rb
90
+ - spec/spec_helper.rb
91
+ - spec/test_db/person.rb
92
+ - spec/test_db/test_db.rb
59
93
  homepage: https://github.com/ZenPayroll/remote_db
60
94
  licenses: []
61
95
  metadata: {}