lotus-model 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +159 -0
- data/{LICENSE.txt → LICENSE.md} +0 -0
- data/README.md +29 -28
- data/lib/lotus/entity.rb +6 -13
- data/lib/lotus/model/adapters/memory/query.rb +9 -9
- data/lib/lotus/model/adapters/sql/query.rb +9 -9
- data/lib/lotus/model/mapper.rb +3 -3
- data/lib/lotus/model/mapping/coercer.rb +4 -4
- data/lib/lotus/model/mapping/coercions.rb +162 -0
- data/lib/lotus/model/mapping/collection.rb +2 -2
- data/lib/lotus/model/version.rb +1 -1
- data/lib/lotus/repository.rb +9 -9
- data/lotus-model.gemspec +3 -3
- metadata +10 -47
- data/.gitignore +0 -18
- data/.travis.yml +0 -6
- data/.yardopts +0 -5
- data/Gemfile +0 -16
- data/Rakefile +0 -17
- data/test/entity_test.rb +0 -126
- data/test/fixtures.rb +0 -81
- data/test/model/adapters/abstract_test.rb +0 -75
- data/test/model/adapters/implementation_test.rb +0 -22
- data/test/model/adapters/memory/query_test.rb +0 -91
- data/test/model/adapters/memory_adapter_test.rb +0 -1044
- data/test/model/adapters/sql/query_test.rb +0 -121
- data/test/model/adapters/sql_adapter_test.rb +0 -1078
- data/test/model/mapper_test.rb +0 -94
- data/test/model/mapping/coercer_test.rb +0 -27
- data/test/model/mapping/collection_test.rb +0 -82
- data/test/repository_test.rb +0 -283
- data/test/test_helper.rb +0 -30
- data/test/version_test.rb +0 -7
data/.gitignore
DELETED
data/.travis.yml
DELETED
data/.yardopts
DELETED
data/Gemfile
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
gemspec
|
3
|
-
|
4
|
-
if !ENV['TRAVIS']
|
5
|
-
gem 'byebug', require: false, platforms: :ruby if RUBY_VERSION == '2.1.1'
|
6
|
-
gem 'yard', require: false
|
7
|
-
# gem 'lotus-utils', require: false, github: 'lotus/utils'
|
8
|
-
else
|
9
|
-
# gem 'lotus-utils', '~> 0.1', '> 0.1.0'
|
10
|
-
end
|
11
|
-
|
12
|
-
gem 'lotus-utils', require: false, github: 'lotus/utils'
|
13
|
-
|
14
|
-
gem 'sqlite3', require: false
|
15
|
-
gem 'simplecov', require: false
|
16
|
-
gem 'coveralls', require: false
|
data/Rakefile
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/testtask'
|
3
|
-
require 'bundler/gem_tasks'
|
4
|
-
|
5
|
-
Rake::TestTask.new do |t|
|
6
|
-
t.pattern = 'test/**/*_test.rb'
|
7
|
-
t.libs.push 'test'
|
8
|
-
end
|
9
|
-
|
10
|
-
namespace :test do
|
11
|
-
task :coverage do
|
12
|
-
ENV['COVERAGE'] = 'true'
|
13
|
-
Rake::Task['test'].invoke
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
task default: :test
|
data/test/entity_test.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
describe Lotus::Entity do
|
4
|
-
before do
|
5
|
-
class Car
|
6
|
-
include Lotus::Entity
|
7
|
-
end
|
8
|
-
|
9
|
-
class Book
|
10
|
-
include Lotus::Entity
|
11
|
-
self.attributes = :title, :author
|
12
|
-
end
|
13
|
-
|
14
|
-
class NonFinctionBook < Book
|
15
|
-
end
|
16
|
-
|
17
|
-
class Camera
|
18
|
-
include Lotus::Entity
|
19
|
-
attr_accessor :analog
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
after do
|
24
|
-
[:Car, :Book, :NonFinctionBook, :Camera].each do |const|
|
25
|
-
Object.send(:remove_const, const)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe 'attributes' do
|
30
|
-
let(:attributes) { [:id, :model] }
|
31
|
-
|
32
|
-
it 'defines attributes' do
|
33
|
-
Car.send(:attributes=, attributes)
|
34
|
-
Car.send(:attributes).must_equal attributes
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe '#initialize' do
|
39
|
-
describe 'with defined attributes' do
|
40
|
-
it 'accepts given attributes' do
|
41
|
-
book = Book.new(title: "A Lover's Discourse: Fragments", author: 'Roland Barthes')
|
42
|
-
|
43
|
-
book.instance_variable_get(:@title).must_equal "A Lover's Discourse: Fragments"
|
44
|
-
book.instance_variable_get(:@author).must_equal 'Roland Barthes'
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'ignores unknown attributes' do
|
48
|
-
book = Book.new(unknown: 'x')
|
49
|
-
|
50
|
-
book.instance_variable_get(:@book).must_be_nil
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'accepts given attributes for subclass' do
|
54
|
-
book = NonFinctionBook.new(title: 'Refactoring', author: 'Martin Fowler')
|
55
|
-
|
56
|
-
book.instance_variable_get(:@title).must_equal 'Refactoring'
|
57
|
-
book.instance_variable_get(:@author).must_equal 'Martin Fowler'
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe 'with undefined attributes' do
|
62
|
-
it 'is able to initialize an entity without given attributes' do
|
63
|
-
camera = Camera.new
|
64
|
-
camera.analog.must_be_nil
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'is able to initialize an entity if it has the right accessors' do
|
68
|
-
camera = Camera.new(analog: true)
|
69
|
-
camera.analog.must_equal(true)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "raises an error when the given attributes don't correspond to a known accessor" do
|
73
|
-
-> { Camera.new(digital: true) }.must_raise(NoMethodError)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe 'accessors' do
|
79
|
-
it 'exposes getters for attributes' do
|
80
|
-
book = Book.new(title: 'High Fidelity')
|
81
|
-
|
82
|
-
book.title.must_equal 'High Fidelity'
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'exposes setters for attributes' do
|
86
|
-
book = Book.new
|
87
|
-
book.title = 'A Man'
|
88
|
-
|
89
|
-
book.instance_variable_get(:@title).must_equal 'A Man'
|
90
|
-
book.title.must_equal 'A Man'
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'exposes accessor for id' do
|
94
|
-
book = Book.new
|
95
|
-
book.id.must_be_nil
|
96
|
-
|
97
|
-
book.id = 23
|
98
|
-
book.id.must_equal 23
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '#==' do
|
103
|
-
before do
|
104
|
-
@book1 = Book.new
|
105
|
-
@book1.id = 23
|
106
|
-
|
107
|
-
@book2 = Book.new
|
108
|
-
@book2.id = 23
|
109
|
-
|
110
|
-
@book3 = Book.new
|
111
|
-
@car = Car.new
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'returns true if they have the same class and id' do
|
115
|
-
@book1.must_equal @book2
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'returns false if they have the same class but different id' do
|
119
|
-
@book1.wont_equal @book3
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'returns false if they have different class' do
|
123
|
-
@book1.wont_equal @car
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
data/test/fixtures.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
class User
|
2
|
-
include Lotus::Entity
|
3
|
-
self.attributes = :name, :age
|
4
|
-
end
|
5
|
-
|
6
|
-
class Article
|
7
|
-
include Lotus::Entity
|
8
|
-
self.attributes = :user_id, :unmapped_attribute, :title, :comments_count
|
9
|
-
end
|
10
|
-
|
11
|
-
class UserRepository
|
12
|
-
include Lotus::Repository
|
13
|
-
end
|
14
|
-
|
15
|
-
class ArticleRepository
|
16
|
-
include Lotus::Repository
|
17
|
-
|
18
|
-
def self.rank
|
19
|
-
query do
|
20
|
-
desc(:comments_count)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.by_user(user)
|
25
|
-
query do
|
26
|
-
where(user_id: user.id)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.not_by_user(user)
|
31
|
-
exclude by_user(user)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.rank_by_user(user)
|
35
|
-
rank.by_user(user)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
DB = Sequel.connect(SQLITE_CONNECTION_STRING)
|
40
|
-
|
41
|
-
DB.create_table :users do
|
42
|
-
primary_key :id
|
43
|
-
String :name
|
44
|
-
Integer :age
|
45
|
-
end
|
46
|
-
|
47
|
-
DB.create_table :articles do
|
48
|
-
primary_key :_id
|
49
|
-
Integer :user_id
|
50
|
-
String :s_title
|
51
|
-
String :comments_count # Not an error: we're testing String => Integer coercion
|
52
|
-
String :umapped_column
|
53
|
-
end
|
54
|
-
|
55
|
-
DB.create_table :devices do
|
56
|
-
primary_key :id
|
57
|
-
end
|
58
|
-
|
59
|
-
# DB.dataset_class = Class.new(Sequel::Dataset)
|
60
|
-
|
61
|
-
#FIXME this should be passed by the framework internals.
|
62
|
-
MAPPER = Lotus::Model::Mapper.new do
|
63
|
-
collection :users do
|
64
|
-
entity User
|
65
|
-
|
66
|
-
attribute :id, Integer
|
67
|
-
attribute :name, String
|
68
|
-
attribute :age, Integer
|
69
|
-
end
|
70
|
-
|
71
|
-
collection :articles do
|
72
|
-
entity Article
|
73
|
-
|
74
|
-
attribute :id, Integer, as: :_id
|
75
|
-
attribute :user_id, Integer
|
76
|
-
attribute :title, String, as: 's_title'
|
77
|
-
attribute :comments_count, Integer
|
78
|
-
|
79
|
-
identity :_id
|
80
|
-
end
|
81
|
-
end.load!
|
@@ -1,75 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
describe Lotus::Model::Adapters::Abstract do
|
4
|
-
let(:adapter) { Lotus::Model::Adapters::Abstract.new(mapper) }
|
5
|
-
let(:mapper) { Object.new }
|
6
|
-
let(:entity) { Object.new }
|
7
|
-
let(:query) { Object.new }
|
8
|
-
let(:collection) { :collection }
|
9
|
-
|
10
|
-
describe '#persist' do
|
11
|
-
it 'raises error' do
|
12
|
-
->{ adapter.persist(collection, entity) }.must_raise NotImplementedError
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe '#create' do
|
17
|
-
it 'raises error' do
|
18
|
-
->{ adapter.create(collection, entity) }.must_raise NotImplementedError
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe '#update' do
|
23
|
-
it 'raises error' do
|
24
|
-
->{ adapter.update(collection, entity) }.must_raise NotImplementedError
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '#delete' do
|
29
|
-
it 'raises error' do
|
30
|
-
->{ adapter.delete(collection, entity) }.must_raise NotImplementedError
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#all' do
|
35
|
-
it 'raises error' do
|
36
|
-
->{ adapter.all(collection) }.must_raise NotImplementedError
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe '#find' do
|
41
|
-
it 'raises error' do
|
42
|
-
->{ adapter.find(collection, 1) }.must_raise NotImplementedError
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe '#first' do
|
47
|
-
it 'raises error' do
|
48
|
-
->{ adapter.first(collection) }.must_raise NotImplementedError
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe '#last' do
|
53
|
-
it 'raises error' do
|
54
|
-
->{ adapter.last(collection) }.must_raise NotImplementedError
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe '#clear' do
|
59
|
-
it 'raises error' do
|
60
|
-
->{ adapter.clear(collection) }.must_raise NotImplementedError
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe '#command' do
|
65
|
-
it 'raises error' do
|
66
|
-
->{ adapter.command(query) }.must_raise NotImplementedError
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe '#query' do
|
71
|
-
it 'raises error' do
|
72
|
-
->{ adapter.query(collection) }.must_raise NotImplementedError
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
describe Lotus::Model::Adapters::Implementation do
|
4
|
-
before do
|
5
|
-
TestAdapter = Class.new(Lotus::Model::Adapters::Abstract) do
|
6
|
-
include Lotus::Model::Adapters::Implementation
|
7
|
-
end
|
8
|
-
|
9
|
-
mapper = Object.new
|
10
|
-
@adapter = TestAdapter.new(mapper)
|
11
|
-
end
|
12
|
-
|
13
|
-
after do
|
14
|
-
Object.send(:remove_const, :TestAdapter)
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'must implement #_collection' do
|
18
|
-
-> {
|
19
|
-
@adapter.send(:_collection, :x)
|
20
|
-
}.must_raise NotImplementedError
|
21
|
-
end
|
22
|
-
end
|
@@ -1,91 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
describe Lotus::Model::Adapters::Memory::Query do
|
4
|
-
before do
|
5
|
-
MockDataset = Struct.new(:records) do
|
6
|
-
def all
|
7
|
-
records
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_s
|
11
|
-
records.to_s
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class MockCollection
|
16
|
-
def deserialize(array)
|
17
|
-
array
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
collection = MockCollection.new
|
22
|
-
@query = Lotus::Model::Adapters::Memory::Query.new(dataset, collection)
|
23
|
-
end
|
24
|
-
|
25
|
-
after do
|
26
|
-
Object.send(:remove_const, :MockDataset)
|
27
|
-
Object.send(:remove_const, :MockCollection)
|
28
|
-
end
|
29
|
-
|
30
|
-
let(:dataset) { MockDataset.new([]) }
|
31
|
-
|
32
|
-
describe '#negate!' do
|
33
|
-
it 'raises an error' do
|
34
|
-
-> { @query.negate! }.must_raise NotImplementedError
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe '#to_s' do
|
39
|
-
let(:dataset) { MockDataset.new([1, 2, 3]) }
|
40
|
-
|
41
|
-
it 'delegates to the wrapped dataset' do
|
42
|
-
@query.to_s.must_equal dataset.to_s
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe '#empty?' do
|
47
|
-
describe "when it's empty" do
|
48
|
-
it 'returns true' do
|
49
|
-
@query.must_be_empty
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "when it's filled with elements" do
|
54
|
-
let(:dataset) { MockDataset.new([1, 2, 3]) }
|
55
|
-
|
56
|
-
it 'returns false' do
|
57
|
-
@query.wont_be_empty
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe '#any?' do
|
63
|
-
describe "when it's empty" do
|
64
|
-
it 'returns false' do
|
65
|
-
assert !@query.any?
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "when it's filled with elements" do
|
70
|
-
let(:dataset) { MockDataset.new([1, 2, 3]) }
|
71
|
-
|
72
|
-
it 'returns true' do
|
73
|
-
assert @query.any?
|
74
|
-
end
|
75
|
-
|
76
|
-
describe "when a block is passed" do
|
77
|
-
describe "and it doesn't match elements" do
|
78
|
-
it 'returns false' do
|
79
|
-
assert !@query.any? {|e| e > 100 }
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
describe "and it matches elements" do
|
84
|
-
it 'returns true' do
|
85
|
-
assert @query.any? {|e| e % 2 == 0 }
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|