usable 3.3.0 → 3.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37d7979f36f818a019b5e938f9271a09021d8740
4
- data.tar.gz: 52f7607ba637d7e1e50c2423797c0680c390af47
3
+ metadata.gz: eb11e2617182a394ba2fcf207926152e7cb93606
4
+ data.tar.gz: 2d7c5698ddd7a8984a791c29cad205f65a0ab6ab
5
5
  SHA512:
6
- metadata.gz: be661c7880726a1fd3235c88c6ac27218f5ed88dad72088ee72da40493ba54208e71743c8951c424095936249a09c2c8db329f262e781be683088d6a4fa0d7bf
7
- data.tar.gz: d074eea1d75951eaf494de6680a94d2cea4f721324570ef50a39c147276fedf85adac77ca5c464cc9d46a1e99a6a6a4d6281e992573196b8f2536affcdde4f6d
6
+ metadata.gz: 7d0835d8eff617914a7968af009e307804f638191f7025dc06a54bd8b89cdf205ea2c13a14ac92de4471f96e91ebfc1d8990d08df5ea78f5d33a42d1c7f05546
7
+ data.tar.gz: 485649445fcbc569624de03000756b61fe972686432d14c6b67db88b3f8988afc1db0109f1e6750f56b7f6c5f68b4aafeb23873b45218dc78cbf181f4aaa905b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ 3.4.0 (12/22/2016)
2
+ ==================
3
+
4
+ * FIX - Copying usable attributes from a module to class/module works as expected
5
+ * NEW - Pass `only: :constants` when mounting a module to import just the constants from a module
6
+
1
7
  3.3.0 (12/4/2016)
2
8
  =================
3
9
 
data/README.md CHANGED
@@ -3,7 +3,17 @@
3
3
  Usable provides an elegant way to mount and configure your modules. Class level settings can be configured on a per module basis,
4
4
  available to both the module and including class. Allows you to include only the methods you want.
5
5
 
6
- Configure a module to be usable
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'usable'
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ Configure a module to have "usable" defaults:
7
17
  ```ruby
8
18
  module VersionMixin
9
19
  extend Usable
@@ -24,7 +34,7 @@ module VersionMixin
24
34
  end
25
35
  ```
26
36
 
27
- Include the module into a class using `usable`, which will copy over any configuration options
37
+ Include the module into a class using `usable`, which will copy over the configs:
28
38
  ```ruby
29
39
  class Model
30
40
  extend Usable
@@ -118,15 +128,32 @@ So Usable gives the modified module a name, which is the same name as the origin
118
128
  Mixin => MixinUsed
119
129
  ```
120
130
 
121
- ## Installation
131
+ ## Tips and Tricks
122
132
 
123
- Add this line to your application's Gemfile:
133
+ #### __3.4__ _-(unreleased)_
134
+
135
+ Import just a module's constants:
124
136
 
125
137
  ```ruby
126
- gem 'usable'
138
+ usable ExampleMod, only: :constants
127
139
  ```
128
140
 
129
- ## Tips and Tricks
141
+ Currently works with `usable ExampleMod, only: []` since version 2.0
142
+
143
+ #### __since version 3.3__ _- (not required)_
144
+ The `Usable::Struct` function is available for creating value objects with defaults. If you `require "usable/struct"` the
145
+ class function is available to create classes:
146
+
147
+ ```ruby
148
+ class Route < Usable::Struct(paths: %w[api v2 v3])
149
+ end
150
+
151
+ Route.usables.to_h # => {:paths=>["api", "v2", "v3"]}
152
+ Route.new.paths # => ["api", "v2", "v3"]
153
+ Route.new(paths: nil).paths # => nil
154
+ ```
155
+
156
+ #### __since version 2.0__
130
157
 
131
158
  When usable modules define the same config setting, the last one mounted takes precedence. Fortunately,
132
159
  Usable also "stacks" config settings by namespacing them:
@@ -156,12 +183,6 @@ User.usables.human.speak # => "Hello"
156
183
  User.usables.robot.speak # => "beep bop"
