Skip to content

Commit

Permalink
introduced new desc dsl with a block instead of option Hash
Browse files Browse the repository at this point in the history
  • Loading branch information
Dieter Späth committed Sep 17, 2014
1 parent fc70676 commit aeadfc2
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 7 deletions.
1 change: 1 addition & 0 deletions lib/grape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ module Util
autoload :InheritableValues, 'grape/util/inheritable_values'
autoload :StackableValues, 'grape/util/stackable_values'
autoload :InheritableSetting, 'grape/util/inheritable_setting'
autoload :StrictHashConfiguration, 'grape/util/strict_hash_configuration'
end

module DSL
Expand Down
43 changes: 39 additions & 4 deletions lib/grape/dsl/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ module Configuration

module ClassMethods
attr_writer :logger
# attr_reader :settings

include Grape::DSL::Settings

Expand All @@ -21,9 +20,22 @@ def logger(logger = nil)
end

# Add a description to the next namespace or function.
def desc(description, options = {})
namespace_setting :description, options.merge(description: description)
route_setting :description, options.merge(description: description)
def desc(description, options = {}, &config_block)
if block_given?
config_class = Grape::DSL::Configuration.new_desc_config

config_class.configure do
description description
end

config_class.configure(&config_block)
options = config_class.settings
else
options = options.merge(description: description)
end

namespace_setting :description, options
route_setting :description, options
end
end

Expand All @@ -33,6 +45,29 @@ def stacked_hash_to_hash(settings)
return nil if settings.nil? || settings.blank?
settings.each_with_object(ActiveSupport::OrderedHash.new) { |value, result| result.deep_merge!(value) }
end

def new_desc_config
Module.new do
include Grape::Util::StrictHashConfiguration.module(
:description,
:detail,
:params,
:entity,
:http_codes,
:named,
:headers
)

def config_context.success(*args)
entity(*args)
end

def config_context.failure(*args)
http_codes(*args)
end

end
end
end
end
end
112 changes: 112 additions & 0 deletions lib/grape/util/strict_hash_configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
module Grape
module Util
module StrictHashConfiguration
extend ActiveSupport::Concern

module DSL
extend ActiveSupport::Concern

module ClassMethods
def settings
config_context.to_hash
end

def configure(&block)
config_context.instance_exec(&block)
end
end
end

class SettingsContainer
def initialize
@settings = {}
end

def to_hash
@settings.to_hash
end
end

def self.config_class(*args)
new_config_class = Class.new(SettingsContainer)

args.each do |setting_name|
str = if setting_name.respond_to? :values
nested_settings_methods(setting_name)
else
simple_settings_methods(setting_name)
end

new_config_class.class_eval str
end

new_config_class
end

def self.simple_settings_methods(setting_name)
<<-EVAL
def #{setting_name}(new_value)
@settings[:#{setting_name}] = new_value
end
EVAL
end

def self.nested_settings_methods(setting_name)
StringIO.new.tap do |new_str|

setting_name.each_with_object(new_str) do |(key, value), str|
str.puts <<-EVAL
def #{key}_context
@#{key}_context ||= Grape::Util::StrictHashConfiguration.config_class(*#{value.inspect}).new
end
def #{key}(&block)
#{key}_context.instance_exec(&block)
end
EVAL
end

new_str.puts <<-EVAL
def to_hash
@settings.to_hash.merge(
#{setting_name.keys.map { |key| "#{key}: #{key}_context.to_hash" }.join(",\n")}
)
end
EVAL

end.string
end

def self.module(*args)
new_module = Module.new do
extend ActiveSupport::Concern
include DSL
end

new_module.tap do |mod|

class_mod = create_class_mod(args)

mod.const_set(:ClassMethods, class_mod)

end
end

def self.create_class_mod(args)
new_module = Module.new do
def config_context
@config_context ||= config_class.new
end
end

new_module.tap do |class_mod|
new_config_class = config_class(*args)

class_mod.send(:define_method, :config_class) do
@config_context ||= new_config_class
end
end
end
end
end
end
47 changes: 44 additions & 3 deletions spec/grape/dsl/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,51 @@ class Dummy

describe '.desc' do
it 'sets a description' do
desc_text = 'The description'
options = { message: 'none' }
subject.desc options
expect(subject.namespace_setting(:description)).to eq(description: options)
expect(subject.route_setting(:description)).to eq(description: options)
subject.desc desc_text, options
expect(subject.namespace_setting(:description)).to eq(options.merge(description: desc_text))
expect(subject.route_setting(:description)).to eq(options.merge(description: desc_text))
end

it 'can be set with a block' do
expected_options = {
description: 'The description',
detail: 'more details',
params: { first: :param },
entity: Object,
http_codes: [[401, 'Unauthorized', "Entities::Error"]],
named: "My named route",
headers: [XAuthToken: {
description: 'Valdates your identity',
required: true
},
XOptionalHeader: {
description: 'Not really needed',
required: false
}
]
}

subject.desc 'The description' do
detail 'more details'
params(first: :param)
success Object
failure [[401, 'Unauthorized', "Entities::Error"]]
named 'My named route'
headers [XAuthToken: {
description: 'Valdates your identity',
required: true
},
XOptionalHeader: {
description: 'Not really needed',
required: false
}
]
end

expect(subject.namespace_setting(:description)).to eq(expected_options)
expect(subject.route_setting(:description)).to eq(expected_options)
end
end

Expand Down
39 changes: 39 additions & 0 deletions spec/grape/util/strict_hash_configuration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require 'spec_helper'
module Grape
module Util
describe 'StrictHashConfiguration' do
subject do
Class.new do
include Grape::Util::StrictHashConfiguration.module(:config1, :config2, config3: [:config4], config5: [config6: [:config7, :config8]])
end
end

it 'set nested configs' do
subject.configure do
config1 'alpha'
config2 'beta'

config3 do
config4 'gamma'
end

local_var = 8

config5 do
config6 do
config7 7
config8 local_var
end
end
end

expect(subject.settings).to eq(config1: 'alpha',
config2: 'beta',
config3: { config4: 'gamma' },
config5: { config6: { config7: 7, config8: 8 } }
)
end

end
end
end

0 comments on commit aeadfc2

Please sign in to comment.