natural_born_slugger 0.1.0 → 0.2.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: c53161bfaee3307f0789e14966a1cef3def933f3
4
- data.tar.gz: b0d8d1d8e94fae0798e5ad1b6411d21ff50a18c0
3
+ metadata.gz: cf8a2e95a9e37528207d180abcfefda53ee8c4a2
4
+ data.tar.gz: 3b12053c7a01c7805a19750ed9eaa73082552fbb
5
5
  SHA512:
6
- metadata.gz: 4847802082fabbcb6f537d607f8cabf918fda7a258966c4ac0b43e9a7fe7a89794f1880a2b1a9918c800a80c1d9ab23c3fb15d2f0fca151b32eb6a5e1d443390
7
- data.tar.gz: b93c87ae94fec058f6dac6e6027cc5dde19ab2880a7d292dfd89f5eeca71cada422cc8fbc326a3acfb3755789c5469716190bc7ac0167d943ad2d063ead921fc
6
+ metadata.gz: 4e7781ec967dc3e89fca75c3a232e203cecd8098841ceecea00878a300353089fbef75c3a4889a06dd2b0beaa8eda0a9a1b5650d5c72bebf3ba23202cdacef76
7
+ data.tar.gz: 0fd95992883ed518d066ae9fbdf545466820556bd870c361e41c6dc25cc110775424f9b7cc7313b0e1535f15dd42db912be4ba9d555ea3d8333af2649be6c5aa
data/.rspec ADDED
@@ -0,0 +1,11 @@
1
+ # Autoload spec helper
2
+ --require spec_helper
3
+
4
+ # Show more colorful RSpec results
5
+ --color
6
+
7
+ # Verbose display
8
+ --format documentation
9
+
10
+ # Use full backtraces
11
+ -b
data/README.md CHANGED
@@ -116,22 +116,7 @@ The options hash is where you define the attribute's dependencies. It also uses
116
116
 
117
117
  bambino = Person.new('Babe', nil, 'Ruth')
118
118
  bambino.slug #=> "Babe-Ruth"
119
- ```
120
-
121
- ##### `:compact`
122
- - Removes nil dependencies before joining.
123
- - Default: true
124
- - Example: Notice the extra dash in the example below:
125
119
 
126
- ```
127
- Person = Struct.new(:first_name, :middle_name, :last_name) do
128
- include NaturalBornSlugger
129
- has_slug first_name: nil, middle_name: nil, last_name: nil, compact: false, join_with: '-'
130
- end
131
-
132
- bambino = Person.new('Babe', nil, 'Ruth')
133
- bambino.slug #=> "Babe--Ruth"
134
- ```
135
120
 
136
121
  ##### `:require_all`
137
122
  - Checks to make sure all attributes exist before composing attribute.
@@ -152,7 +137,7 @@ The options hash is where you define the attribute's dependencies. It also uses
152
137
  bambino.slug #=> "George-Herman-Ruth"
153
138
  ```
154
139
 
155
- ##### `:track`
140
+ ##### `:callback`
156
141
  - Provides a callback function `#{attribute_name}_change` to allow you to persist old slugs as you please.
157
142
  - Default: false
158
143
  - Example:
