barinek.com: the official website
Below you'll find a quick stream of consciousness that includes photos, quotes, code snippets, and possibly even a full post. enjoy!
Guice-ish
Playing around with dependency injection
require "singleton"
require "i18n"
require "active_support"
require "active_support/core_ext/string"
module Guice
def inject(*klass_symbols)
@injections = Hash.new unless @injections
@injections[self.name] = klass_symbols
end
def injections
@injections ||= Hash.new
@injections[self.name] || []
end
class Injector
include Singleton
def self.configure_injector(&block)
raise "Sorry, requires a block." unless block
raise "Sorry, already configured." if instance.configured
block.call(instance)
instance.instance_variable_set(:@configured, true)
instance
end
def initialize
@known_bindings = Hash.new
@known_instances = Hash.new
!@configured
end
def configured
@configured
end
def bind(klass)
@known_bindings[klass.name] = klass
end
def get_instance(klass)
raise "Sorry, not configured." unless @configured
get_deep_instance(klass)
end
def get_deep_instance(klass, parents = [])
instance = @known_instances[klass.name]
return instance if instance
if klass.kind_of?(Guice)
parameters = klass.instance_method(:initialize).parameters.collect { |param| param[1] }
if (parameters.eql?(klass.injections))
parameter_instances = parameters.collect do |parameter|
return nil if parents.include?(parameter.to_s.camelize.constantize)
get_deep_instance(parameter.to_s.camelize.constantize, parents.push(klass))
end
raise "Sorry, possible circular dependency found." if parameter_instances.any? { |parameter_instance| parameter_instance.nil? }
@known_instances[klass.name] = klass.new(*parameter_instances)
end
else
begin
@known_instances[klass.name] = klass.new
rescue
raise "Sorry, unknown constructor args."
end
end
@known_instances[klass.name]
end
end
end
require "rspec"
describe Module do
before(:all) do
@injector = Guice::Injector.configure_injector do |injector|
injector.bind(Foo)
injector.bind(Bar)
injector.bind(Cart)
injector.bind(Horse)
injector.bind(Fiz)
injector.bind(Buz)
end
end
it "can't be created" do
lambda do
Guice::Injector.new
end.should raise_error
end
it "requires a block" do
lambda do
Guice::Injector.configure_injector
end.should raise_error("Sorry, requires a block.")
end
it "complains about being configured twice" do
lambda do
Guice::Injector.configure_injector do |injector|
injector.bind(Foo)
end
end.should raise_error("Sorry, already configured.")
end
it "injects bar" do
foo = @injector.get_instance(Foo)
foo.bar.should be
end
it "complains about circular dependencies" do
lambda { @injector.get_instance(Cart) }.should raise_error("Sorry, possible circular dependency found.")
lambda { @injector.get_instance(Horse) }.should raise_error("Sorry, possible circular dependency found.")
end
it "complains about unknown constructor args" do
lambda { @injector.get_instance(Fiz) }.should raise_error("Sorry, unknown constructor args.")
end
class Foo
extend Guice
inject :bar
def initialize(bar)
@bar = bar
end
def bar
@bar
end
end
class Bar
end
class Cart
extend Guice
inject :horse
def initialize(horse)
end
end
class Horse
extend Guice
inject :cart
def initialize(cart)
end
end
class Fiz
extend Guice
inject :buz
def initialize(buz)
end
end
class Buz
def initialize(bop)
end
end
end
The new ride
The bitterness of poor quality remains long after the sweetness of low price is forgotten
benjamin franklin
Stopwatch
require 'singleton'
module Stopwatch
if defined?(ActiveRecord) && defined?(ActiveRecord::ConnectionAdapters)
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
def log_with_watcher(sql, name = "SQL", binds = [], &block)
Stopwatch.instance.event("sql '#{name}'.") do
log_without_watcher(sql, name, binds, &block)
end
end
alias_method_chain :log, :watcher
end
end
if defined?(ActionController)
ActionController::Base.class_eval do
def render_with_watcher(*args, &block)
Stopwatch.instance.event("render.") do
render_without_watcher(*args, &block)
end
end
alias_method_chain :render, :watcher
end
end
def self.watch(&block)
watcher = Watcher.instance
running = watcher.running
watcher.start
response = yield watcher
watcher.stop unless running
response
end
def self.instance
Stopwatch::Watcher.instance
end
def self.reset
Stopwatch::Watcher.instance.reset
end
class Split
attr_reader :time, :message
def initialize(time, message)
@time = time
@message = message
end
end
class Event
attr_reader :duration, :message
def initialize(duration, message)
@duration = duration
@message = message
end
end
class Tally
attr_reader :duration, :message, :count
def initialize(message)
@message = message
@duration = 0.0
@count = 0.0
end
def add(event)
@duration += event.duration
@count += 1
end
end
class Watcher
include Singleton
attr_reader :running, :splits, :events
def initialize
@running = false
@splits = []
@events = []
end
def start
return if @running
reset
@running = true
@start = Time.now
puts "\n[stopwatch @time=#{human_time(0.0)}] started."
end
def stop
@stop = Time.now
@running = false
puts "[stopwatch @time=#{human_time(@stop - @start)}] stopped."
end
def reset
@running = false
@splits = []
@events = []
end
def split(message)
split_time = Time.now
@splits.push Split.new(split_time, message)
end
def event(message)
start = Time.now
result = yield
stop = Time.now
duration = stop - start
@events.push Event.new(duration, message) if @running
result
end
def report
report_splits
report_events
end
private
def report_splits
last_time = nil
@splits.each do |split|
time = split.time
message = split.message
elapsed = last_time ? time - last_time : time - @start
last_time = time
puts "[stopwatch @time=#{human_time(elapsed)}] split #{message} "
end unless @splits.empty?
end
def report_events
tallies = {}
@events.each do |event|
tallies[event.message] = Tally.new(event.message) unless tallies[event.message]
tallies[event.message].add(event)
end
tallies.each do |key,tally|
puts "[stopwatch @time=#{human_time(tally.duration)}] event #{tally.message} (#{tally.count.to_i})"
end
end
def human_time(time)
"%.2fms" % (time * 1_000)
end
end
end
require "test/unit"
require File.expand_path(File.join(File.dirname(__FILE__), "stopwatch"))
class TestStopwatch Test::Unit::TestCase
class ExampleLogger
include Singleton
def log(message)
p message
end
def self.alias_method_chain(target, feature)
alias_method "#{target}_without_#{feature}", target
alias_method target, "#{target}_with_#{feature}"
end
end
ExampleLogger.class_eval do
def log_with_test(message, &block)
Stopwatch.instance.event("a") do
log_without_test(message, &block)
end
end
alias_method_chain :log, :test
end
def setup
Stopwatch.reset
end
def test_watch
assert(!Stopwatch.instance.running)
Stopwatch.watch do
assert(Stopwatch.instance.running)
end
assert(!Stopwatch.instance.running)
end
def test_splits
Stopwatch.watch do |watcher|
watcher.split("a")
watcher.split("b")
watcher.split("c")
end
assert_equal(Stopwatch.instance.splits.size, 3)
assert_equal(Stopwatch.instance.splits.collect { |split| split.message }, ["a", "b", "c"])
end
def test_nested
Stopwatch.watch do |watcher|
watcher.split("a")
Stopwatch.watch do |watcher|
watcher.split("b")
end
assert(Stopwatch.instance.running)
end
assert_equal(Stopwatch.instance.splits.size, 2)
assert_equal(Stopwatch.instance.splits.collect { |split| split.message }, ["a", "b"])
end
def test_split_report
Stopwatch.watch do |watcher|
watcher.split("a")
watcher.split("b")
watcher.split("c")
watcher.report
end
end
def test_events
Stopwatch.watch do |watcher|
ExampleLogger.instance.log("message")
Stopwatch.instance.event("b") do
end
end
assert_equal(Stopwatch.instance.events.size, 2)
assert_equal(Stopwatch.instance.events.collect { |event| event.message }, ["a", "b"])
end
def test_no_events
Stopwatch.watch do |watcher|
end
ExampleLogger.instance.log("message")
Stopwatch.instance.event("b") do
end
assert_equal(Stopwatch.instance.events.size, 0)
end
end
Simple Trie for Autocomplete
require 'test/unit'
class Trie
def initialize()
@root = TrieNode.new
@entry_count = 0
end
def empty?
@entry_count == 0;
end
def size
@entry_count
end
def add(key, value)
return if key.nil? || key.empty?
current_node = @root
key.each_char { |character|
next_node = current_node.get(character)
next_node = current_node.add(character) unless next_node
current_node = next_node
}
current_node
current_node.value = value
@entry_count += 1
end
def contains(str)
# todo...
end
def find(string)
results = []
(0..string.length-1).each { |start_index|
start_index
current_node = @root
(start_index..string.length-1).each { |i|
ch = string[i].chr
current_node = current_node.get(ch)
break if current_node.nil?
results.push current_node.values if current_node.values?
}
}
results
end
class TrieNode
def initialize()
@children = Hash.new
end
def value=(value)
if (@values.nil?)
@values = Array.new
end
@values.push value
end
def get(character)
@children[character]
end
def add(character)
node = TrieNode.new
@children[character] = node
node
end
def values
@values
end
def values?
!@values.nil?
end
end
end
class TriTest Test::Unit::TestCase
def test_empty?
trie = Trie.new
assert(trie.empty?)
trie.add("key", "value")
assert(!trie.empty?)
end
def test_size
trie = Trie.new
trie.add("key", "value")
assert_equal(1, trie.size)
end
def test_ignores_nil_or_empty_string
trie = Trie.new
trie.add("", "value")
trie.add(nil, "value")
assert(trie.empty?)
end
def test_find
trie = Trie.new
trie.add("key", "value")
assert_equal(1, trie.find("key").size)
trie.add("keys", "value")
assert_equal(2, trie.find("keys").size)
end
def test_allows_duplicates
trie = Trie.new
trie.add("key", "value")
trie.add("key", "value")
assert(!trie.empty?)
end
end
Handy Git Commands
source /usr/local/etc/bash_completion.d/git-completion.bash
alias gits="git status"
git add -p
[alias]
staged = diff --cached
[color]
status = auto
branch = auto
diff = auto
Chris’s Reading List
C
- C Programming Language (2nd Edition) by Brian W. Kernighan and Dennis M. Ritchie
- Java Programming Language, The (4th Edition) by Ken Arnold, James Gosling and David Holmes
- Thinking in Java (4th Edition) by Bruce Eckel
- Advanced Effective Java (2nd Edition) by Joshua Bloch
- Advanced Java Concurrency in Practice by Brian Goetz, Tim Peierls, Joshua Bloch and Joseph Bowbeer
- Learn to Program, Second Edition (The Facets of Ruby Series) by Chris Pine
- Programming Ruby 1.9: The Pragmatic Programmers’ Guide (Facets of Ruby) by Dave Thomas, Chad Fowler and Andy Hunt
- Algorithms in Java, Parts 1-4 (3rd Edition) (Pts.1-4) by Robert Sedgewick
- Test Driven Development: By Example by Kent Beck
- Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides
- Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant and William Opdyke
- Refactoring to Patterns by Joshua Kerievsky
- Patterns of Enterprise Application Architecture by Martin Fowler
- Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions by Gregor Hohpe and Bobby Woolf
- Agile Web Development with Rails (Pragmatic Programmers) by Sam Ruby, Dave Thomas and David Heinemeier Hansson
- Advanced Restful Web Services by Leonard Richardson, Sam Ruby and David Heinemeier Hansson
- Extreme Programming Explained: Embrace Change (2nd Edition) by Kent Beck and Cynthia Andres
- Agile Software Development with Scrum (Series in Agile Software Development) by Ken
- Schwaber and Mike Beedle
- Joe Celko’s SQL for Smarties, Fourth Edition: Advanced SQL Programming (The Morgan Kaufmann Series in Data Management Systems) by Joe Celko
- Rework by Jason Fried and David Heinemeier Hansson
- Getting Real: The smarter, faster, easier way to build a successful web application by Jason Fried, Heinemeier David Hansson and Matthew Linderman
- Pragmatic Unit Testing in Java with JUnit by Andy Hunt and Dave Thomas
- Pragmatic Project Automation: How to Build, Deploy, and Monitor Java Apps by Mike Clark
- Pragmatic Version Control Using Git (Pragmatic Starter Kit) by Travis Swicegood
- The Pragmatic Programmer: From Journeyman to Master by Andrew Hunt and David Thomas
whisky tour - http://whiskygeeks.com/
Surfing in Glenwood Springs (I shot the video)
USGA Handicap Index Effective: 8/1/11 - 12.3
http://www.ghin.com/




