Module: Innate::StateAccessor

Included in:
Trinity
Defined in:
/home/manveru/github/ramaze/ramaze.net/tmp/git/innate/lib/innate/state/accessor.rb

Overview

Simplify accessing Thread.current variables.

Example:

class Foo include Innate::StateAccessor state_accessor :session

def calculate
  session[:num1] + session[:num2]
end

end

Foo#calculate can now be called from anywhere in your application and it will have direct access to the session in the current request/response cycle in a thread-safe way without the need to explicitly pass the session along.

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) each(*names)

Iterate over the names and yield accordingly. names are either objects responding to #to_sym or hashes.

It's only used within this module to make the code readable.

Used below.



29
30
31
32
33
34
35
36
37
38
39
40
# File '/home/manveru/github/ramaze/ramaze.net/tmp/git/innate/lib/innate/state/accessor.rb', line 29

def self.each(*names)
  names.each do |name|
    if name.respond_to?(:to_hash)
      name.to_hash.each do |key, meth|
        yield(key.to_sym, meth.to_sym)
      end
    else
      key = meth = name.to_sym
      yield(key, meth)
    end
  end
end

Instance Method Details

- (Object) state_accessor(*names, &initializer)

Combined state_writer and state_reader. +initializer+ is a block that may be given and its result will be the new value in case the method created by state_reader was never called before and the value wasn't set before.

Example:

state_accessor(:session) state_accessor(:user){ session[:user] }



52
53
54
55
# File '/home/manveru/github/ramaze/ramaze.net/tmp/git/innate/lib/innate/state/accessor.rb', line 52

def state_accessor(*names, &initializer)
  state_writer(*names)
  state_reader(*names, &initializer)
end

- (Object) state_reader(*names, &initializer)

Reader accessor for Thread.current[key]

Example:

class Foo include Innate::StateAccessor state_reader(:session) state_reader(:random){ rand(100_000) }

def calculate
  val1 = session[:num1] + session[:num2] + random
  val2 = session[:num1] + session[:num2] + random
  val1 == val2 # => true
end

end

NOTE: If given +initializer+, there will be some performance impact since we cannot use class_eval and have to use define_method instead, we also have to check every time whether the initializer was executed already.

In 1.8.x the overhead of define_method is 3x that of class_eval/def In 1.9.1 the overhead of define_method is 1.5x that of class_eval/def

This may only be an issue for readers that are called a lot of times.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File '/home/manveru/github/ramaze/ramaze.net/tmp/git/innate/lib/innate/state/accessor.rb', line 114

def state_reader(*names, &initializer)
  StateAccessor.each(*names) do |key, meth|
    if initializer
      define_method(meth) do
        unless Thread.current.key?(key)
          Thread.current[key] = instance_eval(&initializer)
        else
          Thread.current[key]
        end
      end
    else
      class_eval("def %s; Thread.current[%p]; end" % [meth, key])
    end
  end
end

- (Object) state_writer(*names)

Writer accessor to Thread.current[key]=

Example:

class Foo include Innate::StateAccessor state_writer(:result)

def calculate
  self.result = 42
end

end

class Bar include Innate::StateAccessor state_reader(:result)

def calculcate
  result * result
end

end

Foo.new.calculate # => 42 Bar.new.calculate # => 1764



82
83
84
85
86
# File '/home/manveru/github/ramaze/ramaze.net/tmp/git/innate/lib/innate/state/accessor.rb', line 82

def state_writer(*names)
  StateAccessor.each(*names) do |key, meth|
    class_eval("def %s=(obj) Thread.current[%p] = obj; end" % [meth, key])
  end
end