lotus-model 0.4.1 → 0.5.0

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.
@@ -25,21 +25,32 @@ module Lotus
25
25
  # @since 0.4.0
26
26
  # @api private
27
27
  def create
28
- `createdb #{ database } #{ create_options }`
28
+ set_environment_variables
29
+ `createdb #{ database }`
29
30
  end
30
31
 
31
32
  # @since 0.4.0
32
33
  # @api private
33
34
  def drop
34
- new_connection.run %(DROP DATABASE "#{ database }")
35
- rescue Sequel::DatabaseError => e
36
- message = if e.message.match(/does not exist/)
37
- "Cannot find database: #{ database }"
38
- else
39
- e.message
40
- end
35
+ set_environment_variables
36
+
37
+ require 'open3'
38
+
39
+ Open3.popen3('dropdb', database) do |stdin, stdout, stderr, wait_thr|
40
+ exit_status = wait_thr.value
41
+
42
+ unless exit_status.success?
43
+ error_message = stderr.read
41
44
 
42
- raise MigrationError.new(message)
45
+ message = if error_message.match(/does not exist/)
46
+ "Cannot find database: #{ database }"
47
+ else
48
+ message
49
+ end
50
+
51
+ raise MigrationError.new(message)
52
+ end
53
+ end
43
54
  end
44
55
 
45
56
  # @since 0.4.0
@@ -59,14 +70,6 @@ module Lotus
59
70
 
60
71
  private
61
72
 
