Skip to content

Commit e027e49

Browse files
committed
Add ability to include an array of modules as helpers
Changing helpers DSL to allow the inclusion of many modules. This attemps to bring a better readability, since it seems to be more intuitive to send a list of modules when the message in question is called helpers.
1 parent 6c77eea commit e027e49

File tree

3 files changed

+58
-24
lines changed

3 files changed

+58
-24
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* [#1594](https://github.com/ruby-grape/grape/pull/1594): Replace `Hashie::Mash` parameters with `ActiveSupport::HashWithIndifferentAccess` - [@james2m](https://github.com/james2m), [@dblock](https://github.com/dblock).
66
* [#1622](https://github.com/ruby-grape/grape/pull/1622): Add `except_values` validator to replace `except` option of `values` validator - [@jlfaber](https://github.com/jlfaber).
77
* [#1635](https://github.com/ruby-grape/grape/pull/1635): Instrument validators with ActiveSupport::Notifications - [@ktimothy](https://github.com/ktimothy).
8+
* [#1646](https://github.com/ruby-grape/grape/pull/1646): Add ability to include an array of modules as helpers - [@pablonahuelgomez](https://github.com/pablonahuelgomez).
89
* Your contribution here.
910

1011
#### Fixes

lib/grape/dsl/helpers.rb

+32-18
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module ClassMethods
1313
# When called without a block, all known helpers within this scope
1414
# are included.
1515
#
16-
# @param [Module] new_mod optional module of methods to include
16+
# @param [Array] new_modules optional array of modules to include
1717
# @param [Block] block optional block of methods to include
1818
#
1919
# @example Define some helpers.
@@ -26,28 +26,42 @@ module ClassMethods
2626
# end
2727
# end
2828
#
29-
def helpers(new_mod = nil, &block)
30-
if block_given? || new_mod
31-
mod = new_mod || Module.new
32-
define_boolean_in_mod(mod)
33-
inject_api_helpers_to_mod(mod) if new_mod
29+
# @example Include many modules
30+
#
31+
# class ExampleAPI < Grape::API
32+
# helpers Authentication, Mailer, OtherModule
33+
# end
34+
#
35+
def helpers(*new_modules, &block)
36+
include_new_modules(new_modules) if new_modules.any?
37+
include_block(block) if block_given?
38+
include_all_in_scope if !block_given? && new_modules.empty?
39+
end
3440

35-
inject_api_helpers_to_mod(mod) do
36-
mod.class_eval(&block)
37-
end if block_given?
41+
protected
3842

39-
namespace_stackable(:helpers, mod)
40-
else
41-
mod = Module.new
42-
namespace_stackable(:helpers).each do |mod_to_include|
43-
mod.send :include, mod_to_include
44-
end
45-
change!
46-
mod
43+
def include_new_modules(modules)
44+
modules.each { |mod| make_inclusion(mod) }
45+
end
46+
47+
def include_block(block)
48+
Module.new.tap do |mod|
49+
make_inclusion(mod) { mod.class_eval(&block) }
4750
end
4851
end
4952

50-
protected
53+
def make_inclusion(mod, &block)
54+
define_boolean_in_mod(mod)
55+
inject_api_helpers_to_mod(mod, &block)
56+
namespace_stackable(:helpers, mod)
57+
end
58+
59+
def include_all_in_scope
60+
Module.new.tap do |mod|
61+
namespace_stackable(:helpers).each { |mod_to_include| mod.send :include, mod_to_include }
62+
change!
63+
end
64+
end
5165

5266
def define_boolean_in_mod(mod)
5367
return if defined? mod::Boolean

spec/grape/dsl/helpers_spec.rb

+25-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ module HelpersSpec
66
class Dummy
77
include Grape::DSL::Helpers
88

9-
def self.mod
10-
namespace_stackable(:helpers).first
9+
def self.mods
10+
namespace_stackable(:helpers)
11+
end
12+
13+
def self.first_mod
14+
mods.first
1115
end
1216
end
1317
end
@@ -36,23 +40,38 @@ def test
3640
expect(subject).to receive(:namespace_stackable).with(:helpers).and_call_original
3741
subject.helpers(&proc)
3842

39-
expect(subject.mod.instance_methods).to include(:test)
43+
expect(subject.first_mod.instance_methods).to include(:test)
4044
end
4145

4246
it 'uses provided modules' do
4347
mod = Module.new
4448

45-
expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original
49+
expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original.exactly(2).times
4650
expect(subject).to receive(:namespace_stackable).with(:helpers).and_call_original
4751
subject.helpers(mod, &proc)
4852

49-
expect(subject.mod).to eq mod
53+
expect(subject.first_mod).to eq mod
54+
end
55+
56+
it 'uses many provided modules' do
57+
mod = Module.new
58+
mod2 = Module.new
59+
mod3 = Module.new
60+
61+
expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original.exactly(4).times
62+
expect(subject).to receive(:namespace_stackable).with(:helpers).and_call_original.exactly(3).times
63+
64+
subject.helpers(mod, mod2, mod3, &proc)
65+
66+
expect(subject.mods).to include(mod)
67+
expect(subject.mods).to include(mod2)
68+
expect(subject.mods).to include(mod3)
5069
end
5170

5271
context 'with an external file' do
5372
it 'sets Boolean as a Virtus::Attribute::Boolean' do
5473
subject.helpers BooleanParam
55-
expect(subject.mod::Boolean).to eq Virtus::Attribute::Boolean
74+
expect(subject.first_mod::Boolean).to eq Virtus::Attribute::Boolean
5675
end
5776
end
5877
end

0 commit comments

Comments
 (0)