usable 3.7.1 → 3.9.3

Sign up to get free protection for your applications and to get access to all the features.
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: []