lotus-model 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|