Inside Date.once Understanding some of the more interesting
code in the Ruby core
The Problem
The Problem
Instances of Date are immutable
The Problem
Instances of Date are immutable
Many methods involve complex calculations
The Problem
Instances of Date are immutable
Many methods involve complex calculations
Caching of results is desirable
The Problem
Instances of Date are immutable
Many methods involve complex calculations
Caching of results is desirable
Want to keep the code clean and uncluttered with caching related code
def jd_to_civil(jd, sg=GREGORIAN) if os?(jd, sg) a = jd else x = ((jd - 1867216.25) / 36524.25).floor a = jd + 1 + x - (x / 4.0).floor end b = a + 1524 c = ((b - 122.1) / 365.25).floor d = (365.25 * c).floor e = ((b - d) / 30.6001).floor dom = b - d - (30.6001 * e).floor if e <= 13 m = e - 1 y = c - 4716 else m = e - 13 y = c - 4715 end return y, m, domend
The Solution
The Solution
Write the individual methods as if they would not be cached
The Solution
Write the individual methods as if they would not be cached
Use some meta-programming magic to add caching support after the fact
def jd_to_civil ...end
once :jd_to_civil
class << self def once(*ids) # :nodoc: for id in ids module_eval <<-"end;", __FILE__, __LINE__ alias_method :__#{id.to_i}__, :#{id.to_s} private :__#{id.to_i}__ def #{id.to_s}(*args, &block) if defined? @__#{id.to_i}__ @__#{id.to_i}__ elsif ! self.frozen? @__#{id.to_i}__ ||= __#{id.to_i}__(*args, &block) else __#{id.to_i}__(*args, &block) end end end; end end
private :onceend
class << self def once(*ids) # :nodoc: for id in ids module_eval <<-"end;", __FILE__, __LINE__ alias_method :__#{id.to_i}__, :#{id.to_s} private :__#{id.to_i}__ def #{id.to_s}(*args, &block) if defined? @__#{id.to_i}__ @__#{id.to_i}__ elsif ! self.frozen? @__#{id.to_i}__ ||= __#{id.to_i}__(*args, &block) else __#{id.to_i}__(*args, &block) end end end; end end
private :onceend
class << self def once(*ids) # :nodoc: for id in ids module_eval <<-"end;", __FILE__, __LINE__ alias_method :__#{id.to_i}__, :#{id.to_s} private :__#{id.to_i}__ def #{id.to_s}(*args, &block) if defined? @__#{id.to_i}__ @__#{id.to_i}__ elsif ! self.frozen? @__#{id.to_i}__ ||= __#{id.to_i}__(*args, &block) else __#{id.to_i}__(*args, &block) end end end; end end
private :onceend
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
alias_method
puts 'cat'
class Example
def one
puts 'cat'
end
end
one
Message
class Example
alias_methodclass Example
def one
puts 'cat'
end
alias_method :two, :one
endputs 'cat'
two
one
Message
class Example
alias_methodclass Example
def one
puts 'cat'
end
alias_method :two, :one
def one
puts 'dog'
end
end
puts 'cat'twoone
Message
class Example
puts 'dog'
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
Frozen objects
Object.freeze
“Prevents further modifications to obj. A TypeError will be raised if modification is attempted. There is no way to unfreeze a frozen object.”
Object.frozen?
“Returns the freeze status of obj“
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
alias_method :__14369__, :jd_to_civilprivate :__14369__def jd_to_civil(*args, &block) if defined? @__14369__ @__14369__ elsif ! self.frozen? @__14369__ ||= __14369__(*args, &block) else __14369__(*args, &block) endend
once :jd_to_civil
class << self def once(*ids) # :nodoc: for id in ids module_eval <<-"end;", __FILE__, __LINE__ alias_method :__#{id.to_i}__, :#{id.to_s} private :__#{id.to_i}__ def #{id.to_s}(*args, &block) if defined? @__#{id.to_i}__ @__#{id.to_i}__ elsif ! self.frozen? @__#{id.to_i}__ ||= __#{id.to_i}__(*args, &block) else __#{id.to_i}__(*args, &block) end end end; end end
private :onceend
Shameless Plug
I can help you with your Ruby and/or Rails projects. Ask me how.
Mike [email protected] (company)www.SphericalImprovement.com (blog)
Top Related