62
- # @since 0.4.0
63
- # @api private
64
- def create_options
65
- result = ""
66
- result += %( --owner=#{ username }) unless username.nil?
67
- result
68
- end
69
-
70
73
  # @since 0.4.0
71
74
  # @api private
72
75
  def set_environment_variables
@@ -38,7 +38,7 @@ module Lotus
38
38
  def create
39
39
  path.dirname.mkpath
40
40
  FileUtils.touch(path)
41
- rescue Errno::EACCES
41
+ rescue Errno::EACCES, Errno::EPERM
42
42
  raise MigrationError.new("Permission denied: #{ path.sub(/\A\/\//, '') }")
43
43
  end
44
44
 
@@ -69,7 +69,7 @@ module Lotus
69
69
  # @api private
70
70
  def path
71
71
  root.join(
72
- @connection.uri.sub(/#{ @connection.adapter_scheme }\:\/\//, '')
72
+ @connection.uri.sub(/(jdbc\:|)sqlite\:\/\//, '')
73
73
  )
74
74
  end
75
75
 
@@ -3,6 +3,6 @@ module Lotus
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '0.4.1'.freeze
6
+ VERSION = '0.5.0'.freeze
7
7
  end
8
8
  end
@@ -212,11 +212,17 @@ module Lotus
212
212
  @adapter = adapter
213
213
  end
214
214
 
215
+ # @since 0.5.0
216
+ # @api private
217
+ def adapter
218
+ @adapter
219
+ end
220
+
215
221
  # Creates or updates a record in the database for the given entity.
216
222
  #
217
223
  # @param entity [#id, #id=] the entity to persist
218
224
  #
219
- # @return [Object] the entity
225
+ # @return [Object] a copy of the entity with `id` assigned
220
226
  #
221
227
  # @since 0.1.0
222
228
  #
@@ -233,8 +239,9 @@ module Lotus
233
239
  # article = Article.new(title: 'Introducing Lotus::Model')
234
240
  # article.id # => nil
235
241
  #
236
- # ArticleRepository.persist(article) # creates a record
237
- # article.id # => 23
242
+ # persisted_article = ArticleRepository.persist(article) # creates a record
243
+ # article.id # => nil
244
+ # persisted_article.id # => 23
238
245
  #
239
246
  # @example With a persisted entity
240
247
  # require 'lotus/model'
@@ -257,13 +264,13 @@ module Lotus
257
264
  end
258
265
 
259
266
  # Creates a record in the database for the given entity.
260
- # It assigns the `id` attribute, in case of success.
267
+ # It returns a copy of the entity with `id` assigned.
261
268
  #
262
269
  # If already persisted (`id` present) it does nothing.
263
270
  #
264
271
  # @param entity [#id,#id=] the entity to create
265
272
  #
266
- # @return [Object] the entity
273
+ # @return [Object] a copy of the entity with `id` assigned
267
274
  #
268
275
  # @since 0.1.0
269
276
  #
@@ -279,10 +286,16 @@ module Lotus
279
286
  # article = Article.new(title: 'Introducing Lotus::Model')
280
287
  # article.id # => nil
281
288
  #
282
- # ArticleRepository.create(article) # creates a record
283
- # article.id # => 23
289
+ # created_article = ArticleRepository.create(article) # creates a record
290
+ # article.id # => nil
291
+ # created_article.id # => 23
292
+ #
293
+ # created_article = ArticleRepository.create(article)
294
+ # created_article.id # => 24
295
+ #
296
+ # created_article = ArticleRepository.create(existing_article) # => no-op
297
+ # created_article # => nil
284
298
  #
285
- # ArticleRepository.create(article) # no-op
286
299
  def create(entity)
287
300
  unless _persisted?(entity)
288
301
  _touch(entity)
@@ -552,6 +565,7 @@ module Lotus
552
565
  end
553
566
 
554
567
  private
568
+
555
569
  # Executes the given raw statement on the adapter.
556
570
  #
557
571
  # Please note that it's only supported by some databases,
@@ -561,12 +575,13 @@ module Lotus
561
575
  # For advanced scenarios, please check the documentation of each adapter.
562
576
  #
563
577
  # @param raw [String] the raw statement to execute on the connection
564
- # @return [Object] the raw result set from SQL adapter
578
+ #
579
+ # @return [NilClass]
565
580
  #
566
581
  # @raise [NotImplementedError] if current Lotus::Model adapter doesn't
567
582
  # implement `execute`.
568
583
  #
569
- # @raise [Lotus::Model::InvalidQueryError] if raw statement is invalid
584
+ # @raise [Lotus::Model::InvalidCommandError] if the raw statement is invalid
570
585
  #
571
586
  # @see Lotus::Model::Adapters::Abstract#execute
572
587
  # @see Lotus::Model::Adapters::SqlAdapter#execute
@@ -583,21 +598,122 @@ module Lotus
583
598
  #
584
599
  # class ArticleRepository
585
600
  # include Lotus::Repository
586
- # end
587
- #
588
- # article = Article.new(title: 'Introducing transactions',
589
- # body: 'lorem ipsum')
590
601
  #
591
- # result_set = ArticleRepository.execute("SELECT * FROM articles")
592
- # result_set.each_hash do |result|
593
- # result # -> { id: 123, title: "Introducing transactions", body: "lorem ipsum"}
602
+ # def self.reset_comments_count
603
+ # execute "UPDATE articles SET comments_count = 0"
604
+ # end
594
605
  # end
595
606
  #
596
- # puts result_set.class # => SQLite3::ResultSet
607
+ # ArticleRepository.reset_comments_count
597
608
  def execute(raw)
598
609
  @adapter.execute(raw)
599
610
  end
600
611
 
612
+ # Fetch raw result sets for the the given statement.
613
+ #
614
+ # PLEASE NOTE: The returned result set contains an array of hashes.
615
+ # The columns are returned as they are from the database,
616
+ # the mapper is bypassed here.
617
+ #
618
+ # @param raw [String] the raw statement used to fetch records
619
+ # @param blk [Proc] an optional block that is yielded for each record
620
+ #
621
+ # @return [Enumerable<Hash>,Array<Hash>] the collection of raw records
622
+ #
623
+ # @raise [NotImplementedError] if current Lotus::Model adapter doesn't
624
+ # implement `fetch`.
625
+ #
626
+ # @raise [Lotus::Model::InvalidQueryError] if the raw statement is invalid
627
+ #
628
+ # @since 0.5.0
629
+ #
630
+ # @example Basic Usage
631
+ # require 'lotus/model'
632
+ #
633
+ # mapping do
634
+ # collection :articles do
635
+ # attribute :id, Integer, as: :s_id
636
+ # attribute :title, String, as: :s_title
637
+ # end
638
+ # end
639
+ #
640
+ # class Article
641
+ # include Lotus::Entity
642
+ # attributes :title, :body
643
+ # end
644
+ #
645
+ # class ArticleRepository
646
+ # include Lotus::Repository
647
+ #
648
+ # def self.all_raw
649
+ # fetch("SELECT * FROM articles")
650
+ # end
651
+ # end
652
+ #
653
+ # ArticleRepository.all_raw
654
+ # # => [{:_id=>1, :user_id=>nil, :s_title=>"Art 1", :comments_count=>nil, :umapped_column=>nil}]
655
+ #
656
+ # @example Map A Value From Result Set
657
+ # require 'lotus/model'
658
+ #
659
+ # mapping do
660
+ # collection :articles do
661
+ # attribute :id, Integer, as: :s_id
662
+ # attribute :title, String, as: :s_title
663
+ # end
664
+ # end
665
+ #
666
+ # class Article
667
+ # include Lotus::Entity
668
+ # attributes :title, :body
669
+ # end
670
+ #
671
+ # class ArticleRepository
672
+ # include Lotus::Repository
673
+ #
674
+ # def self.titles
675
+ # fetch("SELECT s_title FROM articles").map do |article|
676
+ # article[:s_title]
677
+ # end
678
+ # end
679
+ # end
680
+ #
681
+ # ArticleRepository.titles # => ["Announcing Lotus v0.5.0"]
682
+ #
683
+ # @example Passing A Block
684
+ # require 'lotus/model'
685
+ #
686
+ # mapping do
687
+ # collection :articles do
688
+ # attribute :id, Integer, as: :s_id
689
+ # attribute :title, String, as: :s_title
690
+ # end
691
+ # end
692
+ #
693
+ # class Article
694
+ # include Lotus::Entity
695
+ # attributes :title, :body
696
+ # end
697
+ #
698
+ # class ArticleRepository
699
+ # include Lotus::Repository
700
+ #
701
+ # def self.titles
702
+ # result = []
703
+ #
704
+ # fetch("SELECT s_title FROM articles") do |article|
705
+ # result << article[:s_title]
706
+ # end
707
+ #
708
+ # result
709
+ # end
710
+ # end
711
+ #
712
+ # ArticleRepository.titles # => ["Announcing Lotus v0.5.0"]
713
+ def fetch(raw, &blk)
714
+ @adapter.fetch(raw, &blk)
715
+ end
716
+
601
717
  # Fabricates a query and yields the given block to access the low level
602
718
  # APIs exposed by the query itself.
603
719
  #
data/lotus-model.gemspec CHANGED
@@ -6,7 +6,7 @@ require 'lotus/model/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'lotus-model'
8
8
  spec.version = Lotus::Model::VERSION
9
- spec.authors = ['Luca Guidi', 'Trung Lê', 'Alfonso Uceda Pompa']
9
+ spec.authors = ['Luca Guidi', 'Trung Lê', 'Alfonso Uceda']
10
10
  spec.email = ['me@lucaguidi.com', 'trung.le@ruby-journal.com', 'uceda73@gmail.com']
11
11
  spec.summary = %q{A persistence layer for Lotus}
12
12
  spec.description = %q{A persistence framework with entities, repositories, data mapper and query objects}
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lotus-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  - Trung Lê
9
- - Alfonso Uceda Pompa
9
+ - Alfonso Uceda
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-07-10 00:00:00.000000000 Z
13
+ date: 2015-09-30 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: lotus-utils
@@ -116,16 +116,19 @@ files:
116
116
  - lib/lotus/model/adapters/sql/consoles/sqlite.rb
117
117
  - lib/lotus/model/adapters/sql/query.rb
118
118
  - lib/lotus/model/adapters/sql_adapter.rb
119
+ - lib/lotus/model/coercer.rb
119
120
  - lib/lotus/model/config/adapter.rb
120
121
  - lib/lotus/model/config/mapper.rb
121
122
  - lib/lotus/model/configuration.rb
122
123
  - lib/lotus/model/mapper.rb
123
124
  - lib/lotus/model/mapping.rb
124
- - lib/lotus/model/mapping/coercer.rb
125
- - lib/lotus/model/mapping/coercions.rb
125
+ - lib/lotus/model/mapping/attribute.rb
126
+ - lib/lotus/model/mapping/coercers.rb
126
127
  - lib/lotus/model/mapping/collection.rb
128
+ - lib/lotus/model/mapping/collection_coercer.rb
127
129
  - lib/lotus/model/migrator.rb
128
130
  - lib/lotus/model/migrator/adapter.rb
131
+ - lib/lotus/model/migrator/connection.rb
129
132
  - lib/lotus/model/migrator/mysql_adapter.rb
130
133
  - lib/lotus/model/migrator/postgres_adapter.rb
131
134
  - lib/lotus/model/migrator/sqlite_adapter.rb
@@ -152,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
155
  version: '0'
153
156
  requirements: []
154
157
  rubyforge_project:
155
- rubygems_version: 2.4.8
158
+ rubygems_version: 2.4.5.1
156
159
  signing_key:
157
160
  specification_version: 4
158
161
  summary: A persistence layer for Lotus
@@ -1,192 +0,0 @@
1
- require 'lotus/utils/kernel'
2
-
3
- module Lotus
4
- module Model
5
- module Mapping
6
- # Coercions utilities
7
- #
8
- # @since 0.1.1
9
- module Coercions
10
- # Coerce into an Array, unless the argument is nil
11
- #
12
- # @param arg [Object] the object to coerce
13
- #
14
- # @return [Array] the result of the coercion
15
- #
16
- # @raise [TypeError] if the argument can't be coerced
17
- #
18
- # @since 0.1.1
19
- #
20
- # @see http://ruby-doc.org/core/Kernel.html#method-i-Array
21
- def self.Array(arg)
22
- ::Kernel.Array(arg) unless arg.nil?
23
- end
24
-
25
- # Coerce into a Boolean, unless the argument is nil
26
- #
27
- # @param arg [Object] the object to coerce
28
- #
29
- # @return [Boolean] the result of the coercion
30
- #
31
- # @raise [TypeError] if the argument can't be coerced
32
- #
33
- # @since 0.1.1
34
- #
35
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Boolean-class_method
36
- def self.Boolean(arg)
37
- Utils::Kernel.Boolean(arg) unless arg.nil?
38
- end
39
-
40
- # Coerce into a Date, unless the argument is nil
41
- #
42
- # @param arg [Object] the object to coerce
43
- #
44
- # @return [Date] the result of the coercion
45
- #
46
- # @raise [TypeError] if the argument can't be coerced
47
- #
48
- # @since 0.1.1
49
- #
50
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Date-class_method
51
- def self.Date(arg)
52
- Utils::Kernel.Date(arg) unless arg.nil?
53
- end
54
-
55
- # Coerce into a DateTime, unless the argument is nil
56
- #
57
- # @param arg [Object] the object to coerce
58
- #
59
- # @return [DateTime] the result of the coercion
60
- #
61
- # @raise [TypeError] if the argument can't be coerced
62
- #
63
- # @since 0.1.1
64
- #
65
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#DateTime-class_method
66
- def self.DateTime(arg)
67
- Utils::Kernel.DateTime(arg) unless arg.nil?
68
- end
69
-
70
- # Coerce into a Float, unless the argument is nil
71
- #
72
- # @param arg [Object] the object to coerce
73
- #
74
- # @return [Float] the result of the coercion
75
- #
76
- # @raise [TypeError] if the argument can't be coerced
77
- #
78
- # @since 0.1.1
79
- #
80
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Float-class_method
81
- def self.Float(arg)
82
- Utils::Kernel.Float(arg) unless arg.nil?
83
- end
84
-
85
- # Coerce into a Hash, unless the argument is nil
86
- #
87
- # @param arg [Object] the object to coerce
88
- #
89
- # @return [Hash] the result of the coercion
90
- #
91
- # @raise [TypeError] if the argument can't be coerced
92
- #
93
- # @since 0.1.1
94
- #
95
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Hash-class_method
96
- def self.Hash(arg)
97
- Utils::Kernel.Hash(arg) unless arg.nil?
98
- end
99
-
100
- # Coerce into an Integer, unless the argument is nil
101
- #
102
- # @param arg [Object] the object to coerce
103
- #
104
- # @return [Integer] the result of the coercion
105
- #
106
- # @raise [TypeError] if the argument can't be coerced
107
- #
108
- # @since 0.1.1
109
- #
110
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Integer-class_method
111
- def self.Integer(arg)
112
- Utils::Kernel.Integer(arg) unless arg.nil?
113
- end
114
-
115
- # Coerce into a BigDecimal, unless the argument is nil
116
- #
117
- # @param arg [Object] the object to coerce
118
- #
119
- # @return [BigDecimal] the result of the coercion
120
- #
121
- # @raise [TypeError] if the argument can't be coerced
122
- #
123
- # @since 0.2.0
124
- #
125
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#BigDecimal-class_method
126
- def self.BigDecimal(arg)
127
- Utils::Kernel.BigDecimal(arg) unless arg.nil?
128
- end
129
-
130
- # Coerce into a Set, unless the argument is nil
131
- #
132
- # @param arg [Object] the object to coerce
133
- #
134
- # @return [Set] the result of the coercion
135
- #
136
- # @raise [TypeError] if the argument can't be coerced
137
- #
138
- # @since 0.1.1
139
- #
140
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Set-class_method
141
- def self.Set(arg)
142
- Utils::Kernel.Set(arg) unless arg.nil?
143
- end
144
-
145
- # Coerce into a String, unless the argument is nil
146
- #
147
- # @param arg [Object] the object to coerce
148
- #
149
- # @return [String] the result of the coercion
150
- #
151
- # @raise [TypeError] if the argument can't be coerced
152
- #
153
- # @since 0.1.1
154
- #
155
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#String-class_method
156
- def self.String(arg)
157
- Utils::Kernel.String(arg) unless arg.nil?
158
- end
159
-
160
- # Coerce into a Symbol, unless the argument is nil
161
- #
162
- # @param arg [Object] the object to coerce
163
- #
164
- # @return [Symbol] the result of the coercion
165
- #
166
- # @raise [TypeError] if the argument can't be coerced
167
- #
168
- # @since 0.2.0
169
- #
170
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Symbol-class_method
171
- def self.Symbol(arg)
172
- Utils::Kernel.Symbol(arg) unless arg.nil?
173
- end
174
-
175
- # Coerce into a Time, unless the argument is nil
176
- #
177
- # @param arg [Object] the object to coerce
178
- #
179
- # @return [Time] the result of the coercion
180
- #
181
- # @raise [TypeError] if the argument can't be coerced
182
- #
183
- # @since 0.1.1
184
- #
185
- # @see http://rdoc.info/gems/lotus-utils/Lotus/Utils/Kernel#Time-class_method
186
- def self.Time(arg)
187
- Utils::Kernel.Time(arg) unless arg.nil?
188
- end
189
- end
190
- end
191
- end
192
- end