157
184
  ```
158
185
 
159
- Import just a module's constants with this little trick:
160
-
161
- ```ruby
162
- usable ExampleMod, only: []
163
- ```
164
-
165
186
  ## Development
166
187
 
167
188
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/bin/console CHANGED
@@ -3,6 +3,7 @@
3
3
  require "bundler/setup"
4
4
  require "usable"
5
5
  require "usable/struct"
6
+ require "byebug"
6
7
  require "irb"
7
8
 
8
9
  # You can add fixtures and/or initialization code here to make experimenting
@@ -78,4 +79,21 @@ end
78
79
 
79
80
  Model.usable PersistenceOverride, method: 'prepend'
80
81
 
82
+ def run_tests(subject)
83
+ if subject.usables.instance_variable_get(:@lazy_loads).to_a != [:model]
84
+ puts "Test @lazy_loads FAILED! Expected: #{[:model]}, Actual: #{subject.usables.instance_variable_get(:@lazy_loads)}"
85
+ end
86
+ if subject.usables.model != Model
87
+ puts "Test #model FAILED! Expected: #{Model}, Actual: #{subject.usables.model}"
88
+ end
89
+ if subject.usables.max_versions != 10
90
+ puts "Test #max_version FAILED! Expected: #{10}, Actual: #{subject.usables.max_versions}"
91
+ end
92
+ if subject.usables.model.new.save != 'nope'
93
+ puts "Test #save FAILED! Expected: 'nope', Actual: #{subject.usables.model.new.save}"
94
+ end
95
+ end
96
+
97
+ run_tests Example
98
+
81
99
  IRB.start
data/lib/usable/config.rb CHANGED
@@ -8,6 +8,7 @@ module Usable
8
8
  include ConfigRegister
9
9
  include ConfigMulti
10
10
 
11
+ # @todo Maybe keep a list of all attributes (lazy and regular)?
11
12
  def initialize(attributes = {})
12
13
  @spec = OpenStruct.new(attributes)
13
14
  @lazy_loads = Set.new
@@ -42,17 +43,23 @@ module Usable
42
43
  end
43
44
 
44
45
  def method_missing(key, *args, &block)
46
+ # @attributes << key.to_s
45
47
  if block
46
48
  @lazy_loads << key
47
- # @attributes << key.to_s
48
49
  @spec.define_singleton_method(key) { yield }
49
50
  else
50
- key = key.to_s.tr('=', '')
51
- # @attributes << key
51
+ # Needs to be a symbol so we can consistently access @lazy_loads
52
+ key = key.to_s.tr('=', '').to_sym
52
53
  if args.empty?
53
- value = @spec[key] ||= call_spec_method(key)
54
+ if @spec[key]
55
+ # Cleanup, just in case we loaded it another way (e.g. combining with another usable config)
56
+ @lazy_loads.delete key
57
+ else
58
+ @spec[key] = call_spec_method(key)
59
+ end
60
+ # Define method so we don't hit method missing again
54
61
  define_singleton_method(key) { @spec[key] }
55
- value
62
+ @spec[key]
56
63
  else
57
64
  @spec[key] = args.first
58
65
  end
@@ -1,17 +1,19 @@
1
1
  module Usable
2
2
  module ConfigMulti
3
3
  # It's important to define all block specs we need to lazy load
4
- # Set block specs to nil values so it will fallback to calling the underlying singleton method defined by Config#method_missing
5
4
  def +(other)
6
5
  config = clone
7
6
  specs = other.spec.to_h
8
7
  specs.each { |key, val| config[key] = val }
9
- methods = other.spec.singleton_methods - specs.keys
8
+ methods = other.spec.singleton_methods
9
+ methods.map! { |name| name.to_s.tr('=', '').to_sym }
10
+ methods.uniq!
11
+ methods -= specs.keys
10
12
  methods.each do |name|
11
- config.spec[name] = nil
12
13
  config.spec.define_singleton_method(name) do
13
14
  other.spec.public_method(name).call
14
15
  end
16
+ config.instance_variable_get(:@lazy_loads) << name
15
17
  end
16
18
  config
17
19
  end
@@ -9,7 +9,7 @@ module Usable
9
9
  @options[:method] ||= :include
10
10
  @copy = mod
11
11
  @name = mod.name
12
- @unwanted = options[:only] ? @copy.instance_methods - Array(options[:only]) : []
12
+ @unwanted = find_unwanted_methods(options[:only])
13
13
  if @unwanted.any?
14
14
  @copy = @copy.dup
15
15
  end
@@ -37,5 +37,14 @@ module Usable
37
37
  "UsableMod#{Time.now.strftime('%s')}"
38
38
  end
39
39
  end
40
+
41
+ def find_unwanted_methods(only)
42
+ return [] unless only
43
+ if :constants == only
44
+ @copy.instance_methods
45
+ else
46
+ @copy.instance_methods - Array(only)
47
+ end
48
+ end
40
49
  end
41
50
  end
@@ -1,3 +1,3 @@
1
1
  module Usable
2
- VERSION = "3.3.0".freeze
2
+ VERSION = "3.4.0".freeze
3
3
  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.3.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Buckley
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-05 00:00:00.000000000 Z
11
+ date: 2016-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler