usable 3.7.1 → 3.9.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0a5a38c4e6b7ce12dc8babbb63d9c8ebfca63619
4
- data.tar.gz: 3657c1890f435d920a0e08429956f728fec8b330
2
+ SHA256:
3
+ metadata.gz: bcc17af85e47b938b6f6f86196d7a1a244e062ac1e7c77c4b6260138c18d9bdb
4
+ data.tar.gz: d800dcd7e7d2cff57ba7f2d96e5168a388b503ae480b83980d67286b55d7d970
5
5
  SHA512:
6
- metadata.gz: 9581e053956c78d748cb59431395d569d059b52f5682834a2834ac53d136ca1b55561852bebf6626e1bcddc6dfd697c8890209df11d17a5040e4a6766cf8c9ec
7
- data.tar.gz: b8b305ed5e491828febd8f68b0767bbed70425636b5196609700578a04c275103d7945ea0630730d04eb8d5b3cec97ae6a58adcdf705ae47f9868f53248ff6cd
6
+ metadata.gz: 2c03ec68bf89ff9e4b9ac0d72e2a5a72b7977375169957ae4873462a3e77c68aa01bb91afd7d18415113c5f50c58e00648292ca6932c81849ddea5dab90858a0
7
+ data.tar.gz: e631aece8d224022d1d07c4e777d978111e987bb5a803ed9ea4309701ee553adf11ca516e77f02312a2523a53510ae7dfd699a84590de3027d9c3df470d3c404
data/lib/usable.rb CHANGED
@@ -88,6 +88,15 @@ module Usable
88
88
  super
89
89
  end
90
90
 
91
+ def define_usable_accessors
92
+ usables.to_h.keys.each do |key|
93
+ define_singleton_method(key) { usables.send(key) }
94
+ define_singleton_method("#{key}=") { |new_val| usables.send("#{key}=", new_val) }
95
+ define_method(key) { usables.send(key) }
96
+ define_method("#{key}=") { |new_val| usables.send("#{key}=", new_val) }
97
+ end
98
+ end
99
+
91
100
  def usables
92
101
  @usables ||= Config.new
93
102
  end
@@ -113,11 +122,14 @@ module Usable
113
122
  # @return self
114
123
  def usable(*args, &block)
115
124
  options = args.last.is_a?(Hash) ? args.pop : {}
125
+ only = options.delete(:only)
126
+ extension_method = options.delete(:method)
116
127
  args.each do |mod|
117
- ModExtender.new(mod, only: options.delete(:only), method: options.delete(:method)).call self
128
+ ModExtender.new(mod, only: only, method: extension_method).call self
118
129
  # Define settings on @usables and on the scoped @usables
119
130
  scope = Config.new
120
- if mod.name
131
+ # Nest the new config under a namespace based on it's name, unless it's the default name we gave
132
+ if mod.name && !mod.name.include?("UsableMod")
121
133
  scope_name = mod.name.split('::').last.gsub(/\B([A-Z])([a-z_0-9])/, '_\1\2').downcase
122
134
  usables[scope_name] = scope
123
135
  end
data/lib/usable/config.rb CHANGED
@@ -30,8 +30,12 @@ module Usable
30
30
  @spec.to_h.each(&block)
31
31
  end
32
32
 
33
+ # @note The @spec[key] could already be set in cases where the config was merged with another
34
+ # For example, a usable module defines a default with a block, and when mounting the module
35
+ # the same usable option is overridden as an options hash (usable mod, key: 'val')
33
36
  def to_h
34
- @lazy_loads.each { |key| @spec[key] = call_spec_method(key) }
37
+ @lazy_loads.each { |key| @spec[key] ||= @spec.public_send(key) }
38
+ @lazy_loads.clear
35
39
  @spec.to_h
36
40
  end
37
41
 
@@ -43,10 +47,22 @@ module Usable
43
47
  to_h.merge(other)
44
48
  end
45
49
 
50
+ # @param other [Hash] to update ourselves with
51
+ def merge!(other)
52
+ other.each do |key, val|
53
+ @spec[key] = val
54
+ end
55
+ self
56
+ end
57
+
58
+ def include?(key)
59
+ !!@spec[key] || @lazy_loads.include?(key.to_sym)
60
+ end
61
+
46
62
  def method_missing(key, *args, &block)
