/usr/lib/ruby/1.8/innate/state/accessor.rb is in libinnate-ruby1.8 2010.07-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | module Innate
# 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.
module StateAccessor
# 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.
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
# 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] }
def state_accessor(*names, &initializer)
state_writer(*names)
state_reader(*names, &initializer)
end
# 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
def state_writer(*names)
StateAccessor.each(*names) do |key, meth|
class_eval("def %s=(obj) Thread.current[%p] = obj; end" % [meth, key])
end
end
# 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.
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
end
end
|