erector-rails4 0.1.3 → 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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -1
  3. data/.travis.yml +1 -1
  4. data/Appraisals +4 -1
  5. data/Guardfile +23 -0
  6. data/README.md +6 -1
  7. data/erector-rails4.gemspec +10 -3
  8. data/gemfiles/rails_3.gemfile +1 -0
  9. data/gemfiles/rails_4.0.gemfile +1 -0
  10. data/gemfiles/rails_4.1.gemfile +2 -1
  11. data/lib/erector-rails4.rb +1 -0
  12. data/lib/erector.rb +1 -4
  13. data/lib/erector/abstract_widget.rb +1 -12
  14. data/lib/erector/after_initialize.rb +7 -7
  15. data/lib/erector/caching.rb +35 -71
  16. data/lib/erector/element.rb +4 -4
  17. data/lib/erector/externals.rb +0 -8
  18. data/lib/erector/html_widget.rb +0 -11
  19. data/lib/erector/needs.rb +20 -9
  20. data/lib/erector/output.rb +2 -4
  21. data/lib/erector/promise.rb +4 -4
  22. data/lib/erector/rails.rb +6 -1
  23. data/lib/erector/rails/autoload_monkeypatch.rb +1 -1
  24. data/lib/erector/rails/railtie.rb +15 -8
  25. data/lib/erector/rails/template_handler.rb +2 -1
  26. data/lib/erector/text.rb +4 -8
  27. data/lib/erector/version.rb +1 -1
  28. data/lib/erector/widget.rb +2 -11
  29. data/lib/erector/xml_widget.rb +14 -18
  30. data/script/bootstrap +30 -0
  31. data/script/cibuild +3 -0
  32. data/script/performance +3 -0
  33. data/script/release +38 -0
  34. data/spec/dummy/app/views/test/_partial_with_rails_helpers.rb +7 -0
  35. data/spec/dummy/app/views/test/_user.rb +7 -0
  36. data/spec/dummy/app/views/test/_virtual_path_partial.rb +5 -0
  37. data/spec/dummy/app/views/test/erb_from_erector.html.rb +1 -1
  38. data/spec/dummy/app/views/test/erector_with_helpers_from_erb.html.erb +1 -0
  39. data/spec/dummy/app/views/test/{needs.html.rb → needs.rb} +0 -0
  40. data/spec/dummy/app/views/test/{needs_subclass.html.rb → needs_subclass.rb} +0 -0
  41. data/spec/dummy/app/views/test/render_partial.html.rb +1 -1
  42. data/spec/dummy/app/views/test/render_virtual_path.rb +7 -0
  43. data/spec/dummy/app/views/test/users.rb +9 -0
  44. data/spec/dummy/app/views/test_caching/_foos.rb +7 -0
  45. data/spec/dummy/app/views/test_caching/_partial.rb +9 -0
  46. data/spec/dummy/app/views/test_caching/cache_helper.rb +9 -0
  47. data/spec/dummy/app/views/test_caching/cache_helper_with_explicit_dependencies.rb +7 -0
  48. data/spec/dummy/app/views/test_caching/cache_helper_with_implicit_dependencies.rb +7 -0
  49. data/spec/dummy/app/views/test_caching/cache_helper_with_partial.rb +10 -0
  50. data/spec/dummy/app/views/test_caching/cache_helper_with_skip_digest.rb +9 -0
  51. data/spec/dummy/app/views/test_caching/cacheable_widget_with_dynamic_keys.rb +13 -0
  52. data/spec/dummy/app/views/test_caching/cacheable_widget_with_needs.rb +11 -0
  53. data/spec/dummy/app/views/test_caching/cacheable_widget_with_needs_keys.rb +11 -0
  54. data/spec/dummy/app/views/test_caching/cacheable_widget_with_skip_digest.rb +9 -0
  55. data/spec/dummy/app/views/test_caching/cacheable_widget_with_static_keys.rb +9 -0
  56. data/spec/dummy/config/application.rb +1 -1
  57. data/spec/dummy/spec/autoload_spec.rb +2 -2
  58. data/spec/dummy/spec/caching_spec.rb +180 -0
  59. data/spec/dummy/spec/form_builder_spec.rb +1 -1
  60. data/spec/dummy/spec/rails_helpers_spec.rb +21 -13
  61. data/spec/dummy/spec/rails_widget_spec.rb +1 -1
  62. data/spec/dummy/spec/render_spec.rb +23 -42
  63. data/spec/erector/dependency_spec.rb +0 -1
  64. data/spec/erector/html_spec.rb +4 -4
  65. data/spec/erector/indentation_spec.rb +2 -2
  66. data/spec/erector/needs_spec.rb +33 -0
  67. data/spec/erector/output_spec.rb +0 -2
  68. data/spec/erector/promise_spec.rb +2 -2
  69. data/spec/erector/widget_spec.rb +2 -2
  70. data/spec/performance/allocation_spec.rb +19 -0
  71. data/spec/performance/ruby_prof_spec.rb +23 -0
  72. data/spec/performance/widget_to_html_spec.rb +11 -5
  73. data/spec/spec_helper.rb +1 -10
  74. data/spec/support/capturing_output.rb +8 -0
  75. metadata +116 -17
  76. data/lib/erector/cache.rb +0 -41
  77. data/lib/erector/raw_string.rb +0 -12
  78. data/spec/dummy/spec/rails_spec_helper.rb +0 -10
  79. data/spec/erector/cache_spec.rb +0 -133
  80. data/spec/erector/caching_spec.rb +0 -202
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a74438b8e1a5e68fb0630a400e6863d5eef429d3
4
- data.tar.gz: 5a3bb013b485b9afd29a816abccf442dfec8126a
3
+ metadata.gz: a9340d97584f99c33a1f240e455c4d99976abff9
4
+ data.tar.gz: 45cad63111621752efeaca71702964bcd709072b
5
5
  SHA512:
