diff --git a/app/models/address.rb b/app/models/address.rb deleted file mode 100644 index fee2f2cb..00000000 --- a/app/models/address.rb +++ /dev/null @@ -1,89 +0,0 @@ -# Value object for addresses. - -class Address - # List of readable attributes. - FIELDS = [:street, :street2, :city, :state, :zip, :coords] - FIELDS.each do |f| - attr_reader f - end - - # Initializes a new #Address object from a #Hash of fields or separate arguments in the order given in FIELDS. - def initialize(*args) - case args.length - when 0 - # do nothing - when 1 - if args[0].kind_of?(Hash) - set_from_hash args[0] - else - raise ArgumentError, "expected Hash, got #{args[0].class.name}" - end - when FIELDS.length - set_from_array args - else - raise ArgumentError, "expected 0, 1, or #{FIELDS.length} arguments, got #{args.length}" - end - if !@state.blank? and !@state.kind_of?(State) - @state = State.find(@state) - end - end - - # Returns the #Country that the address belongs to. - def country - state.country - end - - # Returns the #State that the address belongs to, or a #QuietNil if there is no state. - def state - @state || QuietNil.instance - end - - # Converts #Address to a #String. - # - # Valid values of +format+: - # :geo:: Address in comma-separated format for feeding to geocoder. - def to_s(format = :geo) - case format - when :geo - "#{street}, #{city}, #{state.code}, #{zip}, #{country.code}" - else - raise ArgumentError, "unknown format parameter: #{format}" - end - end - - # Compares two Addresses by value. - def ==(other) - if other.kind_of?(Address) - FIELDS.each do |f| - if self.send(f) != other.send(f) - return false - end - end - return true - else - return false - end - end - - protected - - # TODO: set_from_* methods should perhaps become public. - - # Sets instance variables from the supplied #Hash. - def set_from_hash(hash) - FIELDS.each do |f| - if hash.has_key?(f) - eval "@#{f.to_s} = hash[:#{f.to_s}]" - end - end - end - - # Sets instance variables from the supplied #Array, in the same order as #FIELDS. - def set_from_array(array) - hash = {} - FIELDS.each_index do |i| - hash[FIELDS[i]] = array[i] - end - set_from_hash hash - end -end diff --git a/app/models/country.rb b/app/models/country.rb deleted file mode 100644 index 52e53577..00000000 --- a/app/models/country.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Country < ActiveRecord::Base - validates_length_of :code, :is => 2 - validates_presence_of :name -end diff --git a/app/models/state.rb b/app/models/state.rb deleted file mode 100644 index 4faebfaa..00000000 --- a/app/models/state.rb +++ /dev/null @@ -1,10 +0,0 @@ -class State < ActiveRecord::Base - belongs_to :country - validates_presence_of :country_id - - validate do |state| - if state.code.blank? ^ state.name.blank? - state.errors.add_to_base("Code and name must both be blank or must both be nonblank.") - end - end -end diff --git a/lib/quiet_nil.rb b/lib/quiet_nil.rb deleted file mode 100644 index 2823963b..00000000 --- a/lib/quiet_nil.rb +++ /dev/null @@ -1,13 +0,0 @@ -# This is just like NilClass, but when methods are called on a QuietNil, they just return the QuietNil without raising an exception. -# -# WARNING: This class is easy to abuse. Please resist temptation! - -class QuietNil < ActiveSupport::BasicObject - # Implementation is yanked from http://coderrr.wordpress.com/2007/09/15/the-ternary-destroyer/ - include Singleton - - def method_missing(method, *args, &b) - return self unless nil.respond_to? method - nil.send(method, *args, &b) rescue self - end -end diff --git a/spec/models/quiet_nil_spec.rb b/spec/models/quiet_nil_spec.rb deleted file mode 100644 index 33271232..00000000 --- a/spec/models/quiet_nil_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') - -describe QuietNil do - it "should be a valid class" do - QuietNil.class.should == Class - end - - it "should respond as nil to predefined methods" do - qn = QuietNil.instance - qn.should be_nil - pending "can't figure out how to convert to boolean" do - (!!qn).should be_false - end - qn.to_s.should == nil.to_s - qn.to_a.should == nil.to_a - end - - it "should not whine when it receives methods that aren't defined on nil" do - qn = QuietNil.instance - p = lambda {qn.foobarbaz(1, 2, 3)} - p.should_not raise_error - - # We're overriding equality, so we can't do - # (p.call.equal? qn).should be_true - # Instead: - p.call.should be_nil - lambda {p.call.quux(:quuuux)}.should_not raise_error - end -end diff --git a/vendor/plugins/acts_as_addressed/lib/acts/addressed/address.rb b/vendor/plugins/acts_as_addressed/lib/acts/addressed/address.rb new file mode 100644 index 00000000..398f60c9 --- /dev/null +++ b/vendor/plugins/acts_as_addressed/lib/acts/addressed/address.rb @@ -0,0 +1,91 @@ +# Value object for addresses. + +module Acts::Addressed + class Address + # List of readable attributes. + FIELDS = [:street, :street2, :city, :state, :zip, :coords] + FIELDS.each do |f| + attr_reader f + end + + # Initializes a new #Address object from a #Hash of fields or separate arguments in the order given in FIELDS. + def initialize(*args) + case args.length + when 0 + # do nothing + when 1 + if args[0].kind_of?(Hash) + set_from_hash args[0] + else + raise ArgumentError, "expected Hash, got #{args[0].class.name}" + end + when FIELDS.length + set_from_array args + else + raise ArgumentError, "expected 0, 1, or #{FIELDS.length} arguments, got #{args.length}" + end + if !@state.blank? and !@state.kind_of?(State) + @state = State.find(@state) + end + end + + # Returns the #Country that the address belongs to. + def country + state.country + end + + # Returns the #State that the address belongs to, or a #QuietNil if there is no state. + def state + @state || QuietNil.instance + end + + # Converts #Address to a #String. + # + # Valid values of +format+: + # :geo:: Address in comma-separated format for feeding to geocoder. + def to_s(format = :geo) + case format + when :geo + "#{street}, #{city}, #{state.code}, #{zip}, #{country.code}" + else + raise ArgumentError, "unknown format parameter: #{format}" + end + end + + # Compares two Addresses by value. + def ==(other) + if other.kind_of?(Address) + FIELDS.each do |f| + if self.send(f) != other.send(f) + return false + end + end + return true + else + return false + end + end + + protected + + # TODO: set_from_* methods should perhaps become public. + + # Sets instance variables from the supplied #Hash. + def set_from_hash(hash) + FIELDS.each do |f| + if hash.has_key?(f) + eval "@#{f.to_s} = hash[:#{f.to_s}]" + end + end + end + + # Sets instance variables from the supplied #Array, in the same order as #FIELDS. + def set_from_array(array) + hash = {} + FIELDS.each_index do |i| + hash[FIELDS[i]] = array[i] + end + set_from_hash hash + end + end +end diff --git a/vendor/plugins/acts_as_addressed/lib/acts/addressed/country.rb b/vendor/plugins/acts_as_addressed/lib/acts/addressed/country.rb new file mode 100644 index 00000000..1888a8a6 --- /dev/null +++ b/vendor/plugins/acts_as_addressed/lib/acts/addressed/country.rb @@ -0,0 +1,7 @@ +module Acts::Addressed + class Country < ActiveRecord::Base + has_many :states + validates_length_of :code, :is => 2 + validates_presence_of :name + end +end \ No newline at end of file diff --git a/vendor/plugins/acts_as_addressed/lib/acts/addressed/quiet_nil.rb b/vendor/plugins/acts_as_addressed/lib/acts/addressed/quiet_nil.rb new file mode 100644 index 00000000..94d78fc9 --- /dev/null +++ b/vendor/plugins/acts_as_addressed/lib/acts/addressed/quiet_nil.rb @@ -0,0 +1,15 @@ +# This is just like NilClass, but when methods are called on a QuietNil, they just return the QuietNil without raising an exception. +# +# WARNING: This class is easy to abuse. Please resist temptation! + +module Acts::Addressed + class QuietNil < ActiveSupport::BasicObject + # Implementation is yanked from http://coderrr.wordpress.com/2007/09/15/the-ternary-destroyer/ + include Singleton + + def method_missing(method, *args, &b) + return self unless nil.respond_to? method + nil.send(method, *args, &b) rescue self + end + end +end \ No newline at end of file diff --git a/vendor/plugins/acts_as_addressed/lib/acts/addressed/state.rb b/vendor/plugins/acts_as_addressed/lib/acts/addressed/state.rb new file mode 100644 index 00000000..3397bbff --- /dev/null +++ b/vendor/plugins/acts_as_addressed/lib/acts/addressed/state.rb @@ -0,0 +1,12 @@ +module Acts::Addressed + class State < ActiveRecord::Base + belongs_to :country + validates_presence_of :country_id + + validate do |state| + if state.code.blank? ^ state.name.blank? + state.errors.add_to_base("Code and name must both be blank or must both be nonblank.") + end + end + end +end diff --git a/spec/models/address_spec.rb b/vendor/plugins/acts_as_addressed/spec/acts/addressed/address_spec.rb similarity index 100% rename from spec/models/address_spec.rb rename to vendor/plugins/acts_as_addressed/spec/acts/addressed/address_spec.rb diff --git a/spec/models/country_spec.rb b/vendor/plugins/acts_as_addressed/spec/acts/addressed/country_spec.rb similarity index 60% rename from spec/models/country_spec.rb rename to vendor/plugins/acts_as_addressed/spec/acts/addressed/country_spec.rb index e206bbf5..3b6ee906 100644 --- a/spec/models/country_spec.rb +++ b/vendor/plugins/acts_as_addressed/spec/acts/addressed/country_spec.rb @@ -1,8 +1,17 @@ -require File.dirname(__FILE__) + '/../spec_helper' +require File.dirname(__FILE__) + '/../../spec_helper' -describe Country, "(validations)" do +require 'acts/addressed/country' + +describe Acts::Addressed::Country, "(associations)" do + it "should have many states" do + assoc = Acts::Addressed::Country.reflect_on_association(:states) + assoc.should_not be_nil + assoc.macro.should == :has_many + end +end +describe Acts::Addressed::Country, "(validations)" do before(:each) do - @country = Country.new + @country = Acts::Addressed::Country.new @country.code = "AA" # arbitrary value of length 2 @country.name = "x" # arbitrary value end diff --git a/vendor/plugins/acts_as_addressed/spec/acts/addressed/quiet_nil_spec.rb b/vendor/plugins/acts_as_addressed/spec/acts/addressed/quiet_nil_spec.rb new file mode 100644 index 00000000..5aadab52 --- /dev/null +++ b/vendor/plugins/acts_as_addressed/spec/acts/addressed/quiet_nil_spec.rb @@ -0,0 +1,31 @@ +require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') + +module Acts::Addressed + describe QuietNil do + it "should be a valid class" do + QuietNil.class.should == Class + end + + it "should respond as nil to predefined methods" do + qn = QuietNil.instance + qn.should be_nil + pending "can't figure out how to convert to boolean" do + (!!qn).should be_false + end + qn.to_s.should == nil.to_s + qn.to_a.should == nil.to_a + end + + it "should not whine when it receives methods that aren't defined on nil" do + qn = QuietNil.instance + p = lambda {qn.foobarbaz(1, 2, 3)} + p.should_not raise_error + + # We're overriding equality, so we can't do + # (p.call.equal? qn).should be_true + # Instead: + p.call.should be_nil + lambda {p.call.quux(:quuuux)}.should_not raise_error + end + end +end diff --git a/spec/models/state_spec.rb b/vendor/plugins/acts_as_addressed/spec/acts/addressed/state_spec.rb similarity index 100% rename from spec/models/state_spec.rb rename to vendor/plugins/acts_as_addressed/spec/acts/addressed/state_spec.rb diff --git a/vendor/plugins/acts_as_addressed/spec/blueprints.rb b/vendor/plugins/acts_as_addressed/spec/blueprints.rb new file mode 100644 index 00000000..63aa0301 --- /dev/null +++ b/vendor/plugins/acts_as_addressed/spec/blueprints.rb @@ -0,0 +1,23 @@ +# Object blueprints for Machinist. +require 'machinist/active_record' +require 'sham' +require 'faker' +LETTERS = ('A'..'Z').to_a + +module Acts::Addressed + Country.blueprint do + name {Sham.generic_name} + code + end + + State.blueprint do + country + name {Sham.generic_name} + code + end +end + +Sham.define do + generic_name {Faker::Name.last_name} + code {LETTERS.rand + LETTERS.rand} # 2 random letters +end \ No newline at end of file diff --git a/vendor/plugins/acts_as_addressed/spec/spec_helper.rb b/vendor/plugins/acts_as_addressed/spec/spec_helper.rb index 8e240e9c..977b28a8 100644 --- a/vendor/plugins/acts_as_addressed/spec/spec_helper.rb +++ b/vendor/plugins/acts_as_addressed/spec/spec_helper.rb @@ -2,5 +2,73 @@ require 'rubygems' require 'spec' +# Require ActiveRecord so we can test AR-specific stuff. +require 'active_record' -require 'acts_as_addressed' \ No newline at end of file +# Use an in-memory database as described at http://www.bryandonovan.com/ruby/2008/02/20/writing-tests-for-acts_as-plugins/ . +ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") + +require 'acts_as_addressed' + +# Set up autoloading for models. +pwd = Dir.pwd +Dir.chdir(File.dirname(__FILE__) + '/../lib/acts/addressed') +Acts::Addressed.module_eval do + Dir['*.rb'].each do |file| + module_name = File.basename(file, '.rb').camelize.to_sym + autoload module_name, File.expand_path(file) + end +end +Dir.chdir pwd + +require 'machinist' +require 'blueprints' + +Spec::Runner.configure do |config| + # I think we can get away with DB setup and teardown before each spec -- it's in memory so should be fast. + + config.before :each do + setup_db + # Reset Shams for Machinist. + Sham.reset + end + + config.after :each do + teardown_db + end +end + +def setup_db + silent do + ActiveRecord::Base.logger + ActiveRecord::Schema.define(:version => 1) do + create_table "countries", :force => true do |t| + t.column "code", :string, :limit => 2, :null => false + t.column "name", :string, :null => false + end + + create_table "states", :force => true do |t| + t.column "country_id", :integer + t.column "code", :string, :limit => 10, :null => false + t.column "name", :string, :null => false + end + end + end +end + +def teardown_db + silent do + ActiveRecord::Base.connection.tables.each do |table| + ActiveRecord::Base.connection.drop_table(table) + end + end +end + +# Run the block with $stdout temporarily silenced. +# This is meant to be used to prevent schema declarations from appearing in spec output. +def silent(stdout = StringIO.new, &block) + old_stdout = $stdout + $stdout = stdout + yield + $stdout = old_stdout +end