lotus-model 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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