perimeter 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/Guardfile +31 -0
- data/LICENSE.txt +22 -0
- data/README.md +97 -0
- data/Rakefile +1 -0
- data/lib/perimeter/backend/adapters/abstract.rb +8 -0
- data/lib/perimeter/entity.rb +38 -0
- data/lib/perimeter/repository/adapters/abstract.rb +73 -0
- data/lib/perimeter/repository/error.rb +11 -0
- data/lib/perimeter/repository.rb +117 -0
- data/lib/perimeter/version.rb +3 -0
- data/lib/perimeter.rb +8 -0
- data/perimeter.gemspec +33 -0
- data/spec/lib/perimeter/repository_spec.rb +40 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/models/admin/auto.rb +6 -0
- data/spec/support/models/admin/cars.rb +12 -0
- data/spec/support/models/admin/countries/backend.rb +7 -0
- data/spec/support/models/admin/countries.rb +8 -0
- data/spec/support/models/admin/country.rb +6 -0
- data/spec/support/models/admin/vehicles/backend.rb +7 -0
- data/spec/support/models/cities/backend.rb +8 -0
- data/spec/support/models/cities.rb +8 -0
- data/spec/support/models/city.rb +7 -0
- metadata +234 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7ef4dd2cb1aa452485b1643f29cd3ed48d5b059a
|
4
|
+
data.tar.gz: e6956c254e3832098d8fe242b3c74c3f9b0e6b47
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 70a3f7b3a24b0b710cbc7b7ddbe22ccc07e6d82746a8e33fdd1d6957332e54f385bae794cef063d0b62eeec1bbad17c5ce9c4c751c77b4c4a0cf9a6e406a1538
|
7
|
+
data.tar.gz: 670ea4272c6daf5f5eaf06eb61874dbe794c9c773e0a83e6c83e58b3607a3d01ad0975ed7aa1ece0cdf56b762858d147a88a9123ce0df213d9b7480fe87bee67
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :bundler do
|
5
|
+
watch('Gemfile')
|
6
|
+
# Uncomment next line if your Gemfile contains the `gemspec' command.
|
7
|
+
# watch(/^.+\.gemspec/)
|
8
|
+
end
|
9
|
+
|
10
|
+
guard :rspec, cmd: 'rspec --fail-fast' do
|
11
|
+
watch(%r{^spec/.+_spec\.rb$})
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
13
|
+
watch('spec/spec_helper.rb') { "spec" }
|
14
|
+
|
15
|
+
# Rails example
|
16
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
17
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
18
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
19
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
20
|
+
watch('config/routes.rb') { "spec/routing" }
|
21
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
22
|
+
|
23
|
+
# Capybara features specs
|
24
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
25
|
+
|
26
|
+
# Turnip features and steps
|
27
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
28
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
29
|
+
end
|
30
|
+
|
31
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Bukowskis
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Perimeter
|
2
|
+
|
3
|
+
> **[perimeter](https://en.wikipedia.org/wiki/Perimeter) |pəˈrɪmɪtə| noun** - the continuous line forming the boundary of a closed geometrical figure, alt. the outermost parts or boundary of an area or object: *the perimeter of the garden*.
|
4
|
+
|
5
|
+
As developers we are used to draw strict lines in our code, such as with MVC and ORM. There is much buzz about the repository pattern and this gem is an attempt to introduce an implementation convention for it across our applications.
|
6
|
+
|
7
|
+
Consider this file structure:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
models
|
11
|
+
|- product.rb # Entity
|
12
|
+
|- products.rb # Repository
|
13
|
+
\- products
|
14
|
+
|- backend.rb # Persistence Backend
|
15
|
+
\- calculator.rb # (Here you can put any other related class)
|
16
|
+
```
|
17
|
+
|
18
|
+
## Entity
|
19
|
+
|
20
|
+
This is where your business logic lives. Here you have [Virtus](https://github.com/solnic/virtus) and [ActiveModel Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations.html) at your fingertips.
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
class Product
|
24
|
+
attriute, :name
|
25
|
+
|
26
|
+
validate :name, presence: true
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
## Repository
|
31
|
+
|
32
|
+
This is where you run CRUD operations for your Entities. The repository is the only one who may interact with your persistence backend.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
module Products
|
36
|
+
def self.find(id)
|
37
|
+
# ...
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.destroy(id)
|
41
|
+
# ...
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
Every method of the repository always returns an [Operation](http://rubygems.org/gems/operation) instance. You can, however, use the bang version (e.g. '#find!') so that the operation will raise an Exception if it was not successful. Again, what is a "successful" operation is defined [here](https://github.com/bukowskis/perimeter/blob/master/lib/perimeter/repository/adapters/abstract.rb) and not neccessarily that which you know from ActiveRecord. A few methods are *inspired* by the ActiveRecord API, such as find, destroy,... (see them [here](https://github.com/bukowskis/perimeter/blob/master/lib/perimeter/repository/adapters/abstract.rb)). But not more than that, because the repository is supposed to facilitate different kinds of backends (SQL, ElasticSearch,...).
|
47
|
+
|
48
|
+
The returned Operation instances usually hold metadata, such as Entities, or [Leaflet](http://rubygems.org/gems/leaflet) Collections of Entties. They never expose Backend instances, however.
|
49
|
+
|
50
|
+
By default, perimeter looks for the persistence backend class in [REPOSITORY]::Backend, e.g. `Products::Backend`. If you change the location, you can specify it manually. Likewise, the Entity is derived from the singular name of the repository by default and can be overriden.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
module Products
|
54
|
+
entity_class MyPersonalEntity
|
55
|
+
backend_class SomeWhereElse::MyCustomBackend
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
Because it is so common, there is an [ActiveRecord adapter](https://github.com/bukowskis/perimeter/tree/master/lib/perimeter/repository/adapters) included which you can kickstart your repository with:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
require 'perimeter/repository/adapters/active_record'
|
63
|
+
|
64
|
+
module UserTags
|
65
|
+
include Perimeter::Repository::Adapters::ActiveRecord
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
## Backend
|
70
|
+
|
71
|
+
The persistence backend is tucked away in a directory and may look like the following code. You are not supposed to interact with the backend at all in your code.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
module Products
|
75
|
+
class Backend < ActiveRecord::Base
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
Again there is an adapter which does some initial configuration for you, such as specifying the custom table name of the class. Note that you need to specify the backend classes of associations manually:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
require 'perimeter/backend/adapters/active_record'
|
84
|
+
|
85
|
+
module Products
|
86
|
+
class Backend < ActiveRecord::Base
|
87
|
+
|
88
|
+
include Perimeter::Backend::Adapters::ActiveRecord
|
89
|
+
|
90
|
+
has_many :tags, dependent: :destroy, class_name: '::Tags::Backend', foreign_key: 'tag_id'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
# License
|
96
|
+
|
97
|
+
See `MIT-LICENSE` for details.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# ActiveModel is not defined as gem dependency but we still depend on it (for now).
|
2
|
+
# With this technique we can use Perimeter in Rails 2 applications by backporting activemodel manually into the vendor directory.
|
3
|
+
require 'active_model'
|
4
|
+
|
5
|
+
require 'active_support/core_ext/module'
|
6
|
+
require 'active_support/concern'
|
7
|
+
require 'virtus'
|
8
|
+
|
9
|
+
module Perimeter
|
10
|
+
module Entity
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
include Virtus.model
|
15
|
+
|
16
|
+
extend ActiveModel::Naming
|
17
|
+
include ActiveModel::Conversion
|
18
|
+
include ActiveModel::Validations
|
19
|
+
include ActiveModel::Validations::Callbacks
|
20
|
+
|
21
|
+
attribute :id
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_param
|
25
|
+
return if id.blank?
|
26
|
+
id.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def persisted? # Rails 3+
|
30
|
+
id.present?
|
31
|
+
end
|
32
|
+
|
33
|
+
def new_record? # Rails 2
|
34
|
+
!persisted?
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'trouble'
|
3
|
+
require 'perimeter/repository/error'
|
4
|
+
|
5
|
+
module Perimeter
|
6
|
+
module Repository
|
7
|
+
module Adapters
|
8
|
+
module Abstract
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
# Returns an Operation instance that MUST hold an Entity as object.
|
14
|
+
# Success is defined as "the record could be found", everything else is a failure.
|
15
|
+
# If the record does not exist, there is *no* Trouble. Any other StandardError notifies Trouble.
|
16
|
+
#
|
17
|
+
def find(id)
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns an Operation instance that MUST hold an Entity as object.
|
22
|
+
# Success is defined as "there was no record and now there is one", everything else is a failure.
|
23
|
+
# Validations are run on the Record.
|
24
|
+
#
|
25
|
+
def create(attributes)
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns an Operation instance that MAY hold an Entity as object.
|
30
|
+
# Success is defined as "there was a record and now some/all attributes have been updated", everything else is a failure.
|
31
|
+
# NOTE: Whether validations are run on the Record first is backend specific.
|
32
|
+
#
|
33
|
+
def update(id, attributes)
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns an Operation instance that SHOULD hold the destroyed Entity as object.
|
38
|
+
# Success is defined as "after this operation the record is or already was gone", everything else is a failure.
|
39
|
+
#
|
40
|
+
def destroy(id)
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns an Entity or raises a FindingError.
|
45
|
+
#
|
46
|
+
def find!(id)
|
47
|
+
operation = find id
|
48
|
+
raise ::Perimeter::Repository::FindingError, operation.meta.exception if operation.failure?
|
49
|
+
operation.object
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns an Entity or raises a CreationError.
|
53
|
+
#
|
54
|
+
def create!(id)
|
55
|
+
operation = create id
|
56
|
+
raise ::Perimeter::Repository::CreationError, operation.meta.exception if operation.failure?
|
57
|
+
operation.object
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns true or raises a DestructionError.
|
61
|
+
#
|
62
|
+
def destory!(id)
|
63
|
+
operation = destroy id
|
64
|
+
raise ::Perimeter::Repository::DestructionError, operation.meta.exception if operation.failure?
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Perimeter
|
2
|
+
module Repository
|
3
|
+
|
4
|
+
Error = Class.new StandardError
|
5
|
+
|
6
|
+
FindingError = Class.new ::Perimeter::Repository::Error
|
7
|
+
CreationError = Class.new ::Perimeter::Repository::Error
|
8
|
+
DestructionError = Class.new ::Perimeter::Repository::Error
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'hooks'
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'active_support/core_ext'
|
4
|
+
|
5
|
+
module Perimeter
|
6
|
+
module Repository
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
OperationError = Class.new StandardError
|
10
|
+
|
11
|
+
included do
|
12
|
+
include ::Hooks
|
13
|
+
define_hook :after_conversion
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
# ––––––––––––––––––––––
|
19
|
+
# Class name definitions
|
20
|
+
# ––––––––––––––––––––––
|
21
|
+
|
22
|
+
def backend_class(*args)
|
23
|
+
@backend_class = args.first unless args.empty?
|
24
|
+
@backend_class || default_backend_class
|
25
|
+
end
|
26
|
+
|
27
|
+
def entity_class(*args)
|
28
|
+
@entity_class = args.first unless args.empty?
|
29
|
+
@entity_class || default_entity_class
|
30
|
+
end
|
31
|
+
|
32
|
+
# Convenience Wrapper
|
33
|
+
def backend
|
34
|
+
backend_class
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# –––––––––––––––––––
|
40
|
+
# Default Class names
|
41
|
+
# –––––––––––––––––––
|
42
|
+
|
43
|
+
def default_backend_class
|
44
|
+
backend_class_name = name + '::Backend'
|
45
|
+
backend_class_name.constantize
|
46
|
+
|
47
|
+
rescue NameError => exception
|
48
|
+
if exception.message.to_s == "uninitialized constant #{backend_class_name}"
|
49
|
+
raise NameError, %{Repository "#{name}" expects the Backend "#{backend_class_name}" to be defined.}
|
50
|
+
else
|
51
|
+
raise exception
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_entity_class
|
56
|
+
entity_class_name = name.singularize
|
57
|
+
entity_class_name.constantize
|
58
|
+
|
59
|
+
rescue NameError => exception
|
60
|
+
if exception.message.to_s == "uninitialized constant #{entity_class_name}"
|
61
|
+
raise NameError, %{Repository "#{name}" expects the Entity "#{entity_class_name}" to be defined.}
|
62
|
+
else
|
63
|
+
raise exception
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# ––––––––––
|
68
|
+
# Conversion
|
69
|
+
# ––––––––––
|
70
|
+
|
71
|
+
def attributes_to_record(attributes, options = {})
|
72
|
+
options.symbolize_keys!
|
73
|
+
if id = options[:add_id]
|
74
|
+
attributes[:id] = id
|
75
|
+
end
|
76
|
+
entity = entity_class.new attributes
|
77
|
+
entity_to_record entity
|
78
|
+
end
|
79
|
+
|
80
|
+
def entity_to_record(entity, options = {})
|
81
|
+
options.symbolize_keys!
|
82
|
+
attributes = entity.attributes
|
83
|
+
if options[:strip_id]
|
84
|
+
attributes.delete :id
|
85
|
+
attributes.delete 'id'
|
86
|
+
end
|
87
|
+
backend.new attributes
|
88
|
+
end
|
89
|
+
|
90
|
+
def records_to_entities(records)
|
91
|
+
return [] if records.blank?
|
92
|
+
Array(records).map { |record| record_to_entity(record) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def record_to_entity(record)
|
96
|
+
return if record.blank?
|
97
|
+
|
98
|
+
begin
|
99
|
+
entity = entity_class.new record.attributes
|
100
|
+
rescue ArgumentError => exception
|
101
|
+
if exception.message.to_s == 'wrong number of arguments(1 for 0)'
|
102
|
+
raise ArgumentError, %{The Class "#{entity_class}" appears not to be an Entity, because the initializer does not accept one argument. Did you "include Perimeter::Entity"?}
|
103
|
+
else
|
104
|
+
raise exception
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
record.errors.each { |attribute, message| entity.errors.add attribute, message }
|
109
|
+
|
110
|
+
entity.id = record.id
|
111
|
+
entity
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
data/lib/perimeter.rb
ADDED
data/perimeter.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'perimeter/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'perimeter'
|
7
|
+
spec.version = Perimeter::VERSION
|
8
|
+
spec.authors = %w{ perimeter }
|
9
|
+
spec.description = %q{Repository/Entity pattern conventions.}
|
10
|
+
spec.summary = %q{Repository/Entity pattern conventions.}
|
11
|
+
spec.homepage = 'https://github.com/bukowskis/perimeter'
|
12
|
+
spec.license = 'MIT'
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split($/) - ['.travis.yml']
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = %w{ lib }
|
18
|
+
|
19
|
+
spec.add_dependency 'virtus'
|
20
|
+
spec.add_dependency 'activesupport'
|
21
|
+
spec.add_dependency 'hooks'
|
22
|
+
spec.add_dependency 'operation'
|
23
|
+
spec.add_dependency 'trouble'
|
24
|
+
#spec.add_dependency 'activemodel' # Not compatible with Rails 2, backport it if neccessary
|
25
|
+
|
26
|
+
spec.add_development_dependency 'activemodel'
|
27
|
+
spec.add_development_dependency 'activerecord'
|
28
|
+
spec.add_development_dependency 'sqlite3'
|
29
|
+
|
30
|
+
spec.add_development_dependency 'rspec'
|
31
|
+
spec.add_development_dependency 'guard-rspec'
|
32
|
+
spec.add_development_dependency 'guard-bundler'
|
33
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'cities'
|
4
|
+
require 'admin/countries'
|
5
|
+
require 'admin/cars'
|
6
|
+
|
7
|
+
describe Perimeter::Repository do
|
8
|
+
|
9
|
+
describe '.backend_class' do
|
10
|
+
context 'in the root namespace' do
|
11
|
+
it 'follows the Backend convention' do
|
12
|
+
expect( Cities.backend_class ).to be Cities::Backend
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'in a custom namespace' do
|
17
|
+
it 'follows the Backend convention' do
|
18
|
+
expect( Admin::Countries.backend_class ).to be Admin::Countries::Backend
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with custom backend class definitions' do
|
23
|
+
it 'finds the right classe' do
|
24
|
+
expect( Admin::Cars.backend_class ).to be Admin::Vehicles::Backend
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.backend' do
|
30
|
+
it 'is a (read-only) shortcut to #backend_class' do
|
31
|
+
Cities.stub(:backend_class).and_return 'backend_class says hello'
|
32
|
+
expect( Cities.backend ).to eq 'backend_class says hello'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'refuses to take arguments' do
|
36
|
+
expect { Cities.backend 'something custom' }.to raise_error(ArgumentError)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: perimeter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- perimeter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: virtus
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: hooks
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
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: operation
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: trouble
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activemodel
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activerecord
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sqlite3
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: guard-rspec
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: guard-bundler
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
description: Repository/Entity pattern conventions.
|
168
|
+
email:
|
169
|
+
executables: []
|
170
|
+
extensions: []
|
171
|
+
extra_rdoc_files: []
|
172
|
+
files:
|
173
|
+
- ".gitignore"
|
174
|
+
- ".rspec"
|
175
|
+
- Gemfile
|
176
|
+
- Guardfile
|
177
|
+
- LICENSE.txt
|
178
|
+
- README.md
|
179
|
+
- Rakefile
|
180
|
+
- lib/perimeter.rb
|
181
|
+
- lib/perimeter/backend/adapters/abstract.rb
|
182
|
+
- lib/perimeter/entity.rb
|
183
|
+
- lib/perimeter/repository.rb
|
184
|
+
- lib/perimeter/repository/adapters/abstract.rb
|
185
|
+
- lib/perimeter/repository/error.rb
|
186
|
+
- lib/perimeter/version.rb
|
187
|
+
- perimeter.gemspec
|
188
|
+
- spec/lib/perimeter/repository_spec.rb
|
189
|
+
- spec/spec_helper.rb
|
190
|
+
- spec/support/models/admin/auto.rb
|
191
|
+
- spec/support/models/admin/cars.rb
|
192
|
+
- spec/support/models/admin/countries.rb
|
193
|
+
- spec/support/models/admin/countries/backend.rb
|
194
|
+
- spec/support/models/admin/country.rb
|
195
|
+
- spec/support/models/admin/vehicles/backend.rb
|
196
|
+
- spec/support/models/cities.rb
|
197
|
+
- spec/support/models/cities/backend.rb
|
198
|
+
- spec/support/models/city.rb
|
199
|
+
homepage: https://github.com/bukowskis/perimeter
|
200
|
+
licenses:
|
201
|
+
- MIT
|
202
|
+
metadata: {}
|
203
|
+
post_install_message:
|
204
|
+
rdoc_options: []
|
205
|
+
require_paths:
|
206
|
+
- lib
|
207
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
208
|
+
requirements:
|
209
|
+
- - ">="
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
212
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
|
+
requirements:
|
214
|
+
- - ">="
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: '0'
|
217
|
+
requirements: []
|
218
|
+
rubyforge_project:
|
219
|
+
rubygems_version: 2.2.2
|
220
|
+
signing_key:
|
221
|
+
specification_version: 4
|
222
|
+
summary: Repository/Entity pattern conventions.
|
223
|
+
test_files:
|
224
|
+
- spec/lib/perimeter/repository_spec.rb
|
225
|
+
- spec/spec_helper.rb
|
226
|
+
- spec/support/models/admin/auto.rb
|
227
|
+
- spec/support/models/admin/cars.rb
|
228
|
+
- spec/support/models/admin/countries.rb
|
229
|
+
- spec/support/models/admin/countries/backend.rb
|
230
|
+
- spec/support/models/admin/country.rb
|
231
|
+
- spec/support/models/admin/vehicles/backend.rb
|
232
|
+
- spec/support/models/cities.rb
|
233
|
+
- spec/support/models/cities/backend.rb
|
234
|
+
- spec/support/models/city.rb
|