Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Update initializable

  • Loading branch information...
commit df95f165708b6baf93dcc6eff6911ee159cab34c 1 parent da62a7c
Yehuda Katz + Carl Lerche authored
Showing with 144 additions and 61 deletions.
  1. +59 −51 railties/lib/rails/initializable.rb
  2. +85 −10 railties/test/initializable_test.rb
View
110 railties/lib/rails/initializable.rb
@@ -1,78 +1,86 @@
module Rails
module Initializable
-
- # A collection of initializers
- class Collection
- def initialize(context)
- @context = context
- @keys = []
- @values = {}
- @ran = false
+ def self.included(klass)
+ klass.instance_eval do
+ extend Rails::Initializable
+ extend Rails::Initializable::ClassMethodsWhenIncluded
+ include Rails::Initializable::InstanceMethodsWhenIncluded
end
+ end
- def run
- return self if @ran
- each do |key, initializer|
- @context.class_eval(&initializer.block)
- end
- @ran = true
- self
- end
+ def self.extended(klass)
+ klass.extend Initializer
+ end
- def [](key)
- keys, values = merge_with_parent
- values[key.to_sym]
+ class Collection < Array
+ def initialize(klasses)
+ klasses.each do |klass|
+ klass.added_initializers.each do |initializer|
+ index = if initializer.before
+ index_for(initializer.before)
+ elsif initializer.after
+ index_for(initializer.after) + 1
+ else
+ length
+ end
+
+ insert(index, initializer)
+ end
+ end
end
- def []=(key, value)
- key = key.to_sym
- @keys |= [key]
- @values[key] = value
+ def index_for(name)
+ inst = find {|i| i.name == name }
+ inst && index(inst)
end
- def each
- keys, values = merge_with_parent
- keys.each { |k| yield k, values[k] }
- self
- end
+ end
- protected
+ attr_reader :added_initializers
- attr_reader :keys, :values
+ # When you include Rails::Initializable, this method will be on instances
+ # of the class included into. When you extend it, it will be on the
+ # class or module itself.
+ #
+ # The #initializers method is set up to return the right list of
+ # initializers for the context in question.
+ def initialize!
+ return if @_initialized
- private
+ initializers.each {|initializer| instance_eval(&initializer.block) }
- def merge_with_parent
- keys, values = [], {}
+ @_initialized = true
+ end
- if @context.is_a?(Class) && @context.superclass.is_a?(Initializable)
- parent = @context.superclass.initializers
- keys, values = parent.keys, parent.values
- end
+ module Initializer
+ Initializer = Struct.new(:name, :before, :after, :block, :global)
- values = values.merge(@values)
- return keys | @keys, values
+ def all_initializers
+ klasses = ancestors.select {|klass| klass.is_a?(Initializable) }.reverse
+ initializers = Collection.new(klasses)
end
- end
-
- class Initializer
- attr_reader :name, :options, :block
+ alias initializers all_initializers
- def initialize(name, options = {}, &block)
- @name, @options, @block = name, options, block
+ def initializer(name, options = {}, &block)
+ @added_initializers ||= []
+ @added_initializers <<
+ Initializer.new(name, options[:before], options[:after], block, options[:global])
end
end
- def initializer(name, options = {}, &block)
- @initializers ||= Collection.new(self)
- @initializers[name] = Initializer.new(name, options, &block)
- end
+ module ClassMethodsWhenIncluded
+ def initializers
+ all_initializers.select {|i| i.global == true }
+ end
- def initializers
- @initializers ||= Collection.new(self)
end
+ module InstanceMethodsWhenIncluded
+ def initializers
+ self.class.all_initializers.reject {|i| i.global == true }
+ end
+ end
end
extend Initializable
View
95 railties/test/initializable_test.rb
@@ -31,38 +31,113 @@ module Word
end
end
+ class Parent
+ extend Rails::Initializable
+
+ initializer :one do
+ $arr << 1
+ end
+
+ initializer :two do
+ $arr << 2
+ end
+ end
+
+ class Child < Parent
+ extend Rails::Initializable
+
+ initializer :three, :before => :one do
+ $arr << 3
+ end
+
+ initializer :four, :after => :one do
+ $arr << 4
+ end
+ end
+
+ class Parent
+ initializer :five, :before => :one do
+ $arr << 5
+ end
+ end
+
+ class Instance
+ include Rails::Initializable
+
+ initializer :one do
+ $arr << 1
+ end
+
+ initializer :two do
+ $arr << 2
+ end
+
+ initializer :three, :global => true do
+ $arr << 3
+ end
+
+ initializer :four, :global => true do
+ $arr << 4
+ end
+ end
+
class Basic < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
test "initializers run" do
- Foo.initializers.run
+ Foo.initialize!
assert_equal 1, Foo.foo
end
test "initializers are inherited" do
- Bar.initializers.run
+ Bar.initialize!
assert_equal [1, 1], [Bar.foo, Bar.bar]
end
test "initializers only get run once" do
- Foo.initializers.run
- Foo.initializers.run
+ Foo.initialize!
+ Foo.initialize!
assert_equal 1, Foo.foo
end
test "running initializers on children does not effect the parent" do
- Bar.initializers.run
+ Bar.initialize!
assert_nil Foo.foo
assert_nil Foo.bar
end
- test "inherited initializers are the same objects" do
- assert Foo.initializers[:foo].eql?(Bar.initializers[:foo])
- end
-
test "initializing with modules" do
- Word.initializers.run
+ Word.initialize!
assert_equal "bird", $word
end
end
+
+ class BeforeAfter < ActiveSupport::TestCase
+ test "running on parent" do
+ $arr = []
+ Parent.initialize!
+ assert_equal [5, 1, 2], $arr
+ end
+
+ test "running on child" do
+ $arr = []
+ Child.initialize!
+ assert_equal [5, 3, 1, 4, 2], $arr
+ end
+ end
+
+ class InstanceTest < ActiveSupport::TestCase
+ test "running locals" do
+ $arr = []
+ instance = Instance.new
+ instance.initialize!
+ assert_equal [1, 2], $arr
+ end
+
+ test "running globals" do
+ $arr = []
+ Instance.initialize!
+ assert_equal [3, 4], $arr
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.