6
- metadata.gz: acc2083f696024b0ece8425d4591674dbaadc00d5cfca2e6ab61f7a06fd225c5390bb39694bdca32c70e34d24bf80eaeaf60b145339eb8166cdeadc0faebaf5d
7
- data.tar.gz: af17c1bb8dbd175f441b7537f7314e4c4de03abfc0c09b44c9422f2f14a264e8499c681062e878bfc18bdc205da678c252f1f51aa040e416bf74b50394a66b4b
6
+ metadata.gz: ea474c7bbae811af74994baae3bae443b02f15a68f04f5e5a72516a8506c51cb7004d41e2e86478155b8a94ee9f91e29b94f9db0bc5af14c7c044fa2847745a3
7
+ data.tar.gz: d476856b91c0c21ad0b313a89d7ba20c736fabc48df1dce0b43b81e6b2d5f5c5299b3344a8b8f24e162458be636489331099d3cab332a9bc64c3a623f1189e9d
@@ -1,2 +1,2 @@
1
1
  service_name: travis-ci
2
- repo_token: J1XUNT8uCGW7viYD01wooJ6PSlVc3Iyt2
2
+ repo_token: PLlg5sgYq8Bo0YEjewCfjarEnzBu8K9jm
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  cache: bundler
3
- script: bundle exec rspec
3
+ script: script/cibuild
4
4
  notifications:
5
5
  email: false
6
6
 
data/Appraisals CHANGED
@@ -1,14 +1,17 @@
1
1
  appraise 'rails-3' do
2
+ gem 'activesupport', '3.2.7'
2
3
  gem 'rails', '3.2.7'
3
4
  gem 'simple_form', '2.1.1'
4
5
  end
5
6
 
6
7
  appraise 'rails-4.0' do
8
+ gem 'activesupport', '4.0.0'
7
9
  gem 'rails', '4.0.0'
8
10
  gem 'simple_form', '3.0.2'
9
11
  end
10
12
 
11
13
  appraise 'rails-4.1' do
12
- gem 'rails', '4.1.0'
14
+ gem 'activesupport', '4.1.6'
15
+ gem 'rails', '4.1.6'
13
16
  gem 'simple_form', '3.0.2'
14
17
  end