@@ -160,13 +145,12 @@ The options hash is where you define the attribute's dependencies. It also uses
160
145
  ```
161
146
  Person = Struct.new(:first_name, :middle_name, :last_name) do
162
147
  include NaturalBornSlugger
163
- has_slug first_name: nil, middle_name: nil, last_name: nil, track: true
164
-
165
148
  attr_accessor :formerly_known_as
166
- def slug_change(old_slug, new_slug)
167
- @formerly_known_as ||= []
168
- @formerly_known_as << old_slug
149
+ has_slug first_name: nil, middle_name: nil, last_name: nil, callback: ->(old_name, new_name) do
150
+ self.formerly_known_as ||= []
151
+ self.formerly_known_as << old_name
169
152
  end
153
+
170
154
  end
171
155
 
172
156
  bambino = Person.new('George', 'Herman', 'Ruth')
@@ -179,4 +163,4 @@ The options hash is where you define the attribute's dependencies. It also uses
179
163
 
180
164
  ##### _Note:_
181
165
 
182
- If you happen to have methods or attributes called `join_with`, `compact`, `require_all`, or `track`, you can still build composite attributes out of them. Just use a string instead of a symbol when declaring your attribute's dependencies. `NaturalBornSlugger` only looks for symbols when reading your dependencies for these settings.
166
+ If you happen to have methods or attributes called `join_with`, `require_all`, or `callback`, you can still build composite attributes out of them. Just use a string instead of a symbol when declaring your attribute's dependencies. `NaturalBornSlugger` only looks for symbols when reading your dependencies for these settings.
@@ -0,0 +1,116 @@
1
+ module NaturalBornSlugger
2
+ class AttributeComposer
3
+
4
+ def initialize(name, options)
5
+ @name = name.to_s
6
+ @dependencies, options = self.class.extract_dependencies_from_options(options)
7
+ options.each do |option, value|
8
+ self.instance_variable_set("@#{option}", value)
9
+ end
10
+ raise ConfigurationError.new(self.name, name, "no dependent attributes were specified") if @dependencies.empty?
11
+ end
12
+
13
+ def self.default_options
14
+ {
15
+ require_all: false,
16
+ join_with: '',
17
+ callback: false
18
+ }
19
+ end
20
+
21
+ def self.extract_dependencies_from_options(dependencies={})
22
+ options = default_options.dup
23
+ options.keys.each do |option|
24
+ if dependencies.has_key? option
25
+ options[option] = dependencies.delete(option)
26
+ end
27
+ end
28
+ [dependencies, options]
29
+ end
30
+
31
+ def self.resolve_dependency(object, dependency)
32
+ dependency_chain = dependency.to_s.split('.')
33
+ dependency_chain.each do |method|
34
+ object = object.try :send, method
35
+ break unless object
36
+ end
37
+ object
38
+ end
39
+
40
+
41
+ def compose_attribute(resolved_dependencies)
42
+ resolved_dependencies.map do |resolved_dependency, strategy|
43
+ case strategy
44
+ when Symbol # Symbols represent string methods to call on the resolved dependency
45
+ resolved_dependency.to_s.send(strategy)
46
+ when String # Strings represent formats to fit the resolved dependency into
47
+ strategy % resolved_dependency
48
+ when Regexp # Regexps represent patterns to pull out of the resolved dependency and join
49
+ resolved_dependency.scan(strategy).join(@join_with)
50
+ when Proc # Procs should take one parameter and return a string or nil
51
+ strategy.call(resolved_dependency)
52
+ else # If no strategy provided, use resolved dependency as is
53
+ resolved_dependency.to_s
54
+ end
55
+ # Remove nil components if `compact_dependencies` is true
56
+ end.reject{|string| not string or string.empty? }.join(@join_with)
57
+ end
58
+
59
+ def evaluate(object)
60
+ resolved_dependencies = @dependencies.map do |dependency, strategy|
61
+ [self.class.resolve_dependency(object, dependency), strategy]
62
+ end
63
+ # Check existence of all attribute dependencies if `require_all` is true
64
+ if @require_all ? resolved_dependencies.map(&:first).all? : true
65
+ compose_attribute(resolved_dependencies)
66
+ end
67
+ end
68
+
69
+ def callback(object, old_value, new_value)
70
+ if @callback
71
+ unless old_value == new_value
72
+ object.instance_exec old_value, new_value, &@callback
73
+ end
74
+ end
75
+ end
76
+
77
+ ##
78
+ # Adds composite attribute methods to the class:
79
+ # a getter, and updater method.
80
+ # Also adds a setter that either calls the updater
81
+ # or throws an error, depending on configuration
82
+ def add_to(klass)
83
+
84
+ class << klass
85
+ attr_accessor :composite_attributes
86
+ end
87
+ klass.composite_attributes ||= {}
88
+ klass.composite_attributes[@name] = self
89
+
90
+ # Define instance attribute getter
91
+ klass.send :define_method, @name do
92
+ name = __method__
93
+ self.send "update_#{name}"
94
+ end
95
+
96
+ # Define instance attribute setter: ignores assignment and just triggers an update
97
+ klass.send :define_method, "#{@name}=" do |value|
98
+ name = __method__.to_s.gsub '=', ''
99
+ self.send "update_#{name}"
100
+ end
101
+
102
+ # Update instance attribute
103
+ klass.send :define_method, "update_#{@name}" do
104
+ name = __method__.to_s.gsub 'update_', ''
105
+ composer = self.class.composite_attributes[name]
106
+ old_value = self.instance_variable_get("@#{name}")
107
+ new_value = composer.evaluate(self)
108
+ self.instance_variable_set("@#{name}", new_value)
109
+ composer.callback(self, old_value, new_value)
110
+ new_value
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+ end
@@ -1,3 +1,5 @@
1
+ require "natural_born_slugger/attribute_composer"
2
+
1
3
  module NaturalBornSlugger
2
4
  module ClassMethods
3
5
 
@@ -7,8 +9,7 @@ module NaturalBornSlugger
7
9
  def has_slug(name, options={})
8
10
  # Use default name if not provided
9
11
  name, options = 'slug', name if name.is_a?(Hash)
10
- dependencies, options = extract_composite_dependencies(name, options)
11
- build_composite_attribute(name.to_s, dependencies, options)
12
+ NaturalBornSlugger::AttributeComposer.new(name, options).add_to(self)
12
13
  end
13
14
 
14
15
  ##
@@ -17,84 +18,14 @@ module NaturalBornSlugger
17
18
  def has_natural_key(name, options={})
18
19
  # Use default name if not provided
19
20
  name, options = 'natural_key', name if name.is_a?(Hash)
20
- dependencies, options = extract_composite_dependencies(name, options)
21
- build_composite_attribute(name.to_s, dependencies, options)
21
+ NaturalBornSlugger::AttributeComposer.new(name, options).add_to(self)
22
22
  end
23
23
 
24
24
  ##
25
25
  # Adds a generic composite attribute to the class. Name is required.
26
26
  #
27
27
  def has_composite_attribute(name, options={})
28
- dependencies, options = extract_composite_dependencies(name, options)
29
- build_composite_attribute(name.to_s, dependencies, options)
30
- end
31
-
32
- private
33
-
34
- ##
35
- # Pulls method behavior options out of general options. The remaining options
36
- # are assumed to be the dependent attributes that compose this one.
37
- #
38
- def extract_composite_dependencies(name, options={})
39
- dependencies, options = options, {}
40
-
41
- options[:compact_dependencies] = dependencies.delete(:compact) || true
42
- options[:require_dependencies] = dependencies.delete(:require_all) || false
43
- options[:track_changes] = dependencies.delete(:track) || false
44
- options[:joiner] = dependencies.delete(:join_with) || ''
45
-
46
- raise ConfigurationError.new(self.name, name, "no dependent attributes were specified") if dependencies.empty?
47
-
48
- [dependencies, options]
49
- end
50
-
51
- ##
52
- # Adds a composite attribute to the class,
53
- # with a getter and updater method.
54
- # Also adds a setter that either calls the updater
55
- # or throws an error, depending on configuration.
56
- #
57
- def build_composite_attribute(name, dependencies, options)
58
-
59
- # Define instance attribute getter
60
- define_method name do
61
- self.send "update_#{name}"
62
- end
63
-
64
- # Define instance attribute setter: ignores assignment and just triggers an update
65
- define_method "#{name}=" do |value|
66
- if NaturalBornSlugger.configuration.ignore_attribute_setters
67
- # TODO: Log discarded value warning
68
- self.send "update_#{name}"
69
- else
70
- raise IllegalOperationError.new(self.class.name, "#{name}=", 'you cannot set composite attributes directly')
71
- end
72
- end
73
-
74
- # Update instance attribute
75
- define_method "update_#{name}" do
76
- # Check existence of all attribute dependencies if `require_dependencies` is true
77
- resolved_dependencies = dependencies.map do |dependency, strategy|
78
- [resolve_dependency(dependency), strategy]
79
- end
80
- if options[:require_dependencies] ? resolved_dependencies.map(&:first).all? : true
81
- new_value = self.compose_attribute(resolved_dependencies, options)
82
- if options[:track_changes]
83
- old_value = self.instance_variable_get("@#{name}")
84
- unless old_value == new_value
85
- self.send("#{name}_change".to_sym, old_value, new_value)
86
- end
87
- end
88
- self.instance_variable_set("@#{name}", new_value)
89
- end
90
- end
91
-
92
- if [:track_changes]
93
- define_method "#{name}_change" do |old_value, new_value|
94
-
95
- end
96
- end
97
-
28
+ NaturalBornSlugger::AttributeComposer.new(name, options).add_to(self)
98
29
  end
99
30
 
100
31
  end
@@ -1,11 +1,14 @@
1
+ require 'logger'
2
+
1
3
  module NaturalBornSlugger
2
4
  class Configuration
3
5
 
4
- attr_accessor :ignore_attribute_setters, :hashified_length
6
+ attr_accessor :ignore_attribute_setters, :hashified_length, :logger
5
7
 
6
8
  def initialize
7
9
  @ignore_attribute_setters = true
8
10
  @hashified_length = 7
11
+ @logger = Logger.new(STDERR)
9
12
  end
10
13
 
11
14
  end
@@ -1,4 +1,5 @@
1
- require 'active_support/inflector/transliterate'
1
+ require 'active_support/inflector'
2
+
2
3
  class String
3
4
 
4
5
  alias_method :dashify, :parameterize
@@ -1,3 +1,3 @@
1
1
  module NaturalBornSlugger
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_support/core_ext/module/attribute_accessors'
2
+ require 'active_support/core_ext/object/try'
2
3
 
3
4
  require "natural_born_slugger/exceptions"
4
5
  require "natural_born_slugger/configuration"
@@ -14,8 +15,7 @@ module NaturalBornSlugger
14
15
 
15
16
  yield(configuration) if block_given?
16
17
 
17
- require "natural_born_slugger/class_methods"
18
- require "natural_born_slugger/instance_methods"
18
+ require_internals!
19
19
 
20
20
  configuration
21
21
  end
@@ -27,6 +27,12 @@ module NaturalBornSlugger
27
27
  def self.included(base)
28
28
  base.extend ClassMethods
29
29
  end
30
+
31
+ private
32
+
33
+ def self.require_internals!
34
+ require "natural_born_slugger/class_methods"
35
+ end
30
36
  end
31
37
 
32
38
  require "natural_born_slugger/extensions/string"
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "yard", "~> 0.8"
24
24
  spec.add_development_dependency "redcarpet", "~> 2.2"
25
25
  spec.add_development_dependency "rspec", "~> 2.13"
26
+ spec.add_development_dependency "pry"
26
27
 
27
28
  spec.add_dependency 'activesupport', '~> 3.1'
28
29
  end
@@ -0,0 +1,70 @@
1
+ describe NaturalBornSlugger::AttributeComposer do
2
+
3
+ context 'class methods' do
4
+ subject(:composer){ NaturalBornSlugger::AttributeComposer }
5
+
6
+ describe ".default_options" do
7
+ it "should not require that all dependent attributes be present to form composite" do
8
+ composer.composite_options[:require_all].should be_false
9
+ end
10
+ it "should not join depencencies with a special character" do
11
+ composer.composite_options[:join_with].should be_empty
12
+ end
13
+ it "should not use a callback" do
14
+ composer.composite_options[:callback].should be_false
15
+ end
16
+ end
17
+
18
+ describe ".extract_dependencies_from_options" do
19
+ let(:empty_opts) { {} }
20
+ let(:simple_opts) { {name: 'foobar', title: 'asdf'} }
21
+ let(:config_opts) { {require_all: true, join_with: '^'} }
22
+ let(:mixed_opts) { {name: 'foobar', title: 'asdf', require_all: true, join_with: '^'} }
23
+ it "should always return 3 options" do
24
+ [empty_opts, simple_opts, config_opts, mixed_opts].each do |options|
25
+ _, opts = composer.extract_dependencies_from_options(options)
26
+ opts.length.should eql composer.composite_options.length
27
+ end
28
+ end
29
+ end
30
+
31
+ describe ".resolve_dependency" do
32
+ let(:example_object) { Example.new }
33
+ it "should retrieve attributes listed as a dependency" do
34
+ composer.resolve_dependency(example_object, 'attribute').should == 'attribute'
35
+ end
36
+ it "should use the results of methods listed as a dependency" do
37
+ composer.resolve_dependency(example_object, 'meth').should == 'method'
38
+ end
39
+ it "should accept methods that return objects as a dependency" do
40
+ composer.resolve_dependency(example_object, 'child').should be_an ExampleChild
41
+ end
42
+ context "through related objects via dot syntax" do
43
+ it "should resolve a related object's attributes" do
44
+ composer.resolve_dependency(example_object, 'child.attribute').should == 'child attribute'
45
+ end
46
+ it "should resolve a related object's methods" do
47
+ composer.resolve_dependency(example_object, 'child.meth').should == 'child method'
48
+ end
49
+ it "should resolve a related object's own related objects" do
50
+ composer.resolve_dependency(example_object, 'child.child').should be_an ExampleGrandChild
51
+ end
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+
58
+ context 'instance methods' do
59
+
60
+ describe '#compose_attribute' do
61
+
62
+ end
63
+
64
+ describe '#evaluate' do
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
File without changes
@@ -0,0 +1,18 @@
1
+ describe NaturalBornSlugger::Configuration do
2
+ subject(:config) { NaturalBornSlugger.configuration }
3
+
4
+ describe "the default configuration" do
5
+
6
+ it "should ignore attribute setters" do
7
+ config.ignore_attribute_setters.should be_true
8
+ end
9
+ it "should truncate hashed values at 7" do
10
+ config.hashified_length.should eql(7)
11
+ end
12
+ it "should have a basic logger" do
13
+ config.logger.should be_a(Logger)
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,5 @@
1
+ describe String do
2
+ subject { 'foobar' }
3
+ it { should respond_to :dashify }
4
+ it { should respond_to :hashify }
5
+ end
@@ -0,0 +1,17 @@
1
+ describe NaturalBornSlugger do
2
+ subject(:library) { NaturalBornSlugger }
3
+
4
+ context "in order to be configurable" do
5
+ it { should respond_to :configuration }
6
+ it { should respond_to :configure }
7
+
8
+ it "should require library internals after configuration" do
9
+ library.should_receive(:require_internals!)
10
+ library.configure
11
+ end
12
+ end
13
+
14
+ context "in order to write to logs" do
15
+ it { should respond_to :logger }
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ require 'pry'
2
+ require 'rspec'
3
+ require 'natural_born_slugger'
4
+
5
+ NaturalBornSlugger.configure
6
+ require 'support/example'
7
+
8
+ RSpec.configure
@@ -0,0 +1,36 @@
1
+ class Example
2
+ include NaturalBornSlugger
3
+ attr_accessor :attribute
4
+ def initialize
5
+ @attribute = 'attribute'
6
+ end
7
+ def meth
8
+ 'method'
9
+ end
10
+ def child
11
+ ExampleChild.new
12
+ end
13
+ end
14
+
15
+ class ExampleChild
16
+ attr_accessor :attribute
17
+ def initialize
18
+ @attribute = 'child attribute'
19
+ end
20
+ def meth
21
+ 'child method'
22
+ end
23
+ def child
24
+ ExampleGrandChild.new
25
+ end
26
+ end
27
+
28
+ class ExampleGrandChild
29
+ attr_accessor :attribute
30
+ def initialize
31
+ @attribute = 'grandchild attribute'
32
+ end
33
+ def meth
34
+ 'grandchild method'
35
+ end
36
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: natural_born_slugger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Keele
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-18 00:00:00.000000000 Z
11
+ date: 2013-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ~>
81
81
  - !ruby/object:Gem::Version
82
82
  version: '2.13'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: activesupport
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -103,19 +117,26 @@ extensions: []
103
117
  extra_rdoc_files: []
104
118
  files:
105
119
  - .gitignore
106
- - .yardopts
120
+ - .rspec
107
121
  - Gemfile
108
122
  - LICENSE.md
109
123
  - README.md
110
124
  - Rakefile
111
125
  - lib/natural_born_slugger.rb
126
+ - lib/natural_born_slugger/attribute_composer.rb
112
127
  - lib/natural_born_slugger/class_methods.rb
113
128
  - lib/natural_born_slugger/configuration.rb
114
129
  - lib/natural_born_slugger/exceptions.rb
115
130
  - lib/natural_born_slugger/extensions/string.rb
116
- - lib/natural_born_slugger/instance_methods.rb
117
131
  - lib/natural_born_slugger/version.rb
118
132
  - natural_born_slugger.gemspec
133
+ - spec/natural_born_slugger/attribute_builder_spec.rb
134
+ - spec/natural_born_slugger/class_methods_spec.rb
135
+ - spec/natural_born_slugger/configuration_spec.rb
136
+ - spec/natural_born_slugger/extensions/string_spec.rb
137
+ - spec/natural_born_slugger_spec.rb
138
+ - spec/spec_helper.rb
139
+ - spec/support/example.rb
119
140
  homepage: ''
120
141
  licenses:
121
142
  - MIT
@@ -141,5 +162,12 @@ signing_key:
141
162
  specification_version: 4
142
163
  summary: Easily define automatically-updated composed attributes. Includes ORM helpers
143
164
  and a Rack-based URL redirector.
144
- test_files: []
165
+ test_files:
166
+ - spec/natural_born_slugger/attribute_builder_spec.rb
167
+ - spec/natural_born_slugger/class_methods_spec.rb
168
+ - spec/natural_born_slugger/configuration_spec.rb
169
+ - spec/natural_born_slugger/extensions/string_spec.rb
170
+ - spec/natural_born_slugger_spec.rb
171
+ - spec/spec_helper.rb
172
+ - spec/support/example.rb
145
173
  has_rdoc:
data/.yardopts DELETED
@@ -1 +0,0 @@
1
- - LICENSE.md
@@ -1,33 +0,0 @@
1
- module NaturalBornSlugger
2
-
3
- def resolve_dependency(dependency)
4
- object = self
5
- dependency_chain = dependency.to_s.split('.')
6
- dependency_chain.each do |method|
7
- object = object.try :send, method
8
- break unless object
9
- end
10
- object
11
- end
12
-
13
- def compose_attribute(resolved_dependencies, options)
14
- resolved_dependencies.map do |resolved_dependency, strategy|
15
- case strategy
16
- when Symbol # Symbols represent string methods to call on the resolved dependency
17
- resolved_dependency.to_s.send(strategy)
18
- when String # Strings represent formats to fit the resolved dependency into
19
- strategy % resolved_dependency
20
- when Regexp # Regexps represent patterns to pull out of the resolved dependency and join
21
- resolved_dependency.scan(strategy).join(options[:joiner])
22
- when Proc # Procs should take one parameter and return a string or nil
23
- strategy.call(resolved_dependency)
24
- else # If no strategy provided, use resolved dependency as is
25
- resolved_dependency.to_s
26
- end
27
- # Remove nil components if `compact_dependencies` is true
28
- end.tap do |components|
29
- components.compact! if options[:compact_dependencies]
30
- end.join(options[:joiner])
31
- end
32
-
33
- end