47
63
  if block
48
64
  @lazy_loads << key
49
- @spec.define_singleton_method(key) { yield }
65
+ @spec.define_singleton_method(key, &block)
50
66
  else
51
67
  # Needs to be a symbol so we can consistently access @lazy_loads
52
68
  key = key.to_s.tr('=', '').to_sym
@@ -55,10 +71,10 @@ module Usable
55
71
  # Cleanup, just in case we loaded it another way (e.g. combining with another usable config)
56
72
  @lazy_loads.delete key
57
73
  else
58
- @spec[key] = call_spec_method(key)
74
+ @spec[key] = call_spec_method(key) unless frozen?
59
75
  end
60
76
  # Define method so we don't hit method missing again
61
- define_singleton_method(key) { @spec[key] }
77
+ define_singleton_method(key) { @spec[key] } unless frozen?
62
78
  @spec[key]
63
79
  else
64
80
  @spec[key] = args.first
@@ -18,9 +18,7 @@ module Usable
18
18
  # @description Directly include a module whose methods you want made available in +usables.available_methods+
19
19
  # Gives the module a name when including so that it shows up properly in the list of ancestors
20
20
  def call(target)
21
- unwanted.each do |method_name|
22
- copy.send :remove_method, method_name
23
- end
21
+ unwanted.each(&method(:remove_from_module))
24
22
  if copy.name.nil?
25
23
  const_name = "#{mod_name}Used"
26
24
  target.send :remove_const, const_name if target.const_defined? const_name, false
@@ -46,5 +44,16 @@ module Usable
46
44
  @copy.instance_methods - Array(only)
47
45
  end
48
46
  end
47
+
48
+ def remove_from_module(method_name)
49
+ begin
50
+ copy.send :remove_method, method_name
51
+ rescue NameError => e
52
+ # Expected sometimes, like it could be raised trying to remove a superclass method
53
+ Usable.logger.debug("#{e.class}: #{e.message}")
54
+ end
55
+ # Block access to superclass method, and prevent it from being copied to the target
56
+ copy.send :undef_method, method_name if copy.instance_methods.include?(method_name)
57
+ end
49
58
  end
50
59
  end
@@ -0,0 +1,82 @@
1
+ require 'fileutils'
2
+ require 'yaml'
3
+
4
+ module Usable
5
+ module Persistence
6
+ # = Stores usables in a yaml file
7
+
8
+ extend Usable
9
+
10
+ config do
11
+ dir { defined?(Rails) ? Rails.root.join('tmp') : File.expand_path('..', __FILE__) }
12
+ end
13
+
14
+ def self.extended(base)
15
+ base.extend Usable
16
+ base.usable self
17
+ end
18
+
19
+ # Automatically copied over by +usable+
20
+ module InstanceMethods
21
+ # Accessor to read and write default ActiveRecord objects
22
+ # When assigning a config, a reference to it is saved to tmp/<mod_name>.yml
23
+ # and loaded in subsequent console sessions
24
+ def method_missing(name, *args, &block)
25
+ if block
26
+ usables.public_send(name, &block)
27
+ elsif name.to_s.end_with?('=') && args.length == 1
28
+ _save name.to_s.tr('=', '').to_sym, args.pop
29
+ elsif usables[name]
30
+ usables[name]
31
+ elsif _config[name]
32
+ usables[name] = if _config[name].is_a?(Hash)
33
+ _config[name].fetch(:class).constantize.find(_config[name].fetch(:id))
34
+ else
35
+ _config[name]
36
+ end
37
+ else
38
+ usables.public_send(name) || super
39
+ end
40
+ end
41
+
42
+ def has?(setting)
43
+ !!send(setting)
44
+ rescue NoMethodError => e
45
+ if e.message.include?("method `#{setting}'")
46
+ false
47
+ else
48
+ raise
49
+ end
50
+ end
51
+
52
+ #
53
+ # Private
54
+ #
55
+
56
+ def _save(key, val = nil)
57
+ if val.nil?
58
+ _config.delete(key)
59
+ elsif val.respond_to?(:persisted?) && val.persisted?
60
+ _config[key] = { class: val.class.name, id: val.id }
61
+ else
62
+ _config[key] = val
63
+ end
64
+ File.open(_config_file, 'wb') { |f| f.puts _config.to_yaml }
65
+ usables[key] = val
66
+ end
67
+
68
+ def _config_file
69
+ return @_config_file if @_config_file
70
+ FileUtils.mkdir_p(usables.dir) unless File.directory?(usables.dir)
71
+ filename = self.class.name ? self.class.name.downcase.gsub('::', '_') : 'usable'
72
+ @_config_file = File.join(usables.dir, "#{filename}.yml")
73
+ FileUtils.touch(@_config_file) unless File.exists?(@_config_file)
74
+ @_config_file
75
+ end
76
+
77
+ def _config
78
+ @_config ||= YAML.load_file(_config_file) || {}
79
+ end
80
+ end
81
+ end
82
+ end
data/lib/usable/struct.rb CHANGED
@@ -2,10 +2,9 @@ module Usable
2
2
  def self.Struct(attributes = {})
3
3
  Class.new do
4
4
  extend Usable
5
-
6
5
  self.usables = Usable::Config.new(attributes)
7
-
8
- attributes.keys.each do |key|
6
+ define_usable_accessors
7
+ attributes.keys.map(&:to_sym).each do |key|
9
8
  define_method(key) { @attrs[key] }
10
9
  define_method("#{key}=") { |new_val| @attrs[key] = new_val }
11
10
  end
@@ -15,6 +14,30 @@ module Usable
15
14
  def initialize(attrs = {})
16
15
  @attrs = usables.merge(attrs)
17
16
  end
17
+
18
+ def [](key)
19
+ @attrs[key]
20
+ end
21
+
22
+ def []=(key, val)
23
+ @attrs[key] = val
24
+ end
25
+
26
+ def each(&block)
27
+ @attrs.each(&block)
28
+ end
29
+
30
+ def to_h
31
+ @attrs.dup
32
+ end
33
+
34
+ alias to_hash to_h
35
+
36
+ def merge(other)
37
+ to_h.merge!(other)
38
+ end
39
+
40
+ alias + merge
18
41
  end
19
42
  end
20
43
  end
@@ -1,3 +1,3 @@
1
1
  module Usable
2
- VERSION = "3.7.1".freeze
2
+ VERSION = "3.9.3".freeze
3
3
  end
data/usable.gemspec CHANGED
@@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.required_ruby_version = '>= 2.0.0'
23
23
 
24
- spec.add_development_dependency 'bundler', '~> 1.10'
25
- spec.add_development_dependency 'rake', '~> 10.0'
26
- spec.add_development_dependency 'rspec', '>= 3.2', '< 4'
24
+ spec.add_development_dependency "bundler", "~> 2.2.11"
25
+ spec.add_development_dependency "rake", ">= 12.3.3"
26
+ spec.add_development_dependency "rspec", ">= 3.2", "< 4"
27
27
  # spec.add_development_dependency 'rspec-scaffold', '>= 1.0', '< 2'
28
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usable
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.7.1
4
+ version: 3.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-04-03 00:00:00.000000000 Z
11
+ date: 2021-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
19
+ version: 2.2.11
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.10'
26
+ version: 2.2.11
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 12.3.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 12.3.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -71,6 +71,7 @@ files:
71
71
  - lib/usable/config_register.rb
72
72
  - lib/usable/eager_load.rb
73
73
  - lib/usable/mod_extender.rb
74
+ - lib/usable/persistence.rb
74
75
  - lib/usable/railtie.rb
75
76
  - lib/usable/struct.rb
76
77
  - lib/usable/version.rb
@@ -79,7 +80,7 @@ homepage: https://github.com/ridiculous/usable
79
80
  licenses:
80
81
  - MIT
81
82
  metadata: {}
82
- post_install_message:
83
+ post_install_message:
83
84
  rdoc_options: []
84
85
  require_paths:
85
86
  - lib
@@ -94,9 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
95
  - !ruby/object:Gem::Version
95
96
  version: '0'
96
97
  requirements: []
97
- rubyforge_project:
98
- rubygems_version: 2.6.8
99
- signing_key:
98
+ rubygems_version: 3.2.11
99
+ signing_key:
100
100
  specification_version: 4
101
101
  summary: Mounts and configures modules
102
102
  test_files: []