ensurance 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 73ed04613ebf3946434e575c85ca906f25d39626
4
+ data.tar.gz: 77c943a28db5eaf457eab1d3f38baaa345f0afc4
5
+ SHA512:
6
+ metadata.gz: 821667d18e5db34c6cd5219bca2749eddc0fbd3f706350c1dce1b8143048424fbdac3790d8de1c269ce5a84340e1deccf26b6885d180e7324c2a5875b6d8ce50
7
+ data.tar.gz: 8547c089119cee156698b63e6dee1cd89d4a89f16ceabd1e60391342754bacac53656469cf98ff0a3b6ec8b7e289bab7297084511c449dcdaaf4179784910cb3
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.0
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in ensurance.gemspec
6
+ gemspec
7
+
@@ -0,0 +1,61 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ensurance (0.1.0)
5
+ activesupport (>= 3, < 6)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (5.1.4)
11
+ activesupport (= 5.1.4)
12
+ activerecord (5.1.4)
13
+ activemodel (= 5.1.4)
14
+ activesupport (= 5.1.4)
15
+ arel (~> 8.0)
16
+ activesupport (5.1.4)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (~> 0.7)
19
+ minitest (~> 5.1)
20
+ tzinfo (~> 1.1)
21
+ arel (8.0.0)
22
+ concurrent-ruby (1.0.5)
23
+ diff-lcs (1.3)
24
+ globalid (0.4.1)
25
+ activesupport (>= 4.2.0)
26
+ i18n (0.9.0)
27
+ concurrent-ruby (~> 1.0)
28
+ minitest (5.10.3)
29
+ rake (10.5.0)
30
+ rspec (3.7.0)
31
+ rspec-core (~> 3.7.0)
32
+ rspec-expectations (~> 3.7.0)
33
+ rspec-mocks (~> 3.7.0)
34
+ rspec-core (3.7.0)
35
+ rspec-support (~> 3.7.0)
36
+ rspec-expectations (3.7.0)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.7.0)
39
+ rspec-mocks (3.7.0)
40
+ diff-lcs (>= 1.2.0, < 2.0)
41
+ rspec-support (~> 3.7.0)
42
+ rspec-support (3.7.0)
43
+ sqlite3 (1.3.13)
44
+ thread_safe (0.3.6)
45
+ tzinfo (1.2.4)
46
+ thread_safe (~> 0.1)
47
+
48
+ PLATFORMS
49
+ ruby
50
+
51
+ DEPENDENCIES
52
+ activerecord (>= 3)
53
+ bundler (~> 1.16)
54
+ ensurance!
55
+ globalid (>= 0.3.6)
56
+ rake (~> 10.0)
57
+ rspec (~> 3.0)
58
+ sqlite3 (>= 1.3.0)
59
+
60
+ BUNDLED WITH
61
+ 1.16.0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Ben Sharpe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,100 @@
1
+ # Ensurance
2
+
3
+ Allows you to ensure you have the class you expect... it's similar to
4
+
5
+ ```
6
+ result = value.is_a?(Person) ? value : Person.find(value)
7
+ ```
8
+
9
+ You can add fields to "ensure_by" (:id is included always)
10
+ e.g.
11
+
12
+ if you add `ensure_by :token` to the User class
13
+ User.ensure(<UserObject>) works
14
+ User.ensure(:user_id) works
15
+ User.ensure(:token) works
16
+
17
+ .ensure() returns nil if the record is not found
18
+ .ensure!() throws an exception if the record is not found
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ ```ruby
25
+ gem 'ensurance'
26
+ ```
27
+
28
+ And then execute:
29
+
30
+ $ bundle
31
+
32
+ ## Usage
33
+
34
+ In your Rails app... `include Ensurance` either in specific models or `ApplicationRecord` to cover all your models.
35
+
36
+ It's really handy for service objects or Jobs that you want to call from the console to try out.
37
+
38
+ ```
39
+ class User < ApplicationRecord
40
+ include Ensurance
41
+ end
42
+
43
+
44
+ class SomeServiceClass
45
+ def perform(user)
46
+ user = User.ensure(user)
47
+ # do something constructive here
48
+ end
49
+ end
50
+ ```
51
+
52
+ In this way you can call it with a User object, or a user `id` and it works just the same.
53
+
54
+ Also adds ensurance features to `Hash`, `Time`, and `Date`
55
+
56
+ ```
57
+ Time.ensure(Date.today) -> Date.today.beginning_of_day
58
+ Time.ensure(1509556285) -> 2017-11-01 11:11:25 -0600
59
+ Time.ensure("1509556285") -> 2017-11-01 11:11:25 -0600
60
+ Time.ensure(DateTime.now) -> DateTime.now.to_time
61
+ Time.ensure(nil) -> nil
62
+ Time.ensure(1..4) -> ArgumentError "Unhandled Type for Time to ensure: Range"
63
+
64
+ Date.ensure(Date.today) -> Date.today
65
+ Date.ensure(nil) -> nil
66
+ Date.ensure(1509556285) -> 2017-11-01
67
+
68
+ Hash.ensure(<aHash>) -> <aHash>
69
+ Hash.ensure(<json_string>) -> Hash
70
+ Hash.ensure(nil) -> nil
71
+ Hash.ensure(<an array>) -> <an array>.to_h
72
+ ```
73
+
74
+ ### ActiveRecord
75
+
76
+ You can specify another field or fields to ensure by doing the following:
77
+
78
+ ```
79
+ class User < ApplicationRecord
80
+ include Ensurance
81
+
82
+ ensure_by :token <- totally optional
83
+ end
84
+
85
+ User.ensure(1) == User.find(1)
86
+ User.ensure(<a user record>) -> <a user record>
87
+ User.ensure(<globalid>) == GlobalID::Locator.locate(<globalid>)
88
+ User.ensure(<globalid string>) == GlobalID::Locator.locate(<globalid string>)
89
+ User.ensure(<some token>) == User.where(token: <some token>).first
90
+ User.ensure(nil) -> nil
91
+ User.ensuer!(nil) -> ActiveRecord::RecordNotFound
92
+ ```
93
+
94
+ ## Contributing
95
+
96
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bsharpe/ensurance.
97
+
98
+ ## License
99
+
100
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ensurance"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,42 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "ensurance/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ensurance"
8
+ spec.version = Ensurance::VERSION
9
+ spec.authors = ["Ben Sharpe"]
10
+ spec.email = ["bsharpe@gmail.com"]
11
+
12
+ spec.summary = %q{Add ability to ensure common types and AR models}
13
+ spec.description = %q{}
14
+ spec.homepage = ""
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against " \
23
+ # "public gem pushes."
24
+ # end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ f.match(%r{^(test|spec|features)/})
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ spec.add_runtime_dependency 'activesupport', '>= 3', '< 6'
34
+
35
+ spec.add_development_dependency "bundler", "~> 1.16"
36
+ spec.add_development_dependency "rake", "~> 10.0"
37
+ spec.add_development_dependency "rspec", "~> 3.0"
38
+ spec.add_development_dependency "activerecord", '>= 3', '< 6'
39
+ spec.add_development_dependency "globalid", '>= 0.3.6', '< 2'
40
+ spec.add_development_dependency "sqlite3", '>= 1.3.0', '< 4'
41
+ end
42
+
@@ -0,0 +1,52 @@
1
+ require "ensurance/version"
2
+ require 'active_support'
3
+ require 'active_support/core_ext/date'
4
+ require 'active_support/core_ext/time'
5
+ require 'active_support/core_ext/hash'
6
+ require 'json'
7
+
8
+ require 'ensurance/date'
9
+ require 'ensurance/time'
10
+ require 'ensurance/hash'
11
+
12
+ module Ensurance
13
+ extend ActiveSupport::Concern
14
+
15
+ class_methods do
16
+ def ensure_by(*args)
17
+ @_ensure_by ||= [:id]
18
+ @_ensure_by += [args].flatten
19
+ end
20
+
21
+ def ensure(thing = nil)
22
+ return nil unless thing.present?
23
+
24
+ if thing.is_a?(self)
25
+ return thing
26
+ elsif thing.is_a?(GlobalID)
27
+ return GlobalID::Locator.locate(thing)
28
+ elsif thing.is_a?(Hash) && thing['_aj_globalid'] && (found = GlobalID::Locator.locate(thing['_aj_globalid']))
29
+ return found
30
+ elsif thing.is_a?(String) && found = GlobalID::Locator.locate(thing)
31
+ return found
32
+ end
33
+ found = nil
34
+
35
+ @_ensure_by ||= [:id]
36
+ @_ensure_by.each do |ensure_field|
37
+ value = thing.try(:fetch, ensure_field.to_sym, nil) || thing.try(:fetch, ensure_field.to_s, nil) || thing
38
+ found = self.find_by(ensure_field => value)
39
+ break if found.is_a?(self)
40
+ end
41
+
42
+ found
43
+ end
44
+
45
+ def ensure!(thing = nil)
46
+ result = self.ensure(thing)
47
+ raise ::ActiveRecord::RecordNotFound unless result
48
+ result
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,42 @@
1
+
2
+ module Ensurance
3
+ class Date
4
+ FORMATS = %w|%m/%d/%Y %Y/%m/%d|.freeze
5
+ def self.ensure(thing)
6
+ case thing.class.name
7
+ when "NilClass"
8
+ nil
9
+ when "Integer","Float"
10
+ Time.ensure(thing).to_date
11
+ when "Date"
12
+ thing
13
+ when "String"
14
+ if thing.to_i.to_s == thing
15
+ ::Time.at(thing.to_i).to_date
16
+ elsif thing.to_f.to_s == thing
17
+ ::Time.at(thing.to_f).to_date
18
+ elsif thing.index("/")
19
+ # Assume US Date format
20
+ result = nil
21
+ FORMATS.each do |f|
22
+ begin
23
+ result = Date.strptime(thing, f)
24
+ break
25
+ rescue ArgumentError
26
+ end
27
+ end
28
+ raise ArgumentError.new("Bad Date: #{thing}".yellow) unless result
29
+ result
30
+ else
31
+ ::Date.parse(thing)
32
+ end
33
+ else
34
+ if thing.respond_to?(:to_date)
35
+ thing.to_date
36
+ else
37
+ raise ArgumentError.new("Unknown Type for Date to ensure: #{thing.class.name}")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ module Ensurance
2
+ class Hash
3
+ def self.ensure(thing)
4
+ case thing.class.name
5
+ when "Hash","HashWithIndifferentAccess"
6
+ thing
7
+ when "String"
8
+ JSON.parse(thing)
9
+ when "NilClass"
10
+ nil
11
+ else
12
+ if thing.respond_to?(:to_h)
13
+ begin
14
+ thing.to_h
15
+ rescue TypeError
16
+ raise ArgumentError.new("Unhandled Type for Hash to ensure: #{thing.class}")
17
+ end
18
+ else
19
+ raise ArgumentError.new("Unhandled Type for Hash to ensure: #{thing.class}")
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ module Ensurance
2
+ class Time
3
+ def self.ensure(thing)
4
+ case thing.class.name
5
+ when "NilClass"
6
+ thing
7
+ when "Time"
8
+ thing
9
+ when "Date"
10
+ thing.beginning_of_day
11
+ when "Integer", "Float"
12
+ ::Time.at(thing)
13
+ when "String"
14
+ if thing.to_i.to_s == thing
15
+ ::Time.at(thing.to_i)
16
+ elsif thing.to_f.to_s == thing
17
+ ::Time.at(thing.to_f)
18
+ else
19
+ ::Time.parse(thing)
20
+ end
21
+ else
22
+ if thing.respond_to?(:to_time)
23
+ thing.to_time
24
+ else
25
+ raise ArgumentError.new("Unhandled Type for Time to ensure: #{thing.class}")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module Ensurance
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ensurance
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Sharpe
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-11-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '6'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '6'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.16'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.16'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '10.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: activerecord
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '3'
82
+ - - "<"
83
+ - !ruby/object:Gem::Version
84
+ version: '6'
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '3'
92
+ - - "<"
93
+ - !ruby/object:Gem::Version
94
+ version: '6'
95
+ - !ruby/object:Gem::Dependency
96
+ name: globalid
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: 0.3.6
102
+ - - "<"
103
+ - !ruby/object:Gem::Version
104
+ version: '2'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: 0.3.6
112
+ - - "<"
113
+ - !ruby/object:Gem::Version
114
+ version: '2'
115
+ - !ruby/object:Gem::Dependency
116
+ name: sqlite3
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: 1.3.0
122
+ - - "<"
123
+ - !ruby/object:Gem::Version
124
+ version: '4'
125
+ type: :development
126
+ prerelease: false
127
+ version_requirements: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 1.3.0
132
+ - - "<"
133
+ - !ruby/object:Gem::Version
134
+ version: '4'
135
+ description: ''
136
+ email:
137
+ - bsharpe@gmail.com
138
+ executables: []
139
+ extensions: []
140
+ extra_rdoc_files: []
141
+ files:
142
+ - ".gitignore"
143
+ - ".rspec"
144
+ - ".travis.yml"
145
+ - Gemfile
146
+ - Gemfile.lock
147
+ - LICENSE.txt
148
+ - README.md
149
+ - Rakefile
150
+ - bin/console
151
+ - bin/setup
152
+ - ensurance.gemspec
153
+ - file:memdb1?mode=memory&cache=shared
154
+ - lib/ensurance.rb
155
+ - lib/ensurance/date.rb
156
+ - lib/ensurance/hash.rb
157
+ - lib/ensurance/time.rb
158
+ - lib/ensurance/version.rb
159
+ homepage: ''
160
+ licenses:
161
+ - MIT
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 2.6.13
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Add ability to ensure common types and AR models
183
+ test_files: []