Skip to content

Commit

Permalink
Merge pull request #1646 from pablonahuelgomez/allow-helpers-to-mix-i…
Browse files Browse the repository at this point in the history
…n-a-list-of-modules

Add ability to include an array of modules as helpers
  • Loading branch information
dblock authored Jun 12, 2017
2 parents f34fe12 + e027e49 commit 037cd3d
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [#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).
* [#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).
* [#1635](https://github.com/ruby-grape/grape/pull/1635): Instrument validators with ActiveSupport::Notifications - [@ktimothy](https://github.com/ktimothy).
* [#1646](https://github.com/ruby-grape/grape/pull/1646): Add ability to include an array of modules as helpers - [@pablonahuelgomez](https://github.com/pablonahuelgomez).
* Your contribution here.

#### Fixes
Expand Down
50 changes: 32 additions & 18 deletions lib/grape/dsl/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module ClassMethods
# When called without a block, all known helpers within this scope
# are included.
#
# @param [Module] new_mod optional module of methods to include
# @param [Array] new_modules optional array of modules to include
# @param [Block] block optional block of methods to include
#
# @example Define some helpers.
Expand All @@ -26,28 +26,42 @@ module ClassMethods
# end
# end
#
def helpers(new_mod = nil, &block)
if block_given? || new_mod
mod = new_mod || Module.new
define_boolean_in_mod(mod)
inject_api_helpers_to_mod(mod) if new_mod
# @example Include many modules
#
# class ExampleAPI < Grape::API
# helpers Authentication, Mailer, OtherModule
# end
#
def helpers(*new_modules, &block)
include_new_modules(new_modules) if new_modules.any?
include_block(block) if block_given?
include_all_in_scope if !block_given? && new_modules.empty?
end

inject_api_helpers_to_mod(mod) do
mod.class_eval(&block)
end if block_given?
protected

namespace_stackable(:helpers, mod)
else
mod = Module.new
namespace_stackable(:helpers).each do |mod_to_include|
mod.send :include, mod_to_include
end
change!
mod
def include_new_modules(modules)
modules.each { |mod| make_inclusion(mod) }
end

def include_block(block)
Module.new.tap do |mod|
make_inclusion(mod) { mod.class_eval(&block) }
end
end

protected
def make_inclusion(mod, &block)
define_boolean_in_mod(mod)
inject_api_helpers_to_mod(mod, &block)
namespace_stackable(:helpers, mod)
end

def include_all_in_scope
Module.new.tap do |mod|
namespace_stackable(:helpers).each { |mod_to_include| mod.send :include, mod_to_include }
change!
end
end

def define_boolean_in_mod(mod)
return if defined? mod::Boolean
Expand Down
31 changes: 25 additions & 6 deletions spec/grape/dsl/helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ module HelpersSpec
class Dummy
include Grape::DSL::Helpers

def self.mod
namespace_stackable(:helpers).first
def self.mods
namespace_stackable(:helpers)
end

def self.first_mod
mods.first
end
end
end
Expand Down Expand Up @@ -36,23 +40,38 @@ def test
expect(subject).to receive(:namespace_stackable).with(:helpers).and_call_original
subject.helpers(&proc)

expect(subject.mod.instance_methods).to include(:test)
expect(subject.first_mod.instance_methods).to include(:test)
end

it 'uses provided modules' do
mod = Module.new

expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original
expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original.exactly(2).times
expect(subject).to receive(:namespace_stackable).with(:helpers).and_call_original
subject.helpers(mod, &proc)

expect(subject.mod).to eq mod
expect(subject.first_mod).to eq mod
end

it 'uses many provided modules' do
mod = Module.new
mod2 = Module.new
mod3 = Module.new

expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original.exactly(4).times
expect(subject).to receive(:namespace_stackable).with(:helpers).and_call_original.exactly(3).times

subject.helpers(mod, mod2, mod3, &proc)

expect(subject.mods).to include(mod)
expect(subject.mods).to include(mod2)
expect(subject.mods).to include(mod3)
end

context 'with an external file' do
it 'sets Boolean as a Virtus::Attribute::Boolean' do
subject.helpers BooleanParam
expect(subject.mod::Boolean).to eq Virtus::Attribute::Boolean
expect(subject.first_mod::Boolean).to eq Virtus::Attribute::Boolean
end
end
end
Expand Down

0 comments on commit 037cd3d

Please sign in to comment.