mirror of
https://github.com/github/rails.git
synced 2026-01-14 17:17:58 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b7754c950 | ||
|
|
75638c576b | ||
|
|
76884dd7f7 | ||
|
|
29a72262aa | ||
|
|
76c5bf4f4b | ||
|
|
416b7171b8 | ||
|
|
e82a3ba2a0 | ||
|
|
8837faac73 | ||
|
|
20b12c3b42 | ||
|
|
0cf06787af | ||
|
|
5efad05b11 |
@@ -1273,8 +1273,7 @@ module ActionController #:nodoc:
|
|||||||
end
|
end
|
||||||
|
|
||||||
def initialize_template_class(response)
|
def initialize_template_class(response)
|
||||||
response.template = ActionView::Base.new(self.class.view_paths, {}, self)
|
response.template = self.class.master_helper_class.new(self.class.view_paths, {}, self)
|
||||||
response.template.helpers.send :include, self.class.master_helper_module
|
|
||||||
response.redirected_to = nil
|
response.redirected_to = nil
|
||||||
@performed_render = @performed_redirect = false
|
@performed_render = @performed_redirect = false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -69,6 +69,22 @@ module ActionController #:nodoc:
|
|||||||
# N/A | Carolina Railhaws Training Workshop
|
# N/A | Carolina Railhaws Training Workshop
|
||||||
#
|
#
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
# To avoid extending an instance of ActionView::Base with the master_helper_module
|
||||||
|
# every single time we render a view, we're caching a class that has
|
||||||
|
# master_helper_module already included that we can just instantiate.
|
||||||
|
def master_helper_class
|
||||||
|
return @master_helper_class if @master_helper_class
|
||||||
|
|
||||||
|
@master_helper_class = Class.new(ActionView::Base).tap do |klass|
|
||||||
|
klass.send(:include, master_helper_module)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def master_helper_module=(mod)
|
||||||
|
write_inheritable_attribute(:master_helper_module, mod)
|
||||||
|
@master_helper_class = nil
|
||||||
|
end
|
||||||
|
|
||||||
# Makes all the (instance) methods in the helper module available to templates rendered through this controller.
|
# Makes all the (instance) methods in the helper module available to templates rendered through this controller.
|
||||||
# See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules
|
# See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules
|
||||||
# available to the templates.
|
# available to the templates.
|
||||||
@@ -182,8 +198,7 @@ module ActionController #:nodoc:
|
|||||||
# Provides a proxy to access helpers methods from outside the view.
|
# Provides a proxy to access helpers methods from outside the view.
|
||||||
def helpers
|
def helpers
|
||||||
unless @helper_proxy
|
unless @helper_proxy
|
||||||
@helper_proxy = ActionView::Base.new
|
@helper_proxy = master_helper_class.new
|
||||||
@helper_proxy.extend master_helper_module
|
|
||||||
else
|
else
|
||||||
@helper_proxy
|
@helper_proxy
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -203,24 +203,10 @@ module ActionView #:nodoc:
|
|||||||
ActionView::PathSet.new(Array(value))
|
ActionView::PathSet.new(Array(value))
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :helpers
|
|
||||||
|
|
||||||
class ProxyModule < Module
|
|
||||||
def initialize(receiver)
|
|
||||||
@receiver = receiver
|
|
||||||
end
|
|
||||||
|
|
||||||
def include(*args)
|
|
||||||
super(*args)
|
|
||||||
@receiver.extend(*args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc:
|
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil)#:nodoc:
|
||||||
@assigns = assigns_for_first_render
|
@assigns = assigns_for_first_render
|
||||||
@assigns_added = nil
|
@assigns_added = nil
|
||||||
@controller = controller
|
@controller = controller
|
||||||
@helpers = ProxyModule.new(self)
|
|
||||||
self.view_paths = view_paths
|
self.view_paths = view_paths
|
||||||
|
|
||||||
@_first_render = nil
|
@_first_render = nil
|
||||||
|
|||||||
@@ -116,8 +116,7 @@ module ActionView
|
|||||||
end
|
end
|
||||||
|
|
||||||
def _view
|
def _view
|
||||||
view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller)
|
view = self.class.master_helper_class.new(ActionController::Base.view_paths, _assigns, @controller)
|
||||||
view.helpers.include master_helper_module
|
|
||||||
view.output_buffer = self.output_buffer
|
view.output_buffer = self.output_buffer
|
||||||
view
|
view
|
||||||
end
|
end
|
||||||
|
|||||||
134
activesupport/lib/active_support/concern.rb
Normal file
134
activesupport/lib/active_support/concern.rb
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
module ActiveSupport
|
||||||
|
# A typical module looks like this:
|
||||||
|
#
|
||||||
|
# module M
|
||||||
|
# def self.included(base)
|
||||||
|
# base.extend ClassMethods
|
||||||
|
# base.class_eval do
|
||||||
|
# scope :disabled, -> { where(disabled: true) }
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# module ClassMethods
|
||||||
|
# ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
||||||
|
# written as:
|
||||||
|
#
|
||||||
|
# require 'active_support/concern'
|
||||||
|
#
|
||||||
|
# module M
|
||||||
|
# extend ActiveSupport::Concern
|
||||||
|
#
|
||||||
|
# included do
|
||||||
|
# scope :disabled, -> { where(disabled: true) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# module ClassMethods
|
||||||
|
# ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module
|
||||||
|
# and a +Bar+ module which depends on the former, we would typically write the
|
||||||
|
# following:
|
||||||
|
#
|
||||||
|
# module Foo
|
||||||
|
# def self.included(base)
|
||||||
|
# base.class_eval do
|
||||||
|
# def self.method_injected_by_foo
|
||||||
|
# ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# module Bar
|
||||||
|
# def self.included(base)
|
||||||
|
# base.method_injected_by_foo
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# class Host
|
||||||
|
# include Foo # We need to include this dependency for Bar
|
||||||
|
# include Bar # Bar is the module that Host really needs
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
|
||||||
|
# could try to hide these from +Host+ directly including +Foo+ in +Bar+:
|
||||||
|
#
|
||||||
|
# module Bar
|
||||||
|
# include Foo
|
||||||
|
# def self.included(base)
|
||||||
|
# base.method_injected_by_foo
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# class Host
|
||||||
|
# include Bar
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
|
||||||
|
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
||||||
|
# module dependencies are properly resolved:
|
||||||
|
#
|
||||||
|
# require 'active_support/concern'
|
||||||
|
#
|
||||||
|
# module Foo
|
||||||
|
# extend ActiveSupport::Concern
|
||||||
|
# included do
|
||||||
|
# def self.method_injected_by_foo
|
||||||
|
# ...
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# module Bar
|
||||||
|
# extend ActiveSupport::Concern
|
||||||
|
# include Foo
|
||||||
|
#
|
||||||
|
# included do
|
||||||
|
# self.method_injected_by_foo
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# class Host
|
||||||
|
# include Bar # works, Bar takes care now of its dependencies
|
||||||
|
# end
|
||||||
|
module Concern
|
||||||
|
class MultipleIncludedBlocks < StandardError #:nodoc:
|
||||||
|
def initialize
|
||||||
|
super "Cannot define multiple 'included' blocks for a Concern"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.extended(base) #:nodoc:
|
||||||
|
base.instance_variable_set(:@_dependencies, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def append_features(base)
|
||||||
|
if base.instance_variable_defined?(:@_dependencies)
|
||||||
|
base.instance_variable_get(:@_dependencies) << self
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return false if base < self
|
||||||
|
@_dependencies.each { |dep| base.send(:include, dep) }
|
||||||
|
super
|
||||||
|
base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
|
||||||
|
base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def included(base = nil, &block)
|
||||||
|
if base.nil?
|
||||||
|
raise MultipleIncludedBlocks if instance_variable_defined?(:@_included_block)
|
||||||
|
|
||||||
|
@_included_block = block
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
#--
|
|
||||||
# Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
|
|
||||||
# All rights reserved.
|
|
||||||
|
|
||||||
# Permission is granted for use, copying, modification, distribution,
|
|
||||||
# and distribution of modified versions of this work as long as the
|
|
||||||
# above copyright notice is included.
|
|
||||||
#++
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# BlankSlate provides an abstract base class with no predefined
|
|
||||||
# methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
|
|
||||||
# BlankSlate is useful as a base class when writing classes that
|
|
||||||
# depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
|
|
||||||
#
|
|
||||||
class BlankSlate
|
|
||||||
class << self
|
|
||||||
|
|
||||||
# Hide the method named +name+ in the BlankSlate class. Don't
|
|
||||||
# hide +instance_eval+ or any method beginning with "__".
|
|
||||||
def hide(name)
|
|
||||||
if (instance_methods.include?(name) || instance_methods.include?(name.to_sym)) and
|
|
||||||
name !~ /^(__|instance_eval|object_id)/
|
|
||||||
@hidden_methods ||= {}
|
|
||||||
@hidden_methods[name] = instance_method(name)
|
|
||||||
undef_method name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_hidden_method(name)
|
|
||||||
@hidden_methods ||= {}
|
|
||||||
@hidden_methods[name] || superclass.find_hidden_method(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Redefine a previously hidden method so that it may be called on a blank
|
|
||||||
# slate object.
|
|
||||||
def reveal(name)
|
|
||||||
bound_method = nil
|
|
||||||
|
|
||||||
unbound_method = find_hidden_method(name)
|
|
||||||
fail "Don't know how to reveal method '#{name}'" unless unbound_method
|
|
||||||
define_method(name) do |*args|
|
|
||||||
bound_method ||= unbound_method.bind(self)
|
|
||||||
bound_method.call(*args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
instance_methods.each { |m| hide(m) }
|
|
||||||
end
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# Since Ruby is very dynamic, methods added to the ancestors of
|
|
||||||
# BlankSlate <em>after BlankSlate is defined</em> will show up in the
|
|
||||||
# list of available BlankSlate methods. We handle this by defining a
|
|
||||||
# hook in the Object and Kernel classes that will hide any method
|
|
||||||
# defined after BlankSlate has been loaded.
|
|
||||||
#
|
|
||||||
module Kernel
|
|
||||||
class << self
|
|
||||||
alias_method :blank_slate_method_added, :method_added
|
|
||||||
|
|
||||||
# Detect method additions to Kernel and remove them in the
|
|
||||||
# BlankSlate class.
|
|
||||||
def method_added(name)
|
|
||||||
result = blank_slate_method_added(name)
|
|
||||||
return result if self != Kernel
|
|
||||||
BlankSlate.hide(name)
|
|
||||||
result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# Same as above, except in Object.
|
|
||||||
#
|
|
||||||
class Object
|
|
||||||
class << self
|
|
||||||
alias_method :blank_slate_method_added, :method_added
|
|
||||||
|
|
||||||
# Detect method additions to Object and remove them in the
|
|
||||||
# BlankSlate class.
|
|
||||||
def method_added(name)
|
|
||||||
result = blank_slate_method_added(name)
|
|
||||||
return result if self != Object
|
|
||||||
BlankSlate.hide(name)
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_hidden_method(name)
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# Also, modules included into Object need to be scanned and have their
|
|
||||||
# instance methods removed from blank slate. In theory, modules
|
|
||||||
# included into Kernel would have to be removed as well, but a
|
|
||||||
# "feature" of Ruby prevents late includes into modules from being
|
|
||||||
# exposed in the first place.
|
|
||||||
#
|
|
||||||
class Module
|
|
||||||
alias blankslate_original_append_features append_features
|
|
||||||
def append_features(mod)
|
|
||||||
result = blankslate_original_append_features(mod)
|
|
||||||
return result if mod != Object
|
|
||||||
instance_methods.each do |name|
|
|
||||||
BlankSlate.hide(name)
|
|
||||||
end
|
|
||||||
result
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
#--
|
|
||||||
# Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
|
|
||||||
# All rights reserved.
|
|
||||||
|
|
||||||
# Permission is granted for use, copying, modification, distribution,
|
|
||||||
# and distribution of modified versions of this work as long as the
|
|
||||||
# above copyright notice is included.
|
|
||||||
#++
|
|
||||||
|
|
||||||
require 'blankslate'
|
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# BlankSlate has been promoted to a top level name and is now
|
|
||||||
# available as a standalone gem. We make the name available in the
|
|
||||||
# Builder namespace for compatibility.
|
|
||||||
#
|
|
||||||
module Builder
|
|
||||||
BlankSlate = ::BlankSlate
|
|
||||||
end
|
|
||||||
@@ -18,8 +18,6 @@
|
|||||||
# Style Sheets (CSS).
|
# Style Sheets (CSS).
|
||||||
|
|
||||||
|
|
||||||
require 'builder/blankslate'
|
|
||||||
|
|
||||||
module Builder
|
module Builder
|
||||||
|
|
||||||
# Create a Cascading Style Sheet (CSS) using Ruby.
|
# Create a Cascading Style Sheet (CSS) using Ruby.
|
||||||
@@ -89,7 +87,7 @@ module Builder
|
|||||||
# background: red;
|
# background: red;
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
class CSS < BlankSlate
|
class CSS < BasicObject
|
||||||
|
|
||||||
# Create a CSS builder.
|
# Create a CSS builder.
|
||||||
#
|
#
|
||||||
@@ -155,7 +153,7 @@ module Builder
|
|||||||
|
|
||||||
def group!(*args, &block)
|
def group!(*args, &block)
|
||||||
args.each do |arg|
|
args.each do |arg|
|
||||||
if arg.is_a?(Symbol)
|
if arg.is_a?(::Symbol)
|
||||||
instance_eval(&@library[arg])
|
instance_eval(&@library[arg])
|
||||||
else
|
else
|
||||||
instance_eval(&arg)
|
instance_eval(&arg)
|
||||||
@@ -169,7 +167,7 @@ module Builder
|
|||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(sym, *args, &block)
|
def method_missing(sym, *args, &block)
|
||||||
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(::Symbol)
|
||||||
if block
|
if block
|
||||||
_start_container(sym, args.first)
|
_start_container(sym, args.first)
|
||||||
_css_block(block)
|
_css_block(block)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
require 'builder/blankslate'
|
|
||||||
|
|
||||||
module Builder
|
module Builder
|
||||||
|
|
||||||
# Generic error for builder
|
# Generic error for builder
|
||||||
@@ -9,7 +7,7 @@ module Builder
|
|||||||
|
|
||||||
# XmlBase is a base class for building XML builders. See
|
# XmlBase is a base class for building XML builders. See
|
||||||
# Builder::XmlMarkup and Builder::XmlEvents for examples.
|
# Builder::XmlMarkup and Builder::XmlEvents for examples.
|
||||||
class XmlBase < BlankSlate
|
class XmlBase < BasicObject
|
||||||
|
|
||||||
# Create an XML markup builder.
|
# Create an XML markup builder.
|
||||||
#
|
#
|
||||||
@@ -37,10 +35,10 @@ module Builder
|
|||||||
def method_missing(sym, *args, &block)
|
def method_missing(sym, *args, &block)
|
||||||
text = nil
|
text = nil
|
||||||
attrs = nil
|
attrs = nil
|
||||||
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(::Symbol)
|
||||||
args.each do |arg|
|
args.each do |arg|
|
||||||
case arg
|
case arg
|
||||||
when Hash
|
when ::Hash
|
||||||
attrs ||= {}
|
attrs ||= {}
|
||||||
attrs.merge!(arg)
|
attrs.merge!(arg)
|
||||||
else
|
else
|
||||||
@@ -50,7 +48,7 @@ module Builder
|
|||||||
end
|
end
|
||||||
if block
|
if block
|
||||||
unless text.nil?
|
unless text.nil?
|
||||||
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
|
raise ::ArgumentError, "XmlMarkup cannot mix a text argument with a block"
|
||||||
end
|
end
|
||||||
_indent
|
_indent
|
||||||
_start_tag(sym, attrs)
|
_start_tag(sym, attrs)
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ module Builder
|
|||||||
end
|
end
|
||||||
|
|
||||||
def comment!(comment_text)
|
def comment!(comment_text)
|
||||||
_ensure_no_block block_given?
|
_ensure_no_block ::Kernel.block_given?
|
||||||
_special("<!-- ", " -->", comment_text, nil)
|
_special("<!-- ", " -->", comment_text, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -210,13 +210,13 @@ module Builder
|
|||||||
@target << "<!#{inst}"
|
@target << "<!#{inst}"
|
||||||
args.each do |arg|
|
args.each do |arg|
|
||||||
case arg
|
case arg
|
||||||
when String
|
when ::String
|
||||||
@target << %{ "#{arg}"} # " WART
|
@target << %{ "#{arg}"} # " WART
|
||||||
when Symbol
|
when ::Symbol
|
||||||
@target << " #{arg}"
|
@target << " #{arg}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if block_given?
|
if ::Kernel.block_given?
|
||||||
@target << " ["
|
@target << " ["
|
||||||
_newline
|
_newline
|
||||||
_nested_structures(block)
|
_nested_structures(block)
|
||||||
@@ -236,7 +236,7 @@ module Builder
|
|||||||
# #=> <?aaa bbb="ccc"?>
|
# #=> <?aaa bbb="ccc"?>
|
||||||
#
|
#
|
||||||
def instruct!(directive_tag=:xml, attrs={})
|
def instruct!(directive_tag=:xml, attrs={})
|
||||||
_ensure_no_block block_given?
|
_ensure_no_block ::Kernel.block_given?
|
||||||
if directive_tag == :xml
|
if directive_tag == :xml
|
||||||
a = { :version=>"1.0", :encoding=>"UTF-8" }
|
a = { :version=>"1.0", :encoding=>"UTF-8" }
|
||||||
attrs = a.merge attrs
|
attrs = a.merge attrs
|
||||||
@@ -257,7 +257,7 @@ module Builder
|
|||||||
# #=> <![CDATA[text to be included in cdata]]>
|
# #=> <![CDATA[text to be included in cdata]]>
|
||||||
#
|
#
|
||||||
def cdata!(text)
|
def cdata!(text)
|
||||||
_ensure_no_block block_given?
|
_ensure_no_block ::Kernel.block_given?
|
||||||
_special("<![CDATA[", "]]>", text, nil)
|
_special("<![CDATA[", "]]>", text, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -309,7 +309,7 @@ module Builder
|
|||||||
|
|
||||||
def _attr_value(value)
|
def _attr_value(value)
|
||||||
case value
|
case value
|
||||||
when Symbol
|
when ::Symbol
|
||||||
value.to_s
|
value.to_s
|
||||||
else
|
else
|
||||||
_escape_quote(value.to_s)
|
_escape_quote(value.to_s)
|
||||||
|
|||||||
98
activesupport/test/concern_test.rb
Normal file
98
activesupport/test/concern_test.rb
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
require 'abstract_unit'
|
||||||
|
require 'active_support/concern'
|
||||||
|
|
||||||
|
class ConcernTest < ActiveSupport::TestCase
|
||||||
|
module Baz
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
def baz
|
||||||
|
"baz"
|
||||||
|
end
|
||||||
|
|
||||||
|
def included_ran=(value)
|
||||||
|
@@included_ran = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def included_ran
|
||||||
|
@@included_ran
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
included do
|
||||||
|
self.included_ran = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def baz
|
||||||
|
"baz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module Bar
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
include Baz
|
||||||
|
|
||||||
|
def bar
|
||||||
|
"bar"
|
||||||
|
end
|
||||||
|
|
||||||
|
def baz
|
||||||
|
"bar+" + super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module Foo
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
include Bar, Baz
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@klass = Class.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_module_is_included_normally
|
||||||
|
@klass.send(:include, Baz)
|
||||||
|
assert_equal "baz", @klass.new.baz
|
||||||
|
assert @klass.included_modules.include?(ConcernTest::Baz)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_class_methods_are_extended
|
||||||
|
@klass.send(:include, Baz)
|
||||||
|
assert_equal "baz", @klass.baz
|
||||||
|
assert_equal ConcernTest::Baz::ClassMethods, (class << @klass; self.included_modules; end)[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_included_block_is_ran
|
||||||
|
@klass.send(:include, Baz)
|
||||||
|
assert_equal true, @klass.included_ran
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_modules_dependencies_are_met
|
||||||
|
@klass.send(:include, Bar)
|
||||||
|
assert_equal "bar", @klass.new.bar
|
||||||
|
assert_equal "bar+baz", @klass.new.baz
|
||||||
|
assert_equal "baz", @klass.baz
|
||||||
|
assert @klass.included_modules.include?(ConcernTest::Bar)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_dependencies_with_multiple_modules
|
||||||
|
@klass.send(:include, Foo)
|
||||||
|
assert_equal [ConcernTest::Foo, ConcernTest::Bar, ConcernTest::Baz], @klass.included_modules[0..2]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_raise_on_multiple_included_calls
|
||||||
|
assert_raises(ActiveSupport::Concern::MultipleIncludedBlocks) do
|
||||||
|
Module.new do
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
end
|
||||||
|
|
||||||
|
included do
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user