@@ -0,0 +1,23 @@
1
+ group :main do
2
+ guard :rspec,
3
+ all_on_start: false,
4
+ all_after_pass: false,
5
+ spec_paths: ['spec/dummy', 'spec/erector'],
6
+ cmd: 'bundle exec rspec',
7
+ failed_mode: :focus do
8
+
9
+ watch(%r{^spec/.+_spec\.rb$})
10
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+
12
+ end
13
+ end
14
+
15
+ group :perf do
16
+ guard :rspec,
17
+ all_on_start: false,
18
+ all_after_pass: false,
19
+ spec_paths: ['spec/performance'],
20
+ cmd: 'bundle exec rspec' do
21
+
22
+ end
23
+ end
data/README.md CHANGED
@@ -1,10 +1,15 @@
1
1
  Erector for Rails 4
2
2
  =====
3
3
 
4
- [![Gem Version](https://badge.fury.io/rb/erector-rails4.png)](http://badge.fury.io/rb/erector-rails4) [![Build Status](https://travis-ci.org/adamjacobbecker/erector-rails4.png?branch=master)](https://travis-ci.org/adamjacobbecker/erector-rails4) [![Coverage Status](https://coveralls.io/repos/adamjacobbecker/erector-rails4/badge.png)](https://coveralls.io/r/adamjacobbecker/erector-rails4) [![Code Climate](https://codeclimate.com/github/adamjacobbecker/erector-rails4.png)](https://codeclimate.com/github/adamjacobbecker/erector-rails4)
4
+ [![version]](http://badge.fury.io/rb/erector-rails4) [![status]](https://travis-ci.org/ajb/erector-rails4) [![coverage]](https://coveralls.io/r/ajb/erector-rails4) [![climate]](https://codeclimate.com/github/ajb/erector-rails4)
5
5
 
6
6
  This is a fork of [Erector](https://github.com/erector/erector) with a lotta old crap removed. Currently under active development, but in regular use at [DOBT](https://www.github.com/dobtco).
7
7
 
8
8
  ```ruby
9
9
  gem 'erector-rails4', require: 'erector'
10
10
  ```
11
+
12
+ [version]: http://img.shields.io/gem/v/erector-rails4.svg?style=flat
13
+ [status]: http://img.shields.io/travis/ajb/erector-rails4.svg?style=flat
14
+ [coverage]: http://img.shields.io/coveralls/ajb/erector-rails4.svg?style=flat
15
+ [climate]: http://img.shields.io/codeclimate/github/ajb/erector-rails4.svg?style=flat
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.name = "erector-rails4"
9
9
  s.version = Erector::VERSION
10
10
 
11
- s.required_ruby_version = Gem::Requirement.new('>= 2.0.0')
11
+ s.required_ruby_version = Gem::Requirement.new('>= 1.9.3')
12
12
  s.authors = ["Alex Chaffee", "Brian Takita", "Jeff Dean", "Jim Kingdon", "John Firebaugh", "Adam Becker"]
13
13
  s.summary = "Erector, for Rails 4"
14
14
  s.description = "This is a fork of Erector, updated for Rails 4."
@@ -18,16 +18,18 @@ Gem::Specification.new do |s|
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.test_files = `git ls-files -- {features,spec}/*`.split("\n")
20
20
 
21
- s.homepage = "http://github.com/adamjacobbecker/erector-rails4"
21
+ s.homepage = "http://github.com/ajb/erector-rails4"
22
22
  s.require_paths = ["lib"]
23
23
 
24
- s.add_dependency 'rails', '>= 3.0.0'
24
+ s.add_dependency 'activesupport', '>= 3.0.0'
25
25
  s.add_dependency 'treetop'
26
26
 
27
27
  s.add_development_dependency 'appraisal', '1.0.0'
28
28
  s.add_development_dependency 'coveralls', '0.7.0'
29
29
  s.add_development_dependency 'haml', '4.0.5'
30
+ s.add_development_dependency 'guard-rspec', '4.3.1'
30
31
  s.add_development_dependency 'nokogiri', '1.6.1'
32
+ s.add_development_dependency 'rails', '>= 3.0.0'
31
33
  s.add_development_dependency 'rr', '1.1.2'
32
34
  s.add_development_dependency 'rspec-rails', '2.14.2'
33
35
  s.add_development_dependency 'sass', '3.3.4'
@@ -35,4 +37,9 @@ Gem::Specification.new do |s|
35
37
  s.add_development_dependency 'sqlite3', '1.3.9'
36
38
  s.add_development_dependency 'wrong', '0.7.1'
37
39
 
40
+ if RUBY_VERSION >= '2.1'
41
+ s.add_development_dependency 'allocation_stats', '0.1.5'
42
+ s.add_development_dependency 'ruby-prof', '0.15.1'
43
+ end
44
+
38
45
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem "activesupport", "3.2.7"
5
6
  gem "rails", "3.2.7"
6
7
  gem "simple_form", "2.1.1"
7
8
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem "activesupport", "4.0.0"
5
6
  gem "rails", "4.0.0"
6
7
  gem "simple_form", "3.0.2"
7
8
 
@@ -2,7 +2,8 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "4.1.0"
5
+ gem "activesupport", "4.1.6"
6
+ gem "rails", "4.1.6"
6
7
  gem "simple_form", "3.0.2"
7
8
 
8
9
  gemspec :path => "../"
@@ -0,0 +1 @@
1
+ require 'erector'
@@ -1,15 +1,12 @@
1
1
  module Erector
2
2
  end
3
3
 
4
- require "cgi"
4
+ require "active_support/core_ext/string"
5
5
 
6
- require "erector/raw_string"
7
6
  require "erector/dependencies"
8
7
  require "erector/dependency"
9
8
  require "erector/externals"
10
9
  require "erector/output"
11
- require "erector/cache"
12
- require "erector/caching"
13
10
  require "erector/after_initialize"
14
11
  require "erector/needs"
15
12
  require "erector/html"
@@ -71,7 +71,7 @@ module Erector
71
71
  @_parent = eval("self", block.binding) if block
72
72
  @_block = block
73
73
 
74
- self.class.after_initialize(self)
74
+ self.class.call_after_initialize(self)
75
75
  end
76
76
 
77
77
  # Entry point for rendering a widget (and all its children). This method
@@ -101,16 +101,6 @@ module Erector
101
101
  _emit(options).to_s
102
102
  end
103
103
 
104
- # alias for #emit
105
- # @deprecated Please use {#emit} instead
106
- def to_s(*args)
107
- unless defined? @@already_warned_to_s
108
- $stderr.puts "Erector::Widget#to_s is deprecated. Please use #to_html instead. Called from #{caller.first}"
109
- @@already_warned_to_s = true
110
- end
111
- to_html(*args)
112
- end
113
-
114
104
  # Entry point for rendering a widget (and all its children). Same as
115
105
  # #render / #to_html only it returns an array, for theoretical performance
116
106
  # improvements when using a Rack server (like Sinatra or Rails Metal).
@@ -183,7 +173,6 @@ module Erector
183
173
  ensure
184
174
  @_output = original
185
175
  end
186
- alias_method :capture, :capture_content
187
176
 
188
177
  protected
189
178
  # executes this widget's #content method, which emits stuff onto the
@@ -5,18 +5,18 @@ module Erector
5
5
  end
6
6
 
7
7
  module ClassMethods
8
- def after_initialize(instance=nil, &blk)
9
- if blk
10
- after_initialize_parts << blk
11
- elsif instance
8
+ def after_initialize(&blk)
9
+ after_initialize_parts << blk
10
+ end
11
+
12
+ def call_after_initialize(instance)
13
+ if instance
12
14
  if superclass.respond_to?(:after_initialize)
13
- superclass.after_initialize instance
15
+ superclass.call_after_initialize instance
14
16
  end
15
17
  after_initialize_parts.each do |part|
16
18
  instance.instance_eval &part
17
19
  end
18
- else
19
- raise ArgumentError, "You must provide either an instance or a block"
20
20
  end
21
21
  end
22
22
 
@@ -5,93 +5,57 @@ module Erector
5
5
  end
6
6
 
7
7
  module ClassMethods
8
- def cacheable(value = true, opts = {})
9
- @cachable, @cache_opts = value, opts
8
+ def cacheable(*args)
9
+ options = args.extract_options!
10
10
 
11
- if value && value != true
12
- @cache_version = value
13
- end
14
- end
15
-
16
- alias_method :cachable, :cacheable
17
-
18
- def cachable?
19
- if @cachable.nil?
20
- superclass.respond_to?(:cachable?) && superclass.cachable?
21
- else
22
- @cachable
23
- end
24
- end
25
-
26
- def cache_opts
27
- if cachable?
28
- @cache_opts || {}
29
- end
30
- end
31
-
32
- def cache_version
33
- @cache_version || nil
11
+ @cacheable_opts = {
12
+ static_keys: args,
13
+ dynamic_keys: if options[:needs_keys]
14
+ needed_variables & options[:needs_keys]
15
+ else
16
+ needed_variables
17
+ end,
18
+ skip_digest: options[:skip_digest]
19
+ }
34
20
  end
35
21
 
36
- def cache
37
- Erector::Cache.instance
22
+ def cacheable_opts
23
+ @cacheable_opts
38
24
  end
39
25
  end
40
26
 
41
- def cache
42
- self.class.cache
27
+ def cacheable?
28
+ !self.class.cacheable_opts.nil?
43
29
  end
44
30
 
45
- def should_cache?
46
- if block.nil? && self.class.cachable? && caching_configured?
47
- true
48
- else
49
- false
50
- end
51
- end
31
+ def cache_name
32
+ [].tap do |a|
33
+ self.class.cacheable_opts[:static_keys].each do |x|
34
+ if x.is_a?(Symbol) && respond_to?(x)
35
+ a << send(x)
36
+ else
37
+ a << x
38
+ end
39
+ end
52
40
 
53
- def caching_configured?
54
- return true if !defined?(Rails)
55
- ::Rails.configuration.action_controller.perform_caching &&
56
- ::Rails.configuration.action_controller.cache_store
41
+ self.class.cacheable_opts[:dynamic_keys].each do |x|
42
+ a << instance_variable_get(:"@#{x}")
43
+ end
44
+ end.reject(&:nil?)
57
45
  end
58
46
 
59
- def cache_key_assigns
60
- if self.class.cache_opts[:only_keys]
61
- assigns.slice(*self.class.cache_opts[:only_keys])
62
- else
63
- assigns
64
- end
47
+ def cache_options
48
+ {
49
+ skip_digest: self.class.cacheable_opts[:skip_digest]
50
+ }
65
51
  end
66
52
 
67
53
  protected
68
54
  def _emit(options = {})
69
- if should_cache?
70
- if options[:output]
71
- # todo: document that either :buffer or :output can be used to specify an output buffer, and deprecate :output
72
- if options[:output].is_a? Output
73
- @_output = options[:output]
74
- else
75
- @_output = Output.new({:buffer => options[:output]}.merge(options))
76
- end
77
- else
78
- @_output = Output.new(options)
55
+ if cacheable? && options[:helpers].try(:respond_to?, :cache)
56
+ options[:helpers].cache cache_name, cache_options do
57
+ super
79
58
  end
80
-
81
- if (cached_str = cache[self.class, self.class.cache_version, cache_key_assigns, options[:content_method_name]])
82
- output << cached_str
83
- else
84
- cache[self.class, self.class.cache_version, cache_key_assigns, options[:content_method_name]] = super
85
- end
86
- else
87
- super
88
- end
89
- end
90
-
91
- def _emit_via(parent, options = {})
92
- if should_cache?
93
- parent.output << cache[self.class, self.class.cache_version, cache_key_assigns, options[:content_method_name]] ||= parent.capture_content { super }
94
- parent.output.widgets << self.class # todo: test!!!
95
59
  else
96
60
  super
97
61
  end
@@ -86,7 +86,7 @@ module Erector
86
86
 
87
87
  attributes ||= {}
88
88
  promise = if !value.nil?
89
- Promise.new(output, tag_name, attributes, false, newliney?(tag_name)) do
89
+ Promise.new(output, tag_name, attributes, false, self.class.newliney?(tag_name)) do
90
90
  if value.is_a? AbstractWidget
91
91
  widget value
92
92
  else
@@ -94,16 +94,16 @@ module Erector
94
94
  end
95
95
  end
96
96
  elsif block
97
- Promise.new(output, tag_name, attributes, false, newliney?(tag_name), &block)
97
+ Promise.new(output, tag_name, attributes, false, self.class.newliney?(tag_name), &block)
98
98
  else
99
- Promise.new(output, tag_name, attributes, false, newliney?(tag_name))
99
+ Promise.new(output, tag_name, attributes, false, self.class.newliney?(tag_name))
100
100
  end
101
101
  promise._render
102
102
  promise
103
103
  end
104
104
 
105
105
  def _empty_element(tag_name, attributes={})
106
- promise = Promise.new(output, tag_name, attributes, true, newliney?(tag_name))
106
+ promise = Promise.new(output, tag_name, attributes, true, self.class.newliney?(tag_name))
107
107
  promise._render
108
108
  promise
109
109
  end
@@ -30,14 +30,6 @@ module Erector
30
30
  my_dependencies.push(x)
31
31
  end
32
32
 
33
- # deprecated in favor of #depends_on
34
- # todo: warning
35
- def external(type, value, options = {})
36
- type = type.to_sym
37
- x = Dependency.new(type, value, options)
38
- my_dependencies << x unless my_dependencies.include?(x)
39
- end
40
-
41
33
  # returns all dependencies of the given type from this class and all its
42
34
  # superclasses
43
35
  def dependencies(type)
@@ -45,7 +45,6 @@ module Erector
45
45
  # * Attributes
46
46
  # * Text
47
47
  # * Needs
48
- # * Caching
49
48
  # * Externals
50
49
  # * AfterInitialize
51
50
  #
@@ -200,16 +199,6 @@ module Erector
200
199
  _render(options).to_s
201
200
  end
202
201
 
203
- # alias for #to_html
204
- # @deprecated Please use {#to_html} instead
205
- def to_s(*args)
206
- unless defined? @@already_warned_to_s
207
- $stderr.puts "Erector::Widget#to_s is deprecated. Please use #to_html instead. Called from #{caller.first}"
208
- @@already_warned_to_s = true
209
- end
210
- to_html(*args)
211
- end
212
-
213
202
  end
214
203
 
215
204
  public
@@ -36,28 +36,39 @@ module Erector
36
36
  # FancyForm.new(:name => 'Login')
37
37
  # will fail.
38
38
  #
39
+ def inherited(subclass)
40
+ subclass.needs(*self.get_needs)
41
+ end
42
+
39
43
  def needs(*args)
44
+ @needs ||= []
45
+
40
46
  args.each do |arg|
41
- (@needs ||= []) << (arg.nil? ? nil : (arg.is_a? Hash) ? arg : arg.to_sym)
47
+ @needs.push(if arg.nil?
48
+ nil
49
+ elsif arg.is_a? Hash
50
+ arg
51
+ elsif arg.is_a? Symbol
52
+ arg
53
+ else
54
+ fail 'arguments passed to :needs must be Nil, a Hash, or a Symbol'
55
+ end)
42
56
  end
43
57
  end
44
58
 
45
59
  def get_needs
46
- @needs ||= []
47
-
48
- ancestors[1..-1].inject(@needs.dup) do |needs, ancestor|
49
- needs.push(*ancestor.get_needs) if ancestor.respond_to?(:get_needs)
50
- needs
51
- end
60
+ @needs || []
52
61
  end
53
62
 
54
63
  def needed_variables
55
- @needed_variables ||= get_needs.map{|need| need.is_a?(Hash) ? need.keys : need}.flatten
64
+ @needed_variables ||= get_needs.map { |need|
65
+ need.is_a?(Hash) ? need.keys : need
66
+ }.flatten
56
67
  end
57
68
 
58
69
  def needed_defaults
59
70
  @needed_defaults ||= get_needs.inject({}) do |defaults, need|
60
- defaults = need.merge(defaults) if need.is_a? Hash
71
+ defaults = defaults.merge(need) if need.is_a? Hash
61
72
  defaults
62
73
  end
63
74
  end