sbf-dm-timestamps 1.3.0.beta

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9eb98b6e188b0ec86511c39fdd4221f2e462fc98607ddaf24134c805e90d08c7
4
+ data.tar.gz: 07b7970e3cc3f70a2480d7a4e719d1db066edee83a64e732cbbb328c5b5bb6df
5
+ SHA512:
6
+ metadata.gz: 6d6c9f7397f67ad515b9563dd2599233d77d55622b5ddddefcbbbd69a54af1fbe1344b5f05a2b548f9cf30d458f28ae0f59faf0bb5393088b7c40a0e745fba1e
7
+ data.tar.gz: 36f028b5d80ff0299f79a3bb0430714bd8f0d9098b6b4a72478e8ca5dcdcc935b39a92984dd72ff5b213c8dfadf02cdaecd25207a3cd2efc73eb85704485a195
data/.gitignore ADDED
@@ -0,0 +1,40 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## Rubinius
17
+ *.rbc
18
+ ## RubyMine
19
+ .idea
20
+
21
+ ## Rubymine
22
+ .idea/
23
+
24
+ ## PROJECT::GENERAL
25
+ *.gem
26
+ coverage
27
+ rdoc
28
+ pkg
29
+ tmp
30
+ doc
31
+ log
32
+ .yardoc
33
+ measurements
34
+
35
+ ## BUNDLER
36
+ .bundle
37
+ Gemfile.*
38
+
39
+ ## PROJECT::SPECIFIC
40
+ spec/db/
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --order rand
3
+ --format documentation
4
+ --profile
5
+ --backtrace
data/.rubocop.yml ADDED
@@ -0,0 +1,468 @@
1
+ #require: rubocop-performance
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.7
5
+
6
+ Gemspec/DeprecatedAttributeAssignment:
7
+ Enabled: true
8
+
9
+ Gemspec/DevelopmentDependencies: # new in 1.44
10
+ Enabled: true
11
+
12
+ Gemspec/RequireMFA:
13
+ Enabled: false
14
+
15
+ Layout/LineContinuationLeadingSpace: # new in 1.31
16
+ Enabled: true
17
+
18
+ Layout/LineContinuationSpacing: # new in 1.31
19
+ Enabled: true
20
+
21
+ Layout/LineEndStringConcatenationIndentation:
22
+ Enabled: true
23
+
24
+ Layout/LineLength:
25
+ Max: 150
26
+
27
+ Layout/MultilineOperationIndentation:
28
+ EnforcedStyle: aligned
29
+
30
+ Layout/SpaceAfterSemicolon:
31
+ Enabled: true
32
+
33
+ Layout/SpaceBeforeBrackets: # new in 1.7
34
+ Enabled: true
35
+
36
+ Layout/SpaceInsideHashLiteralBraces:
37
+ EnforcedStyle: no_space
38
+
39
+ Lint/AmbiguousAssignment: # new in 1.7
40
+ Enabled: true
41
+
42
+ Lint/AmbiguousBlockAssociation:
43
+ Enabled: true
44
+ Exclude:
45
+ - 'spec/**/*'
46
+
47
+ Lint/AmbiguousOperatorPrecedence: # new in 1.21
48
+ Enabled: true
49
+
50
+ Lint/AmbiguousRange: # new in 1.19
51
+ Enabled: true
52
+
53
+ Lint/ConstantDefinitionInBlock:
54
+ Enabled: true
55
+
56
+ Lint/ConstantOverwrittenInRescue: # new in 1.31
57
+ Enabled: true
58
+
59
+ Lint/DeprecatedConstants: # new in 1.8
60
+ Enabled: true
61
+
62
+ Lint/DuplicateBranch: # new in 1.3
63
+ Enabled: true
64
+
65
+ Lint/DuplicateMagicComment: # new in 1.37
66
+ Enabled: true
67
+
68
+ Lint/DuplicateMatchPattern: # new in 1.50
69
+ Enabled: true
70
+
71
+ Lint/DuplicateMethods:
72
+ Enabled: false
73
+
74
+ Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
75
+ Enabled: true
76
+
77
+ Lint/EmptyBlock:
78
+ Enabled: true
79
+
80
+ Lint/EmptyClass: # new in 1.3
81
+ Enabled: true
82
+
83
+ Lint/EmptyFile:
84
+ Enabled: true
85
+
86
+ Lint/EmptyInPattern: # new in 1.16
87
+ Enabled: true
88
+
89
+ Lint/FloatComparison:
90
+ Enabled: true
91
+
92
+ Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
93
+ Enabled: true
94
+
95
+ Lint/ItWithoutArgumentsInBlock: # new in 1.59
96
+ Enabled: true
97
+
98
+ Lint/LambdaWithoutLiteralBlock: # new in 1.8
99
+ Enabled: true
100
+
101
+ Lint/LiteralAssignmentInCondition: # new in 1.58
102
+ Enabled: true
103
+
104
+ Lint/MissingSuper:
105
+ Enabled: true
106
+
107
+ Lint/MixedCaseRange: # new in 1.53
108
+ Enabled: true
109
+
110
+ Lint/NoReturnInBeginEndBlocks: # new in 1.2
111
+ Enabled: true
112
+
113
+ Lint/NonAtomicFileOperation: # new in 1.31
114
+ Enabled: true
115
+
116
+ Lint/NumberedParameterAssignment: # new in 1.9
117
+ Enabled: true
118
+
119
+ Lint/OrAssignmentToConstant: # new in 1.9
120
+ Enabled: true
121
+
122
+ Lint/RaiseException:
123
+ Enabled: false
124
+
125
+ Lint/RedundantDirGlobSort: # new in 1.8
126
+ Enabled: true
127
+
128
+ Lint/RedundantRegexpQuantifiers: # new in 1.53
129
+ Enabled: true
130
+
131
+ Lint/RefinementImportMethods: # new in 1.27
132
+ Enabled: true
133
+
134
+ Lint/RequireRangeParentheses: # new in 1.32
135
+ Enabled: true
136
+
137
+ Lint/RequireRelativeSelfPath: # new in 1.22
138
+ Enabled: true
139
+
140
+ Lint/SafeNavigationChain:
141
+ Enabled: true
142
+ AllowedMethods:
143
+ - present?
144
+ - blank?
145
+ - presence
146
+ - try
147
+ - try!
148
+ - empty?
149
+ - nil?
150
+ - blank?
151
+
152
+ Lint/SymbolConversion:
153
+ Enabled: false
154
+
155
+ Lint/ToEnumArguments: # new in 1.1
156
+ Enabled: true
157
+
158
+ Lint/TripleQuotes: # new in 1.9
159
+ Enabled: true
160
+
161
+ Lint/UnexpectedBlockArity: # new in 1.5
162
+ Enabled: true
163
+
164
+ Lint/UnmodifiedReduceAccumulator: # new in 1.1
165
+ Enabled: true
166
+
167
+ Lint/UnreachableLoop:
168
+ Enabled: true
169
+
170
+ Lint/UselessRescue: # new in 1.43
171
+ Enabled: true
172
+
173
+ Lint/UselessRuby2Keywords: # new in 1.23
174
+ Enabled: true
175
+
176
+ Metrics/AbcSize:
177
+ Enabled: false
178
+
179
+ Metrics/BlockLength:
180
+ Enabled: false
181
+
182
+ Metrics/BlockNesting:
183
+ Max: 4
184
+
185
+ Metrics/ClassLength:
186
+ Enabled: false
187
+
188
+ Metrics/CollectionLiteralLength: # new in 1.47
189
+ Enabled: true
190
+
191
+ Metrics/CyclomaticComplexity:
192
+ Max: 15
193
+
194
+ Metrics/MethodLength:
195
+ Max: 30
196
+
197
+ Metrics/ModuleLength:
198
+ Enabled: false
199
+
200
+ Metrics/ParameterLists:
201
+ Max: 5
202
+ CountKeywordArgs: false
203
+
204
+ Metrics/PerceivedComplexity:
205
+ Max: 20
206
+
207
+ Naming/BlockForwarding: # new in 1.24
208
+ Enabled: true
209
+
210
+ Naming/HeredocDelimiterNaming:
211
+ Enabled: false
212
+
213
+ Naming/MethodParameterName:
214
+ AllowedNames: [a, _, id]
215
+
216
+ Naming/VariableNumber:
217
+ Enabled: true
218
+ # EnforcedStyle: snake_case
219
+
220
+ #Performance/CollectionLiteralInLoop:
221
+ # Enabled: true
222
+ #
223
+ #Performance/RangeInclude:
224
+ # Enabled: false
225
+ #
226
+ #Performance/RedundantEqualityComparisonBlock:
227
+ # Enabled: true
228
+
229
+ Security/CompoundHash: # new in 1.28
230
+ Enabled: true
231
+
232
+ Security/IoMethods: # new in 1.22
233
+ Enabled: true
234
+
235
+ Style/AccessModifierDeclarations:
236
+ EnforcedStyle: inline
237
+
238
+ Style/Alias:
239
+ Enabled: false
240
+ EnforcedStyle: prefer_alias_method
241
+
242
+ Style/ArgumentsForwarding: # new in 1.1
243
+ Enabled: true
244
+
245
+ Style/ArrayIntersect: # new in 1.40
246
+ Enabled: true
247
+
248
+ Style/CaseLikeIf:
249
+ Enabled: true
250
+
251
+ Style/CollectionCompact: # new in 1.2
252
+ Enabled: true
253
+
254
+ Style/CombinableLoops:
255
+ Enabled: true
256
+
257
+ Style/ComparableClamp: # new in 1.44
258
+ Enabled: true
259
+
260
+ Style/ConcatArrayLiterals: # new in 1.41
261
+ Enabled: true
262
+
263
+ Style/DataInheritance: # new in 1.49
264
+ Enabled: true
265
+
266
+ Style/DirEmpty: # new in 1.48
267
+ Enabled: true
268
+
269
+ Style/Documentation:
270
+ Enabled: false
271
+
272
+ Style/DocumentDynamicEvalDefinition: # new in 1.1
273
+ Enabled: true
274
+
275
+ Style/EmptyHeredoc: # new in 1.32
276
+ Enabled: true
277
+
278
+ Style/EndlessMethod: # new in 1.8
279
+ Enabled: true
280
+
281
+ Style/EnvHome: # new in 1.29
282
+ Enabled: true
283
+
284
+ Style/ExactRegexpMatch: # new in 1.51
285
+ Enabled: true
286
+
287
+ Style/FetchEnvVar:
288
+ Enabled: true
289
+
290
+ Style/FileEmpty: # new in 1.48
291
+ Enabled: true
292
+
293
+ Style/FileRead: # new in 1.24
294
+ Enabled: true
295
+
296
+ Style/FileWrite: # new in 1.24
297
+ Enabled: true
298
+
299
+ Style/FormatStringToken:
300
+ Enabled: false
301
+
302
+ Style/FrozenStringLiteralComment:
303
+ Enabled: false
304
+
305
+ Style/HashConversion: # new in 1.10
306
+ Enabled: true
307
+
308
+ Style/HashExcept: # new in 1.7
309
+ Enabled: true
310
+
311
+ Style/HashLikeCase:
312
+ Enabled: true
313
+
314
+ Style/HashSyntax:
315
+ Enabled: true
316
+ EnforcedShorthandSyntax: consistent
317
+
318
+ Style/IfWithBooleanLiteralBranches: # new in 1.9
319
+ Enabled: true
320
+
321
+ Style/InPatternThen: # new in 1.16
322
+ Enabled: true
323
+
324
+ Style/MagicCommentFormat: # new in 1.35
325
+ Enabled: true
326
+
327
+ Style/MapCompactWithConditionalBlock: # new in 1.30
328
+ Enabled: true
329
+
330
+ Style/MapToHash: # new in 1.24
331
+ Enabled: true
332
+
333
+ Style/MapToSet: # new in 1.42
334
+ Enabled: true
335
+
336
+ Style/MinMaxComparison: # new in 1.42
337
+ Enabled: true
338
+
339
+ Style/MixinGrouping:
340
+ Enabled: true
341
+ EnforcedStyle: grouped
342
+
343
+ Style/MultilineInPatternThen: # new in 1.16
344
+ Enabled: true
345
+
346
+ Style/NegatedIfElseCondition: # new in 1.2
347
+ Enabled: true
348
+
349
+ Style/NestedFileDirname: # new in 1.26
350
+ Enabled: true
351
+
352
+ Style/NilLambda: # new in 1.3
353
+ Enabled: true
354
+
355
+ Style/NumberedParameters: # new in 1.22
356
+ Enabled: true
357
+
358
+ Style/NumberedParametersLimit: # new in 1.22
359
+ Enabled: true
360
+
361
+ Style/NumericPredicate:
362
+ Enabled: false
363
+
364
+ Style/ObjectThen: # new in 1.28
365
+ Enabled: true
366
+
367
+ Style/OpenStructUse:
368
+ Enabled: false
369
+
370
+ Style/OperatorMethodCall: # new in 1.37
371
+ Enabled: true
372
+
373
+ Style/OptionalBooleanParameter:
374
+ Enabled: true
375
+
376
+ Style/PercentLiteralDelimiters:
377
+ PreferredDelimiters:
378
+ default: ()
379
+ '%i': '()'
380
+ '%I': '()'
381
+ '%r': '{}'
382
+ '%w': '()'
383
+ '%W': '()'
384
+
385
+ Style/QuotedSymbols: # new in 1.16
386
+ Enabled: true
387
+
388
+ Style/RedundantArgument: # new in 1.4
389
+ Enabled: true
390
+
391
+ Style/RedundantArrayConstructor: # new in 1.52
392
+ Enabled: true
393
+
394
+ Style/RedundantConstantBase: # new in 1.40
395
+ Enabled: true
396
+
397
+ Style/RedundantCurrentDirectoryInPath: # new in 1.53
398
+ Enabled: true
399
+
400
+ Style/RedundantDoubleSplatHashBraces: # new in 1.41
401
+ Enabled: true
402
+
403
+ Style/RedundantEach: # new in 1.38
404
+ Enabled: true
405
+
406
+ Style/RedundantFilterChain: # new in 1.52
407
+ Enabled: true
408
+
409
+ Style/RedundantHeredocDelimiterQuotes: # new in 1.45
410
+ Enabled: true
411
+
412
+ Style/RedundantInitialize: # new in 1.27
413
+ Enabled: true
414
+
415
+ Style/RedundantLineContinuation: # new in 1.49
416
+ Enabled: true
417
+
418
+ Style/RedundantParentheses:
419
+ Enabled: true
420
+
421
+ Style/RedundantRegexpArgument: # new in 1.53
422
+ Enabled: true
423
+
424
+ Style/RedundantRegexpConstructor: # new in 1.52
425
+ Enabled: true
426
+
427
+ Style/RedundantSelfAssignmentBranch: # new in 1.19
428
+ Enabled: true
429
+
430
+ Style/RedundantStringEscape: # new in 1.37
431
+ Enabled: true
432
+
433
+ Style/RegexpLiteral:
434
+ Enabled: true
435
+ EnforcedStyle: mixed
436
+
437
+ Style/RescueStandardError:
438
+ EnforcedStyle: implicit
439
+
440
+ Style/ReturnNilInPredicateMethodDefinition: # new in 1.53
441
+ Enabled: true
442
+
443
+ Style/SelectByRegexp: # new in 1.22
444
+ Enabled: true
445
+
446
+ Style/SingleArgumentDig:
447
+ Enabled: true
448
+
449
+ Style/SignalException:
450
+ EnforcedStyle: only_raise
451
+
452
+ Style/SingleLineDoEndBlock: # new in 1.57
453
+ Enabled: true
454
+
455
+ Style/StringChars: # new in 1.12
456
+ Enabled: true
457
+
458
+ Style/SuperWithArgsParentheses: # new in 1.58
459
+ Enabled: true
460
+
461
+ Style/SwapValues: # new in 1.1
462
+ Enabled: true
463
+
464
+ Style/TernaryParentheses:
465
+ EnforcedStyle: require_parentheses_when_complex
466
+
467
+ Style/YAMLFileRead: # new in 1.53
468
+ Enabled: true
data/Gemfile ADDED
@@ -0,0 +1,69 @@
1
+ require 'pathname'
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ SOURCE = ENV.fetch('SOURCE', :git).to_sym
8
+ REPO_POSTFIX = (SOURCE == :path) ? '' : '.git'
9
+ DATAMAPPER = (SOURCE == :path) ? Pathname(__FILE__).dirname.parent : 'https://github.com/firespring'
10
+ DM_VERSION = '~> 1.3.0.beta'.freeze
11
+ DO_VERSION = '~> 0.10.17'.freeze
12
+ DM_DO_ADAPTERS = %w(sqlite postgres mysql oracle sqlserver).freeze
13
+ CURRENT_BRANCH = ENV.fetch('GIT_BRANCH', 'master')
14
+
15
+ options = {}
16
+ options[SOURCE] = "#{DATAMAPPER}/dm-core#{REPO_POSTFIX}"
17
+ options[:branch] = CURRENT_BRANCH unless SOURCE == :path
18
+ gem 'sbf-dm-core', DM_VERSION, options.dup
19
+
20
+ platforms :mri_18 do
21
+ group :quality do
22
+ gem 'yard'
23
+ gem 'yardstick'
24
+ end
25
+ end
26
+
27
+ group :datamapper do
28
+ adapters = ENV['ADAPTER'] || ENV.fetch('ADAPTERS', nil)
29
+ adapters = adapters.to_s.tr(',', ' ').split.uniq - %w(in_memory)
30
+
31
+ if (do_adapters = DM_DO_ADAPTERS & adapters).any?
32
+ do_options = {}
33
+ if ENV['DO_GIT'] == 'true'
34
+ do_options = options.dup
35
+ do_options[SOURCE] = "#{DATAMAPPER}/datamapper-do#{REPO_POSTFIX}"
36
+ end
37
+ gem 'sbf-data_objects', DO_VERSION, do_options.dup
38
+
39
+ do_adapters.each do |adapter|
40
+ adapter = 'sqlite3' if adapter == 'sqlite'
41
+
42
+ gem "sbf-do_#{adapter}", DO_VERSION, do_options.dup
43
+ end
44
+
45
+ options[SOURCE] = "#{DATAMAPPER}/dm-do-adapter#{REPO_POSTFIX}"
46
+ gem 'sbf-dm-do-adapter', DM_VERSION, options.dup
47
+ end
48
+
49
+ adapters.each do |adapter|
50
+ options[SOURCE] = "#{DATAMAPPER}/dm-#{adapter}-adapter#{REPO_POSTFIX}"
51
+ gem "sbf-dm-#{adapter}-adapter", DM_VERSION, options.dup
52
+ end
53
+
54
+ plugins = ENV['PLUGINS'] || ENV.fetch('PLUGIN', nil)
55
+ plugins = plugins.to_s.tr(',', ' ').split.push('dm-migrations').uniq
56
+
57
+ plugins.each do |plugin|
58
+ options[SOURCE] = "#{DATAMAPPER}/#{plugin}#{REPO_POSTFIX}"
59
+ gem "sbf-#{plugin}", DM_VERSION, options.dup
60
+ end
61
+ end
62
+
63
+ group :development do
64
+ gem 'pry'
65
+ gem 'pry-byebug'
66
+ gem 'rake'
67
+ gem 'rspec'
68
+ gem 'simplecov'
69
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Foy Savas
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = dm-timestamps
2
+
3
+ DataMapper plugin which adds "magic" to created_at, created_on, et cetera.
4
+
5
+ = Using
6
+
7
+ This plugin works by looking for the "created_at," "updated_at," "created_on"
8
+ and "updated_on" properties. If they exist, it does the right thing by setting
9
+ them or updating them. The *at properties should be of type DateTime, while the
10
+ *on properties should be of type Date.
11
+
12
+ Alternatively, you can have all of this setup for you if you use the "timestamps"
13
+ helper:
14
+
15
+ timestamps :at # Add created_at and updated_at
16
+ timestamps :on # Add created_on and updated_on
17
+ timestamps :created_at, :updated_on # Add these only
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ FileList['tasks/**/*.rake'].each { |task| import task }
@@ -0,0 +1,20 @@
1
+ require File.expand_path('lib/data_mapper/timestamps/version', __dir__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ['Foy Savas', 'Dan Kubb']
5
+ gem.email = ['dan.kubb@gmail.com']
6
+ gem.summary = 'DataMapper plugin for magical timestamps'
7
+ gem.description = 'DataMapper plugin which adds “magic” to created_at, created_on, et cetera.'
8
+ gem.license = 'Nonstandard'
9
+ gem.homepage = 'https://datamapper.org'
10
+
11
+ gem.files = `git ls-files`.split("\n")
12
+ gem.extra_rdoc_files = %w(LICENSE README.rdoc)
13
+
14
+ gem.name = 'sbf-dm-timestamps'
15
+ gem.require_paths = ['lib']
16
+ gem.version = DataMapper::Timestamps::VERSION
17
+ gem.required_ruby_version = '>= 2.7.8'
18
+
19
+ gem.add_runtime_dependency('sbf-dm-core', '~> 1.3.0.beta')
20
+ end
@@ -0,0 +1,5 @@
1
+ module DataMapper
2
+ module Timestamps
3
+ VERSION = '1.3.0.beta'
4
+ end
5
+ end
@@ -0,0 +1,67 @@
1
+ require 'dm-core'
2
+
3
+ module DataMapper
4
+ module Timestamps
5
+ TIMESTAMP_PROPERTIES = {
6
+ updated_at: [DateTime, ->(_r) { DateTime.now }],
7
+ updated_on: [Date, ->(_r) { Date.today }],
8
+ created_at: [DateTime, ->(r) { r.created_at || (DateTime.now if r.new?) }],
9
+ created_on: [Date, ->(r) { r.created_on || (Date.today if r.new?) }],
10
+ }.freeze
11
+
12
+ def self.included(model)
13
+ model.before :save, :set_timestamps_on_save
14
+ model.extend ClassMethods
15
+ end
16
+
17
+ # Saves the record with the updated_at/on attributes set to the current time.
18
+ def touch
19
+ set_timestamps
20
+ save
21
+ end
22
+
23
+ private
24
+
25
+ def set_timestamps_on_save
26
+ return unless dirty?
27
+
28
+ set_timestamps
29
+ end
30
+
31
+ def set_timestamps
32
+ TIMESTAMP_PROPERTIES.each do |name,(_type,proc)|
33
+ attribute_set(name, proc.call(self)) if properties.named?(name)
34
+ end
35
+ end
36
+
37
+ module ClassMethods
38
+ def timestamps(*names)
39
+ raise ArgumentError, 'You need to pass at least one argument' if names.empty?
40
+
41
+ names.each do |name|
42
+ case name
43
+ when *TIMESTAMP_PROPERTIES.keys
44
+ options = {required: true}
45
+
46
+ options.update(auto_validation: false) if Property.accepted_options.include?(:auto_validation)
47
+
48
+ property name, TIMESTAMP_PROPERTIES[name].first, options
49
+ when :at
50
+ timestamps(:created_at, :updated_at)
51
+ when :on
52
+ timestamps(:created_on, :updated_on)
53
+ else
54
+ raise InvalidTimestampName, "Invalid timestamp property name '#{name}'"
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ class InvalidTimestampName < RuntimeError; end
61
+
62
+ Model.append_inclusions self
63
+ end
64
+
65
+ # include Timestamp or Timestamps, it still works
66
+ Timestamp = Timestamps
67
+ end
@@ -0,0 +1,197 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe 'DataMapper::Timestamp' do
4
+ supported_by :all do
5
+
6
+ shared_examples 'Timestamp (shared behavior)' do
7
+ it "does not set the created_at/on fields if they're already set" do
8
+ green_smoothie = GreenSmoothie.new(:name => 'Banana')
9
+ time = (DateTime.now - 100)
10
+ date = Date.new(time.year,time.month,time.day)
11
+ green_smoothie.created_at = time
12
+ green_smoothie.created_on = date
13
+ green_smoothie.save
14
+ expect(green_smoothie.created_at).to eq time
15
+ expect(green_smoothie.created_on).to eq date
16
+ expect(green_smoothie.created_at).to be_a_kind_of(DateTime)
17
+ expect(green_smoothie.created_on).to be_a_kind_of(Date)
18
+ end
19
+
20
+ it 'sets the created_at/on fields on creation' do
21
+ green_smoothie = GreenSmoothie.new(:name => 'Banana')
22
+ expect(green_smoothie.created_at).to be_nil
23
+ expect(green_smoothie.created_on).to be_nil
24
+ green_smoothie.save
25
+ expect(green_smoothie.created_at).to be_a_kind_of(DateTime)
26
+ expect(green_smoothie.created_on).to be_a_kind_of(Date)
27
+ end
28
+
29
+ it 'does not alter the create_at/on fields on model updates' do
30
+ green_smoothie = GreenSmoothie.new(:id => 2, :name => 'Berry')
31
+ expect(green_smoothie.created_at).to be_nil
32
+ expect(green_smoothie.created_on).to be_nil
33
+ green_smoothie.save
34
+ original_created_at = green_smoothie.created_at
35
+ original_created_on = green_smoothie.created_on
36
+ green_smoothie.name = 'Strawberry'
37
+ green_smoothie.save
38
+ expect(green_smoothie.created_at).to eql(original_created_at)
39
+ expect(green_smoothie.created_on).to eql(original_created_on)
40
+ end
41
+
42
+ it 'sets the updated_at/on fields on creation and on update' do
43
+ green_smoothie = GreenSmoothie.new(:name => 'Mango')
44
+ expect(green_smoothie.updated_at).to be_nil
45
+ expect(green_smoothie.updated_on).to be_nil
46
+ green_smoothie.save
47
+ expect(green_smoothie.updated_at).to be_a_kind_of(DateTime)
48
+ expect(green_smoothie.updated_on).to be_a_kind_of(Date)
49
+ original_updated_at = green_smoothie.updated_at
50
+ original_updated_on = green_smoothie.updated_on
51
+ time_tomorrow = DateTime.now + 1
52
+ date_tomorrow = Date.today + 1
53
+ DateTime.stub!(:now).and_return { time_tomorrow }
54
+ Date.stub!(:today).and_return { date_tomorrow }
55
+ green_smoothie.name = 'Cranberry Mango'
56
+ green_smoothie.save
57
+ expect(green_smoothie.updated_at).not_to eql(original_updated_at)
58
+ expect(green_smoothie.updated_on).not_to eql(original_updated_on)
59
+ expect(green_smoothie.updated_at).to eql(time_tomorrow)
60
+ expect(green_smoothie.updated_on).to eql(date_tomorrow)
61
+ end
62
+
63
+ it 'only sets the updated_at/on fields on dirty objects' do
64
+ green_smoothie = GreenSmoothie.new(:name => 'Mango')
65
+ expect(green_smoothie.updated_at).to be_nil
66
+ expect(green_smoothie.updated_on).to be_nil
67
+ green_smoothie.save
68
+ expect(green_smoothie.updated_at).to be_a_kind_of(DateTime)
69
+ expect(green_smoothie.updated_on).to be_a_kind_of(Date)
70
+ original_updated_at = green_smoothie.updated_at
71
+ original_updated_on = green_smoothie.updated_on
72
+ time_tomorrow = DateTime.now + 1
73
+ date_tomorrow = Date.today + 1
74
+ DateTime.stub!(:now).and_return { time_tomorrow }
75
+ Date.stub!(:today).and_return { date_tomorrow }
76
+ green_smoothie.save
77
+ expect(green_smoothie.updated_at).not_to eql(time_tomorrow)
78
+ expect(green_smoothie.updated_on).not_to eql(date_tomorrow)
79
+ expect(green_smoothie.updated_at).to eql(original_updated_at)
80
+ expect(green_smoothie.updated_on).to eql(original_updated_on)
81
+ end
82
+
83
+ describe '#touch' do
84
+ it 'updates the updated_at/on fields' do
85
+ green_smoothie = GreenSmoothie.create(:name => 'Mango')
86
+
87
+ time_tomorrow = DateTime.now + 1
88
+ date_tomorrow = Date.today + 1
89
+ DateTime.stub!(:now).and_return { time_tomorrow }
90
+ Date.stub!(:today).and_return { date_tomorrow }
91
+
92
+ green_smoothie.touch
93
+
94
+ expect(green_smoothie.updated_at).to eql(time_tomorrow)
95
+ expect(green_smoothie.updated_on).to eql(date_tomorrow)
96
+ end
97
+
98
+ it 'does not update the created_at/on fields' do
99
+ green_smoothie = GreenSmoothie.create(:name => 'Mango')
100
+
101
+ original_created_at = green_smoothie.created_at
102
+ original_created_on = green_smoothie.created_on
103
+
104
+ green_smoothie.touch
105
+
106
+ expect(green_smoothie.created_at).to equal(original_created_at)
107
+ expect(green_smoothie.created_on).to equal(original_created_on)
108
+ end
109
+ end
110
+ end
111
+
112
+ describe 'explicit property declaration' do
113
+ before do
114
+ Object.send(:remove_const, :GreenSmoothie) if defined?(GreenSmoothie)
115
+ class GreenSmoothie
116
+ include DataMapper::Resource
117
+
118
+ property :id, Serial
119
+ property :name, String
120
+ property :created_at, DateTime, required: true
121
+ property :created_on, Date, required: true
122
+ property :updated_at, DateTime, required: true
123
+ property :updated_on, Date, required: true
124
+
125
+ auto_migrate!
126
+ end
127
+ end
128
+
129
+ it_behaves_like 'Timestamp (shared behavior)'
130
+ end
131
+
132
+ describe 'implicit property declaration' do
133
+ before do
134
+ Object.send(:remove_const, :GreenSmoothie) if defined?(GreenSmoothie)
135
+ class GreenSmoothie
136
+ include DataMapper::Resource
137
+
138
+ property :id, Serial
139
+ property :name, String
140
+
141
+ timestamps :at, :on
142
+
143
+ auto_migrate!
144
+ end
145
+ end
146
+
147
+ it_behaves_like 'Timestamp (shared behavior)'
148
+ end
149
+
150
+ describe 'timestamps helper' do
151
+ describe 'inclusion' do
152
+ before :each do
153
+ @klass = Class.new do
154
+ include DataMapper::Resource
155
+ end
156
+ end
157
+
158
+ it 'provides #timestamps' do
159
+ expect(@klass).to respond_to(:timestamps)
160
+ end
161
+
162
+ it 'sets the *at properties' do
163
+ @klass.timestamps :at
164
+
165
+ expect(@klass.properties).to be_named(:created_at)
166
+ expect(@klass.properties[:created_at]).to be_kind_of(DataMapper::Property::DateTime)
167
+ expect(@klass.properties).to be_named(:updated_at)
168
+ expect(@klass.properties[:updated_at]).to be_kind_of(DataMapper::Property::DateTime)
169
+ end
170
+
171
+ it 'sets the *on properties' do
172
+ @klass.timestamps :on
173
+
174
+ expect(@klass.properties).to be_named(:created_on)
175
+ expect(@klass.properties[:created_on]).to be_kind_of(DataMapper::Property::Date)
176
+ expect(@klass.properties).to be_named(:updated_on)
177
+ expect(@klass.properties[:updated_on]).to be_kind_of(DataMapper::Property::Date)
178
+ end
179
+
180
+ it 'sets multiple properties' do
181
+ @klass.timestamps :created_at, :updated_on
182
+
183
+ expect(@klass.properties).to be_named(:created_at)
184
+ expect(@klass.properties).to be_named(:updated_on)
185
+ end
186
+
187
+ it 'fails on unknown property name' do
188
+ expect { @klass.timestamps :wowee }.to raise_error(DataMapper::Timestamp::InvalidTimestampName)
189
+ end
190
+
191
+ it 'fails on empty arguments' do
192
+ expect { @klass.timestamps }.to raise_error(ArgumentError)
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
data/spec/rcov.opts ADDED
@@ -0,0 +1,6 @@
1
+ --exclude "spec,^/"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
@@ -0,0 +1,11 @@
1
+ require 'dm-core/spec/setup'
2
+ require 'dm-core/spec/lib/adapter_helpers'
3
+
4
+ require 'dm-timestamps'
5
+ require 'dm-migrations'
6
+
7
+ DataMapper::Spec.setup
8
+
9
+ RSpec.configure do |config|
10
+ config.extend(DataMapper::Spec::Adapters::Helpers)
11
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,21 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ begin
4
+ task(:default).clear
5
+ task(:spec).clear
6
+
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = 'spec/**/*_spec.rb'
9
+
10
+ require 'simplecov'
11
+ SimpleCov.start do
12
+ minimum_coverage 100
13
+ end
14
+ end
15
+ rescue LoadError
16
+ task :spec do
17
+ abort 'rspec is not available. In order to run spec, you must: gem install rspec'
18
+ end
19
+ end
20
+
21
+ task default: :spec
data/tasks/yard.rake ADDED
@@ -0,0 +1,9 @@
1
+ begin
2
+ require 'yard'
3
+
4
+ YARD::Rake::YardocTask.new
5
+ rescue LoadError
6
+ task :yard do
7
+ abort 'YARD is not available. In order to run yard, you must: gem install yard'
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'pathname'
3
+ require 'yardstick/rake/measurement'
4
+ require 'yardstick/rake/verify'
5
+
6
+ # yardstick_measure task
7
+ Yardstick::Rake::Measurement.new
8
+
9
+ # verify_measurements task
10
+ Yardstick::Rake::Verify.new do |verify|
11
+ verify.threshold = 100
12
+ end
13
+ rescue LoadError
14
+ %w(yardstick_measure verify_measurements).each do |name|
15
+ task name.to_s do
16
+ abort "Yardstick is not available. In order to run #{name}, you must: gem install yardstick"
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sbf-dm-timestamps
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.0.beta
5
+ platform: ruby
6
+ authors:
7
+ - Foy Savas
8
+ - Dan Kubb
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2024-10-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: sbf-dm-core
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 1.3.0.beta
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 1.3.0.beta
28
+ description: DataMapper plugin which adds “magic” to created_at, created_on, et cetera.
29
+ email:
30
+ - dan.kubb@gmail.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files:
34
+ - LICENSE
35
+ - README.rdoc
36
+ files:
37
+ - ".gitignore"
38
+ - ".rspec"
39
+ - ".rubocop.yml"
40
+ - Gemfile
41
+ - LICENSE
42
+ - README.rdoc
43
+ - Rakefile
44
+ - dm-timestamps.gemspec
45
+ - lib/data_mapper/timestamps/version.rb
46
+ - lib/dm-timestamps.rb
47
+ - spec/integration/timestamps_spec.rb
48
+ - spec/rcov.opts
49
+ - spec/spec_helper.rb
50
+ - tasks/spec.rake
51
+ - tasks/yard.rake
52
+ - tasks/yardstick.rake
53
+ homepage: https://datamapper.org
54
+ licenses:
55
+ - Nonstandard
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: 2.7.8
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">"
69
+ - !ruby/object:Gem::Version
70
+ version: 1.3.1
71
+ requirements: []
72
+ rubygems_version: 3.4.10
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: DataMapper plugin for magical timestamps
76
+ test_files: []