ruby_utils 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9d43510375fc15c6420ccfadbfebba96d7e0727a
4
+ data.tar.gz: c7065fb2cb96f74f6101ee62d75b6c1414e6c882
5
+ SHA512:
6
+ metadata.gz: 63c5a576af4dbc6b3ce10b9103d03993e23dbe8989ae357b0c8f2f51714cd1f594e9462f86af4d2c4875a3d986206989c04227888799dfcd0b28ee2ae51b1578
7
+ data.tar.gz: 44ff4f5a46fdce4b0ec0819e1351456e1665fc696220116b915dbe3c7656a0176071e71d50e9218b71ea5d5c7b3c86826b407c824b3108b7492531f8cddf8bce
@@ -0,0 +1,59 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+ /.bundle/
52
+ /.yardoc
53
+ /Gemfile.lock
54
+ /_yardoc/
55
+ /coverage/
56
+ /doc/
57
+ /pkg/
58
+ /spec/reports/
59
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.3
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Laertis
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 all
13
+ 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 THE
21
+ SOFTWARE.
@@ -0,0 +1,33 @@
1
+ # ruby-utils
2
+
3
+ Various ruby core extensions and class utilities.
4
+
5
+ ## Status
6
+ TBD
7
+
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'ruby-utils'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install hanami-utils
24
+
25
+ ## Usage
26
+ TBD
27
+
28
+
29
+ ## Features
30
+
31
+ ### Ruby::Utils::Param
32
+
33
+ ### Ruby::Utils::Hash
@@ -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 "ruby_utils"
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
@@ -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,13 @@
1
+ require "ruby_utils/version"
2
+ require 'ruby_utils/param'
3
+ require 'ruby_utils/core_ext/hash'
4
+
5
+ module Ruby
6
+ module Utils
7
+
8
+ module_function
9
+ def Param(original = {})
10
+ Param.new(original || {})
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ class Hash
2
+ def deep_fetch *args, &block
3
+ raise ArgumentError.new("wrong number of arguments (0 for 1..n)") if args.empty?
4
+
5
+ value = fetch(args.shift, &block)
6
+ if args.size > 0
7
+ if value.kind_of?(Hash)
8
+ value.deep_fetch(*args, &block)
9
+ elsif value.kind_of?(Array)
10
+ value = value[args.shift]
11
+ if args.size > 0
12
+ value.deep_fetch(*args, &block)
13
+ else
14
+ value
15
+ end
16
+ else
17
+ {}.fetch(args.shift, &block)
18
+ end
19
+ else
20
+ value
21
+ end
22
+ end
23
+ end
24
+
25
+
@@ -0,0 +1,216 @@
1
+ module Ruby::Utils
2
+ class Param
3
+ def initialize(hash = {})
4
+ @original_hash = hash
5
+
6
+ define_methods(@original_hash)
7
+ end
8
+
9
+ def define_methods(h)
10
+ h.each do |k, v|
11
+ h.define_singleton_method(k) do
12
+ v
13
+ end
14
+
15
+ define_methods(v) if v.is_a?(Hash)
16
+ end
17
+ end
18
+
19
+ def respond_to?(name)
20
+ if @original_hash.respond_to?(name)
21
+ true
22
+ else
23
+ super
24
+ end
25
+ end
26
+
27
+ def method_missing(name, *args, &block)
28
+ if @original_hash.respond_to?(name)
29
+ @original_hash.send(name)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ # Returns the value of the hash given a delimited key
36
+ # If not key is found an error is raised
37
+ #
38
+ # @param[String] key A delimited string key to find the value of the hash
39
+ #
40
+ # @return [Object, Exception] Exception if no key is found or else the value
41
+ #
42
+ # => params.get(".poll.user.profile.email")
43
+ #
44
+ def get(key)
45
+ methods = key.scan(/[\w'-]+/)
46
+ _get(methods, self)
47
+ end
48
+
49
+ def _get(methods, obj)
50
+ current = methods.shift
51
+ res = obj.send(current)
52
+
53
+ return res if methods.empty?
54
+ _get(methods, res)
55
+ end
56
+ private :_get
57
+
58
+ # Get a value from hash. If it's not set, return default value. If default value
59
+ # is not provided, return nil. Never throw exception.
60
+ #
61
+ # ex:
62
+ # params.getOrElse(":user:location:address", "Street address") # => "Betonimiehenkuja 5"
63
+ # params.getOrElse(":user:location:zipcode", "00000") # => "00000"
64
+ # params.getOrElse(":user:location:zipcode", params.getOrElse(":user:location:address", "N/A")) # => "Betonimiehenkuja 5"
65
+ #
66
+ # TODO Add more args for fallbacks:
67
+ #
68
+ # getOrElse(locator, [fallback_locator_1, ... , fallback_locator_n], default)]
69
+ # params.getOrElse(":user:location:zipcode", ":user:location:address", "N/A") # => "Betonimiehenkuja 5"
70
+ # params.getOrElse(":user:location:zipcode", ":user:location:state", "N/A") # => "N/A"
71
+ # params.getOrElse(":user:location:zipcode", ":user:location:state", ":user:location:country", "N/A") # => "Finland"
72
+ #
73
+ def getOrElse(locator, default=nil)
74
+ get(locator)
75
+ rescue NoMethodError
76
+ default
77
+ end
78
+
79
+ # Get a value from hash and map the value with block.
80
+ # If value is not set, do nothing.
81
+ #
82
+ # => mappedParams = params.map(":user:location:city", &:upcase)
83
+ # => mappedParams.get(:city) # => "HELSINKI"
84
+ def map(key, &block)
85
+ result = getOrElse(key)
86
+ block.call(result) if result
87
+ end
88
+
89
+ def map_keys(h, &block)
90
+ Hash[h.map { |(k, v)| [block.call(k), v] }]
91
+ end
92
+
93
+ def map_values(h, &block)
94
+ h.inject({}) do |memo, (k, v)|
95
+ memo[k] = block.call(v)
96
+ memo
97
+ end
98
+ end
99
+
100
+ # Select a subset of the hash h using given set of keys.
101
+ # Only include keys that are present in h.
102
+ # Usage:
103
+ # sub({first: "First", last: "Last", age: 55}, :first, :age, :sex)
104
+ # => {first: "First", age: 55}
105
+ def sub(h, *keys)
106
+ keys.reduce({}) do |sub_hash, k|
107
+ sub_hash[k] = h[k] if h.has_key?(k)
108
+ sub_hash
109
+ end
110
+ end
111
+
112
+ # Select values by given keys from array of hash
113
+ # Usage:
114
+ # pluck([{name: "John", age: 15}, {name: "Joe"}], :name, :age) => ["John", "Joe", 15]
115
+ def pluck(array_of_hashes, *keys)
116
+ array_of_hashes.map { |h|
117
+ keys.map { |key| h[key] }
118
+ }.flatten.compact
119
+ end
120
+
121
+ # Return true if given subset of fields in both hashes are equal
122
+ # Usage:
123
+ # suq_eq({a: 1, b: 2, c: 3}, {a: 1, b: 2, c: 4}, :a, :b) => true
124
+ def sub_eq(a, b, *keys)
125
+ a.slice(*keys) == b.slice(*keys)
126
+ end
127
+
128
+ # deep_contains({a: 1}, {a: 1, b: 2}) => true
129
+ # deep_contains({a: 2}, {a: 1, b: 2}) => false
130
+ # deep_contains({a: 1, b: 1}, {a: 1, b: 2}) => false
131
+ # deep_contains({a: 1, b: 2}, {a: 1, b: 2}) => true
132
+ def deep_contains(needle, haystack)
133
+ needle.all? do |key, val|
134
+ haystack_val = haystack[key]
135
+ if val.is_a?(Hash) && haystack_val.is_a?(Hash)
136
+ deep_contains(val, haystack_val)
137
+ else
138
+ val == haystack_val
139
+ end
140
+ end
141
+ end
142
+
143
+ # wrap_if_present(:wrap, {a: 1}} -> {wrap: {a: 1}}
144
+ # wrap_if_present(:wrap, {}} -> {}
145
+ # wrap_if_present(:wrap, nil) -> {}
146
+ def wrap_if_present(key, value)
147
+ Maybe(value).map { |v|
148
+ Hash[key, v]
149
+ }.or_else({})
150
+ end
151
+
152
+ # { a: b: 1 } -> { :"a.b" => 1 }"}
153
+ def flatten(h)
154
+ # use helper lambda
155
+ acc = ->(prefix, hash) {
156
+ hash.inject({}) { |memo, (k, v)|
157
+ key_s = k.to_s
158
+ if !k.is_a?(Symbol) || key_s.include?(".")
159
+ raise ArgumentError.new("Key must be a Symbol and must not contain dot (.). Was: '#{k.to_s}', (#{k.class.name})")
160
+ end
161
+ prefixed_key = prefix.nil? ? k : [prefix.to_s, key_s].join(".")
162
+ if v.is_a? Hash
163
+ memo.merge(acc.call(prefixed_key, v))
164
+ else
165
+ memo.merge(prefixed_key.to_sym => v)
166
+ end
167
+ }
168
+ }
169
+
170
+ acc.call(nil, h)
171
+ end
172
+
173
+ # p = Person.new({name: "Foo", email: "foo@example.com"})
174
+ # object_to_hash(p) => {name: "Foo" , email: "foo@example.com"}
175
+ def object_to_hash(object)
176
+ object.instance_variables.inject({}) do |hash, var|
177
+ hash[var.to_s.delete("@")] = object.instance_variable_get(var)
178
+ hash
179
+ end
180
+ end
181
+
182
+ # Return true if the value is set.
183
+ #
184
+ # has_address = params.defined?(":user:location:address")
185
+ # has_address # => true
186
+ #
187
+ def defined?(locator)
188
+ !getOrElse(locator).nil?
189
+ end
190
+
191
+ # Return true if all of the values are set.
192
+ #
193
+ # can_show_fullname = params.all?(":user:name:first", ":user:name:last")
194
+ #
195
+ def all?(*locators)
196
+ locators.all? { |locator| getOrElse(locator) }
197
+ end
198
+
199
+ # Run a given block only if value is defined.
200
+ #
201
+ # params.with(":user:location:address") { |address| puts "Address: #{address}"} } # => "Address: Betonimiehenkuja 5"
202
+ # params.with(":user:location:city") { |city| puts "City: #{}"}
203
+ #
204
+ def with(key, &block)
205
+ result = getOrElse(key)
206
+ yield(result) if result
207
+ end
208
+
209
+ def to_h
210
+ @original_hash
211
+ end
212
+ alias_method :to_hash, :to_h
213
+ alias_method :as_hash, :to_h
214
+ end # End Param
215
+ end
216
+
@@ -0,0 +1,5 @@
1
+ module Ruby
2
+ module Utils
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruby_utils/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ruby_utils"
8
+ spec.version = Ruby::Utils::VERSION
9
+ spec.authors = ["Laertis Pappas"]
10
+ spec.email = ["laertis.pappas@gmail.com"]
11
+
12
+ spec.summary = %q{Ruby core extensions and class utilities}
13
+ spec.description = %q{Ruby core extensions and class utilities}
14
+ spec.homepage = "https://www.github.com/laertispappas/ruby_utils"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.12"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec", "~> 3.0"
32
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Laertis Pappas
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-11-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: Ruby core extensions and class utilities
56
+ email:
57
+ - laertis.pappas@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rspec"
64
+ - ".travis.yml"
65
+ - Gemfile
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - bin/console
70
+ - bin/setup
71
+ - lib/ruby_utils.rb
72
+ - lib/ruby_utils/core_ext/hash.rb
73
+ - lib/ruby_utils/param.rb
74
+ - lib/ruby_utils/version.rb
75
+ - ruby_utils.gemspec
76
+ homepage: https://www.github.com/laertispappas/ruby_utils
77
+ licenses: []
78
+ metadata:
79
+ allowed_push_host: https://rubygems.org
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.4.5.1
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Ruby core extensions and class utilities
100
+ test_files: []
101
+ has_rdoc: