fusu 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/fusu.rb +2 -0
- data/lib/fusu/array.rb +17 -0
- data/lib/fusu/blank.rb +4 -0
- data/lib/fusu/configurable.rb +146 -0
- data/lib/fusu/hash.rb +8 -0
- data/lib/fusu/ordered_options.rb +83 -0
- data/lib/fusu/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: abe9860bb714eb06dff8a1df416ee4002883d1f74a66166eb9ca61331f10cf35
|
4
|
+
data.tar.gz: 0472026d1cc75b37592ad0d61618c4e7dc3c1bc2711a8a73c1761fa3f95ac213
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a6b3ff3d19907727179ec8fe2646b3e88eb1047f4e90423bad354766e07c464e4b909807f9d75b05c9ad1359e1af4f5ee1e62359ea2a5ed35560f9f8122e9e5
|
7
|
+
data.tar.gz: db21445a5c0d8d4aa3f351f9ba42bcde5d293fd9a37bddac66f350ace8678fac0ab0bd54de3e3763fc07e296e0ba77beebd898887db6037c6facaa55b9f076eb
|
data/lib/fusu.rb
CHANGED
data/lib/fusu/array.rb
CHANGED
@@ -9,5 +9,22 @@ module Fusu
|
|
9
9
|
[object]
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
# Extracts options from a set of arguments. Removes and returns the last
|
14
|
+
# element in the array if it's a hash, otherwise returns a blank hash.
|
15
|
+
#
|
16
|
+
# def options(*args)
|
17
|
+
# args.extract_options!
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# options(1, 2) # => {}
|
21
|
+
# options(1, 2, a: :b) # => {:a=>:b}
|
22
|
+
def self.extract_options!(ary)
|
23
|
+
if ary.last.is_a?(::Hash) && Fusu::Hash.extractable_options?(ary.last)
|
24
|
+
ary.pop
|
25
|
+
else
|
26
|
+
{}
|
27
|
+
end
|
28
|
+
end
|
12
29
|
end
|
13
30
|
end
|
data/lib/fusu/blank.rb
CHANGED
@@ -0,0 +1,146 @@
|
|
1
|
+
require "fusu/concern"
|
2
|
+
require "fusu/ordered_options"
|
3
|
+
|
4
|
+
module Fusu
|
5
|
+
# Configurable provides a <tt>config</tt> method to store and retrieve
|
6
|
+
# configuration options as an <tt>OrderedHash</tt>.
|
7
|
+
module Configurable
|
8
|
+
extend Fusu::Concern
|
9
|
+
|
10
|
+
class Configuration < Fusu::InheritableOptions
|
11
|
+
def compile_methods!
|
12
|
+
self.class.compile_methods!(keys)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Compiles reader methods so we don't have to go through method_missing.
|
16
|
+
def self.compile_methods!(keys)
|
17
|
+
keys.reject { |m| method_defined?(m) }.each do |key|
|
18
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
19
|
+
def #{key}; _get(#{key.inspect}); end
|
20
|
+
RUBY
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
def config
|
27
|
+
@_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
|
28
|
+
superclass.config.inheritable_copy
|
29
|
+
else
|
30
|
+
# create a new "anonymous" class that will host the compiled reader methods
|
31
|
+
Class.new(Configuration).new
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def configure
|
36
|
+
yield config
|
37
|
+
end
|
38
|
+
|
39
|
+
# Allows you to add shortcut so that you don't have to refer to attribute
|
40
|
+
# through config. Also look at the example for config to contrast.
|
41
|
+
#
|
42
|
+
# Defines both class and instance config accessors.
|
43
|
+
#
|
44
|
+
# class User
|
45
|
+
# include Fusu::Configurable
|
46
|
+
# config_accessor :allowed_access
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# User.allowed_access # => nil
|
50
|
+
# User.allowed_access = false
|
51
|
+
# User.allowed_access # => false
|
52
|
+
#
|
53
|
+
# user = User.new
|
54
|
+
# user.allowed_access # => false
|
55
|
+
# user.allowed_access = true
|
56
|
+
# user.allowed_access # => true
|
57
|
+
#
|
58
|
+
# User.allowed_access # => false
|
59
|
+
#
|
60
|
+
# The attribute name must be a valid method name in Ruby.
|
61
|
+
#
|
62
|
+
# class User
|
63
|
+
# include Fusu::Configurable
|
64
|
+
# config_accessor :"1_Badname"
|
65
|
+
# end
|
66
|
+
# # => NameError: invalid config attribute name
|
67
|
+
#
|
68
|
+
# To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
|
69
|
+
# To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
|
70
|
+
#
|
71
|
+
# class User
|
72
|
+
# include Fusu::Configurable
|
73
|
+
# config_accessor :allowed_access, instance_reader: false, instance_writer: false
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# User.allowed_access = false
|
77
|
+
# User.allowed_access # => false
|
78
|
+
#
|
79
|
+
# User.new.allowed_access = true # => NoMethodError
|
80
|
+
# User.new.allowed_access # => NoMethodError
|
81
|
+
#
|
82
|
+
# Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods.
|
83
|
+
#
|
84
|
+
# class User
|
85
|
+
# include Fusu::Configurable
|
86
|
+
# config_accessor :allowed_access, instance_accessor: false
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# User.allowed_access = false
|
90
|
+
# User.allowed_access # => false
|
91
|
+
#
|
92
|
+
# User.new.allowed_access = true # => NoMethodError
|
93
|
+
# User.new.allowed_access # => NoMethodError
|
94
|
+
#
|
95
|
+
# Also you can pass a block to set up the attribute with a default value.
|
96
|
+
#
|
97
|
+
# class User
|
98
|
+
# include Fusu::Configurable
|
99
|
+
# config_accessor :hair_colors do
|
100
|
+
# [:brown, :black, :blonde, :red]
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
105
|
+
def config_accessor(*names)
|
106
|
+
options = Fusu::Array.extract_options!(names)
|
107
|
+
|
108
|
+
names.each do |name|
|
109
|
+
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
|
110
|
+
|
111
|
+
reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
|
112
|
+
writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
|
113
|
+
|
114
|
+
singleton_class.class_eval reader, __FILE__, reader_line
|
115
|
+
singleton_class.class_eval writer, __FILE__, writer_line
|
116
|
+
|
117
|
+
unless options[:instance_accessor] == false
|
118
|
+
class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false
|
119
|
+
class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false
|
120
|
+
end
|
121
|
+
send("#{name}=", yield) if block_given?
|
122
|
+
end
|
123
|
+
end
|
124
|
+
private :config_accessor
|
125
|
+
end
|
126
|
+
|
127
|
+
# Reads and writes attributes from a configuration <tt>OrderedHash</tt>.
|
128
|
+
#
|
129
|
+
# require 'fusu/configurable'
|
130
|
+
#
|
131
|
+
# class User
|
132
|
+
# include Fusu::Configurable
|
133
|
+
# end
|
134
|
+
#
|
135
|
+
# user = User.new
|
136
|
+
#
|
137
|
+
# user.config.allowed_access = true
|
138
|
+
# user.config.level = 1
|
139
|
+
#
|
140
|
+
# user.config.allowed_access # => true
|
141
|
+
# user.config.level # => 1
|
142
|
+
def config
|
143
|
+
@_config ||= self.class.config.inheritable_copy
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/lib/fusu/hash.rb
CHANGED
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fusu
|
4
|
+
# Usually key value pairs are handled something like this:
|
5
|
+
#
|
6
|
+
# h = {}
|
7
|
+
# h[:boy] = 'John'
|
8
|
+
# h[:girl] = 'Mary'
|
9
|
+
# h[:boy] # => 'John'
|
10
|
+
# h[:girl] # => 'Mary'
|
11
|
+
# h[:dog] # => nil
|
12
|
+
#
|
13
|
+
# Using +OrderedOptions+, the above code could be reduced to:
|
14
|
+
#
|
15
|
+
# h = ActiveSupport::OrderedOptions.new
|
16
|
+
# h.boy = 'John'
|
17
|
+
# h.girl = 'Mary'
|
18
|
+
# h.boy # => 'John'
|
19
|
+
# h.girl # => 'Mary'
|
20
|
+
# h.dog # => nil
|
21
|
+
#
|
22
|
+
# To raise an exception when the value is blank, append a
|
23
|
+
# bang to the key name, like:
|
24
|
+
#
|
25
|
+
# h.dog! # => raises KeyError: :dog is blank
|
26
|
+
#
|
27
|
+
class OrderedOptions < ::Hash
|
28
|
+
alias_method :_get, :[] # preserve the original #[] method
|
29
|
+
protected :_get # make it protected
|
30
|
+
|
31
|
+
def []=(key, value)
|
32
|
+
super(key.to_sym, value)
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](key)
|
36
|
+
super(key.to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(name, *args)
|
40
|
+
name_string = name.to_s
|
41
|
+
if name_string.chomp!("=")
|
42
|
+
self[name_string] = args.first
|
43
|
+
else
|
44
|
+
bangs = name_string.chomp!("!")
|
45
|
+
|
46
|
+
if bangs
|
47
|
+
Fusu.presence(self[name_string]) || raise(KeyError.new(":#{name_string} is blank"))
|
48
|
+
else
|
49
|
+
self[name_string]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def respond_to_missing?(name, include_private)
|
55
|
+
true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# +InheritableOptions+ provides a constructor to build an +OrderedOptions+
|
60
|
+
# hash inherited from another hash.
|
61
|
+
#
|
62
|
+
# Use this if you already have some hash and you want to create a new one based on it.
|
63
|
+
#
|
64
|
+
# h = ActiveSupport::InheritableOptions.new({ girl: 'Mary', boy: 'John' })
|
65
|
+
# h.girl # => 'Mary'
|
66
|
+
# h.boy # => 'John'
|
67
|
+
class InheritableOptions < OrderedOptions
|
68
|
+
def initialize(parent = nil)
|
69
|
+
if parent.kind_of?(OrderedOptions)
|
70
|
+
# use the faster _get when dealing with OrderedOptions
|
71
|
+
super() { |h, k| parent._get(k) }
|
72
|
+
elsif parent
|
73
|
+
super() { |h, k| parent[k] }
|
74
|
+
else
|
75
|
+
super()
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def inheritable_copy
|
80
|
+
self.class.new(self)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/fusu/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fusu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Artur Panyach
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -74,12 +74,14 @@ files:
|
|
74
74
|
- lib/fusu/array.rb
|
75
75
|
- lib/fusu/blank.rb
|
76
76
|
- lib/fusu/concern.rb
|
77
|
+
- lib/fusu/configurable.rb
|
77
78
|
- lib/fusu/hash.rb
|
78
79
|
- lib/fusu/hash/deep_merge.rb
|
79
80
|
- lib/fusu/hash/except.rb
|
80
81
|
- lib/fusu/hash/keys.rb
|
81
82
|
- lib/fusu/hash/reverse_merge.rb
|
82
83
|
- lib/fusu/hash_with_indifferent_access.rb
|
84
|
+
- lib/fusu/ordered_options.rb
|
83
85
|
- lib/fusu/regexp.rb
|
84
86
|
- lib/fusu/string.rb
|
85
87
|
- lib/fusu/string/methods.rb
|
@@ -105,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
107
|
version: '0'
|
106
108
|
requirements: []
|
107
109
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.
|
110
|
+
rubygems_version: 2.7.6
|
109
111
|
signing_key:
|
110
112
|
specification_version: 4
|
111
113
|
summary: Functional support
|