Added Rubocop.

This commit is contained in:
dblock 2014-03-30 20:44:13 -04:00
parent 578f829eb2
commit 881c6edfe7
27 changed files with 606 additions and 545 deletions

36
.rubocop.yml Normal file
View File

@ -0,0 +1,36 @@
AllCops:
Excludes:
- vendor/**
- bin/**
- .bundle/**
LineLength:
Enabled: false
MethodLength:
Enabled: false
ClassLength:
Enabled: false
Documentation:
# don't require classes to be documented
Enabled: false
Encoding:
# no need to always specify encoding
Enabled: false
Lambda:
# TODO: replace all lambda with -> or Proc
Enabled: false
CyclomaticComplexity:
Enabled: false
DoubleNegation:
Enabled: false
CaseEquality:
Enabled: false

View File

@ -1,6 +1,7 @@
## Next Release
* Removed support for Ruby 1.8.7 - [@dblock](https://github.com/dblock).
* Ruby style now enforced with Rubocop - [@dblock](https://github.com/dblock).
* [#107](https://github.com/intridea/hashie/pull/107): Fixed excessive value conversions causing poor performance of deep merge in Hashie::Mash - [@davemitchell](https://github.com/dblock), [@dblock](https://github.com/dblock).
* [#69](https://github.com/intridea/hashie/issues/69): Fixed assigning multiple properties in Hashie::Trash - [@einzige](https://github.com/einzige).
* [#100](https://github.com/intridea/hashie/pull/100): IndifferentAccess#store will respect indifference - [@jrochkind](https://github.com/jrochkind).

View File

@ -6,3 +6,5 @@ platforms :rbx do
end
gemspec
gem 'rubocop', '~> 0.19.1'

View File

@ -6,8 +6,10 @@ Bundler::GemHelper.install_tasks
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new do |spec|
# spec.libs << 'lib' << 'spec'
spec.pattern = 'spec/**/*_spec.rb'
end
task :default => :spec
require 'rubocop/rake_task'
Rubocop::RakeTask.new(:rubocop)
task default: [:rubocop, :spec]

View File

@ -3,10 +3,10 @@ require 'hashie/hash'
module Hashie
#
# A Clash is a "Chainable Lazy Hash". Inspired by libraries such as Arel,
# a Clash allows you to chain together method arguments to build a
# a Clash allows you to chain together method arguments to build a
# hash, something that's especially useful if you're doing something
# like constructing a complex options hash. Here's a basic example:
#
#
# c = Hashie::Clash.new.conditions(:foo => 'bar').order(:created_at)
# c # => {:conditions => {:foo => 'bar'}, :order => :created_at}
#
@ -25,7 +25,7 @@ module Hashie
class ChainError < ::StandardError; end
# The parent Clash if this Clash was created via chaining.
attr_reader :_parent
# Initialize a new clash by passing in a Hash to
# convert and, optionally, the parent to which this
# Clash is chained.
@ -35,7 +35,7 @@ module Hashie
self[k.to_sym] = v
end
end
# Jump back up a level if you are using bang method
# chaining. For example:
#
@ -43,44 +43,44 @@ module Hashie
# c.baz!.foo(123) # => c[:baz]
# c.baz!._end! # => c
def _end!
self._parent
_parent
end
def id(*args) #:nodoc:
method_missing(:id, *args)
end
def merge_store(key, *args) #:nodoc:
case args.length
when 1
val = args.first
val = self[key].merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
else
val = args
when 1
val = args.first
val = self[key].merge(val) if self[key].is_a?(::Hash) && val.is_a?(::Hash)
else
val = args
end
self[key.to_sym] = val
self
end
def method_missing(name, *args) #:nodoc:
name = name.to_s
if name.match(/!$/) && args.empty?
key = name[0...-1].to_sym
if self[key].nil?
self[key] = Clash.new({}, self)
elsif self[key].is_a?(::Hash) && !self[key].is_a?(Clash)
self[key] = Clash.new(self[key], self)
else
raise ChainError, "Tried to chain into a non-hash key."
fail ChainError, 'Tried to chain into a non-hash key.'
end
self[key]
elsif args.any?
key = name.to_sym
self.merge_store(key, *args)
merge_store(key, *args)
end
end
end
end
end

View File

@ -30,17 +30,17 @@ module Hashie
def self.property(property_name, options = {})
property_name = property_name.to_sym
self.properties << property_name
properties << property_name
if options.has_key?(:default)
self.defaults[property_name] = options[:default]
elsif self.defaults.has_key?(property_name)
self.defaults.delete property_name
if options.key?(:default)
defaults[property_name] = options[:default]
elsif defaults.key?(property_name)
defaults.delete property_name
end
unless instance_methods.map { |m| m.to_s }.include?("#{property_name}=")
define_method(property_name) { |&block| self.[](property_name.to_s, &block) }
property_assignment = property_name.to_s.concat("=").to_sym
property_assignment = property_name.to_s.concat('=').to_sym
define_method(property_assignment) { |value| self.[]=(property_name.to_s, value) }
end
@ -61,9 +61,9 @@ module Hashie
def self.inherited(klass)
super
(@subclasses ||= Set.new) << klass
klass.instance_variable_set('@properties', self.properties.dup)
klass.instance_variable_set('@defaults', self.defaults.dup)
klass.instance_variable_set('@required_properties', self.required_properties.dup)
klass.instance_variable_set('@properties', properties.dup)
klass.instance_variable_set('@defaults', defaults.dup)
klass.instance_variable_set('@required_properties', required_properties.dup)
end
# Check to see if the specified property has already been
@ -122,15 +122,15 @@ module Hashie
end
def merge(other_hash)
new_dash = self.dup
other_hash.each do |k,v|
new_dash = dup
other_hash.each do |k, v|
new_dash[k] = block_given? ? yield(k, self[k], v) : v
end
new_dash
end
def merge!(other_hash)
other_hash.each do |k,v|
other_hash.each do |k, v|
self[k] = block_given? ? yield(k, self[k], v) : v
end
self
@ -145,35 +145,34 @@ module Hashie
private
def initialize_attributes(attributes)
attributes.each_pair do |att, value|
self[att] = value
end if attributes
end
def initialize_attributes(attributes)
attributes.each_pair do |att, value|
self[att] = value
end if attributes
end
def assert_property_exists!(property)
unless self.class.property?(property)
raise NoMethodError, "The property '#{property}' is not defined for this Dash."
end
def assert_property_exists!(property)
unless self.class.property?(property)
fail NoMethodError, "The property '#{property}' is not defined for this Dash."
end
end
def assert_required_properties_set!
self.class.required_properties.each do |required_property|
assert_property_set!(required_property)
end
def assert_required_properties_set!
self.class.required_properties.each do |required_property|
assert_property_set!(required_property)
end
end
def assert_property_set!(property)
if send(property).nil?
raise ArgumentError, "The property '#{property}' is required for this Dash."
end
def assert_property_set!(property)
if send(property).nil?
fail ArgumentError, "The property '#{property}' is required for this Dash."
end
end
def assert_property_required!(property, value)
if self.class.required?(property) && value.nil?
raise ArgumentError, "The property '#{property}' is required for this Dash."
end
def assert_property_required!(property, value)
if self.class.required?(property) && value.nil?
fail ArgumentError, "The property '#{property}' is required for this Dash."
end
end
end
end

View File

@ -21,7 +21,7 @@ module Hashie
super(key, value)
end
def custom_writer(key, value, convert=true)
def custom_writer(key, value, convert = true)
self[key] = value
end
@ -53,7 +53,7 @@ module Hashie
attrs.each { |key| @key_coercions[key] = into }
end
alias :coerce_keys :coerce_key
alias_method :coerce_keys, :coerce_key
# Returns a hash of any existing key coercions.
def key_coercions
@ -87,7 +87,7 @@ module Hashie
# end
# end
def coerce_value(from, into, options = {})
options = {:strict => true}.merge(options)
options = { strict: true }.merge(options)
if options[:strict]
(@strict_value_coercions ||= {})[from] = into
@ -100,9 +100,13 @@ module Hashie
end
# Return all value coercions that have the :strict rule as true.
def strict_value_coercions; @strict_value_coercions || {} end
def strict_value_coercions
@strict_value_coercions || {}
end
# Return all value coercions that have the :strict rule as false.
def lenient_value_coercions; @value_coercions || {} end
def lenient_value_coercions
@value_coercions || {}
end
# Fetch the value coercion, if any, for the specified object.
def value_coercion(value)

View File

@ -3,7 +3,7 @@ module Hashie
module DeepMerge
# Returns a new hash with +self+ and +other_hash+ merged recursively.
def deep_merge(other_hash)
self.dup.deep_merge!(other_hash)
dup.deep_merge!(other_hash)
end
# Returns a new hash with +self+ and +other_hash+ merged recursively.
@ -18,7 +18,7 @@ module Hashie
def _recursive_merge(hash, other_hash)
if other_hash.is_a?(::Hash) && hash.is_a?(::Hash)
other_hash.each do |k, v|
hash[k] = hash.has_key?(k) ? _recursive_merge(hash[k], v) : v
hash[k] = hash.key?(k) ? _recursive_merge(hash[k], v) : v
end
hash
else

View File

@ -62,7 +62,7 @@ module Hashie
# is injecting itself into member hashes.
def convert!
keys.each do |k|
regular_writer convert_key(k), convert_value(self.regular_delete(k))
regular_writer convert_key(k), convert_value(regular_delete(k))
end
self
end
@ -76,7 +76,7 @@ module Hashie
value
end
end
def indifferent_default(key = nil)
return self[convert_key(key)] if key?(key)
regular_default(key)
@ -84,18 +84,34 @@ module Hashie
def indifferent_update(other_hash)
return regular_update(other_hash) if hash_with_indifference?(other_hash)
other_hash.each_pair do |k,v|
other_hash.each_pair do |k, v|
self[k] = v
end
end
def indifferent_writer(key, value); regular_writer convert_key(key), convert_value(value) end
def indifferent_fetch(key, *args); regular_fetch convert_key(key), *args end
def indifferent_delete(key); regular_delete convert_key(key) end
def indifferent_key?(key); regular_key? convert_key(key) end
def indifferent_values_at(*indices); indices.map{|i| self[i] } end
def indifferent_access?; true end
def indifferent_writer(key, value)
regular_writer convert_key(key), convert_value(value)
end
def indifferent_fetch(key, *args)
regular_fetch convert_key(key), *args
end
def indifferent_delete(key)
regular_delete convert_key(key)
end
def indifferent_key?(key)
regular_key? convert_key(key)
end
def indifferent_values_at(*indices)
indices.map { |i| self[i] }
end
def indifferent_access?
true
end
def indifferent_replace(other_hash)
(keys - other_hash.keys).each { |key| delete(key) }

View File

@ -10,7 +10,7 @@ module Hashie
def stringify_keys!
keys.each do |k|
stringify_keys_recursively!(self[k])
self[k.to_s] = self.delete(k)
self[k.to_s] = delete(k)
end
self
end
@ -51,7 +51,7 @@ module Hashie
def symbolize_keys!
keys.each do |k|
symbolize_keys_recursively!(self[k])
self[k.to_sym] = self.delete(k)
self[k.to_sym] = delete(k)
end
self
end
@ -81,7 +81,7 @@ module Hashie
end
end
end
module KeyConversion
def self.included(base)
base.send :include, SymbolizeKeys

View File

@ -5,8 +5,8 @@ module Hashie
# to access your hash's keys. It will recognize keys
# either as strings or symbols.
#
# Note that while nil keys will be returned as nil,
# undefined keys will raise NoMethodErrors. Also note that
# Note that while nil keys will be returned as nil,
# undefined keys will raise NoMethodErrors. Also note that
# #respond_to? has been patched to appropriately recognize
# key methods.
#
@ -18,9 +18,9 @@ module Hashie
# user = User.new
# user['first_name'] = 'Michael'
# user.first_name # => 'Michael'
#
#
# user[:last_name] = 'Bleigh'
# user.last_name # => 'Bleigh'
# user.last_name # => 'Bleigh'
#
# user[:birthday] = nil
# user.birthday # => nil
@ -31,7 +31,7 @@ module Hashie
return true if key?(name.to_s) || key?(name.to_sym)
super
end
def method_missing(name, *args)
return self[name.to_s] if key?(name.to_s)
return self[name.to_sym] if key?(name.to_sym)
@ -64,7 +64,7 @@ module Hashie
def method_missing(name, *args)
if args.size == 1 && name.to_s =~ /(.*)=$/
return self[convert_key($1)] = args.first
return self[convert_key(Regexp.last_match[1])] = args.first
end
super
@ -97,13 +97,13 @@ module Hashie
# h.hji? # => NoMethodError
module MethodQuery
def respond_to?(name, include_private = false)
return true if name.to_s =~ /(.*)\?$/ && (key?($1) || key?($1.to_sym))
return true if name.to_s =~ /(.*)\?$/ && (key?(Regexp.last_match[1]) || key?(Regexp.last_match[1].to_sym))
super
end
def method_missing(name, *args)
if args.empty? && name.to_s =~ /(.*)\?$/ && (key?($1) || key?($1.to_sym))
return self[$1] || self[$1.to_sym]
if args.empty? && name.to_s =~ /(.*)\?$/ && (key?(Regexp.last_match[1]) || key?(Regexp.last_match[1].to_sym))
return self[Regexp.last_match[1]] || self[Regexp.last_match[1].to_sym]
end
super

View File

@ -28,6 +28,8 @@ module Hashie
end
module ClassMethods
attr_reader :permitted_keys
def key(key, options = {})
(@permitted_keys ||= []) << key
@ -37,10 +39,6 @@ module Hashie
permitted_keys
end
def permitted_keys
@permitted_keys
end
end
end
end

View File

@ -8,7 +8,7 @@ module Hashie
include HashExtensions
# Converts a mash back to a hash (with stringified or symbolized keys)
def to_hash(options={})
def to_hash(options = {})
out = {}
keys.each do |k|
assignment_key = k.to_s

View File

@ -11,10 +11,8 @@ module Hashie
# Destructively convert all of the keys of a Hash
# to their string representations.
def hashie_stringify_keys!
self.keys.each do |k|
unless String === k
self[k.to_s] = self.delete(k)
end
keys.each do |k|
self[k.to_s] = delete(k) unless String === k
end
self
end
@ -22,7 +20,7 @@ module Hashie
# Convert all of the keys of a Hash
# to their string representations.
def hashie_stringify_keys
self.dup.stringify_keys!
dup.stringify_keys!
end
# Convert this hash into a Mash
@ -38,11 +36,11 @@ module Hashie
end
def hashie_inspect
ret = "#<#{self.class.to_s}"
ret = "#<#{self.class}"
stringify_keys.keys.sort.each do |key|
ret << " #{key}=#{self[key].inspect}"
end
ret << ">"
ret << '>'
ret
end
end

View File

@ -68,14 +68,14 @@ module Hashie
default ? super(default) : super(&blk)
end
class << self; alias [] new; end
class << self; alias_method :[], :new; end
def id #:nodoc:
self["id"]
self['id']
end
def type #:nodoc:
self["type"]
self['type']
end
alias_method :regular_reader, :[]
@ -92,7 +92,7 @@ module Hashie
# Sets an attribute in the Mash. Key will be converted to
# a string before it is set, and Hashes will be converted
# into Mashes for nesting purposes.
def custom_writer(key,value,convert=true) #:nodoc:
def custom_writer(key, value, convert = true) #:nodoc:
regular_writer(convert_key(key), convert ? convert_value(value) : value)
end
@ -129,7 +129,7 @@ module Hashie
alias_method :regular_dup, :dup
# Duplicates the current mash as a new mash.
def dup
self.class.new(self, self.default)
self.class.new(self, default)
end
def key?(key)
@ -149,9 +149,9 @@ module Hashie
# Recursively merges this mash with the passed
# in hash, merging each hash in the hierarchy.
def deep_update(other_hash, &blk)
other_hash.each_pair do |k,v|
other_hash.each_pair do |k, v|
key = convert_key(k)
if regular_reader(key).is_a?(Mash) and v.is_a?(::Hash)
if regular_reader(key).is_a?(Mash) && v.is_a?(::Hash)
custom_reader(key).deep_update(v, &blk)
else
value = convert_value(v, true)
@ -173,7 +173,7 @@ module Hashie
# Merges (non-recursively) the hash from the argument,
# changing the receiving hash
def shallow_update(other_hash)
other_hash.each_pair do |k,v|
other_hash.each_pair do |k, v|
regular_writer(convert_key(k), convert_value(v, true))
end
self
@ -187,12 +187,11 @@ module Hashie
# Will return true if the Mash has had a key
# set in addition to normal respond_to? functionality.
def respond_to?(method_name, include_private=false)
def respond_to?(method_name, include_private = false)
return true if key?(method_name) || prefix_method?(method_name)
super
end
def prefix_method?(method_name)
method_name = method_name.to_s
method_name.end_with?(*ALLOWED_SUFFIXES) && key?(method_name.chop)
@ -203,13 +202,13 @@ module Hashie
suffixes_regex = ALLOWED_SUFFIXES.join
match = method_name.to_s.match(/(.*?)([#{suffixes_regex}]?)$/)
case match[2]
when "="
when '='
self[match[1]] = args.first
when "?"
when '?'
!!self[match[1]]
when "!"
when '!'
initializing_reader(match[1])
when "_"
when '_'
underbang_reader(match[1])
else
default(method_name)
@ -222,19 +221,19 @@ module Hashie
key.to_s
end
def convert_value(val, duping=false) #:nodoc:
def convert_value(val, duping = false) #:nodoc:
case val
when self.class
val.dup
when Hash
duping ? val.dup : val
when ::Hash
val = val.dup if duping
self.class.new(val)
when Array
val.collect{ |e| convert_value(e) }
else
val
when self.class
val.dup
when Hash
duping ? val.dup : val
when ::Hash
val = val.dup if duping
self.class.new(val)
when Array
val.map { |e| convert_value(e) }
else
val
end
end
end

View File

@ -8,7 +8,6 @@ module Hashie
# such as a Java api, where the keys are named differently from how we would
# in Ruby.
class Trash < Dash
# Defines a property on the Trash. Options are as follows:
#
# * <tt>:default</tt> - Specify a default value for this property, to be
@ -25,7 +24,7 @@ module Hashie
if options[:from]
if property_name == options[:from]
raise ArgumentError, "Property name (#{property_name}) and :from option must not be the same"
fail ArgumentError, "Property name (#{property_name}) and :from option must not be the same"
end
translations[options[:from]] ||= {}
@ -33,8 +32,8 @@ module Hashie
# NOTE: may overwrite existing method multiple times
define_method "#{options[:from]}=" do |val|
self.class.translations[options[:from]].each do |property_name, with|
self[property_name] = with.respond_to?(:call) ? with.call(val) : val
self.class.translations[options[:from]].each do |name, with|
self[name] = with.respond_to?(:call) ? with.call(val) : val
end
end
else
@ -74,7 +73,7 @@ module Hashie
#
def property_exists?(property)
unless self.class.property?(property.to_sym)
raise NoMethodError, "The property '#{property}' is not defined for this Trash."
fail NoMethodError, "The property '#{property}' is not defined for this Trash."
end
true
end
@ -84,7 +83,7 @@ module Hashie
# Deletes any keys that have a translation
def initialize_attributes(attributes)
return unless attributes
attributes_copy = attributes.dup.delete_if do |k,v|
attributes_copy = attributes.dup.delete_if do |k, v|
if self.class.translations.include?(k.to_sym)
self[k] = v
true
@ -93,4 +92,4 @@ module Hashie
super attributes_copy
end
end
end
end

View File

@ -4,46 +4,46 @@ describe Hashie::Clash do
before do
@c = Hashie::Clash.new
end
it 'should be able to set an attribute via method_missing' do
@c.foo('bar')
@c[:foo].should == 'bar'
@c[:foo].should eq 'bar'
end
it 'should be able to set multiple attributes' do
@c.foo('bar').baz('wok')
@c.should == {:foo => 'bar', :baz => 'wok'}
@c.should eq(foo: 'bar', baz: 'wok')
end
it 'should convert multiple arguments into an array' do
@c.foo(1, 2, 3)
@c[:foo].should == [1,2,3]
@c[:foo].should eq [1, 2, 3]
end
it 'should be able to use bang notation to create a new Clash on a key' do
@c.foo!
@c[:foo].should be_kind_of(Hashie::Clash)
end
it 'should be able to chain onto the new Clash when using bang notation' do
@c.foo!.bar('abc').baz(123)
@c.should == {:foo => {:bar => 'abc', :baz => 123}}
@c.should eq(foo: { bar: 'abc', baz: 123 })
end
it 'should be able to jump back up to the parent in the chain with #_end!' do
@c.foo!.bar('abc')._end!.baz(123)
@c.should == {:foo => {:bar => 'abc'}, :baz => 123}
@c.should eq(foo: { bar: 'abc' }, baz: 123)
end
it 'should merge rather than replace existing keys' do
@c.where(:abc => 'def').where(:hgi => 123)
@c.should == {:where => {:abc => 'def', :hgi => 123}}
@c.where(abc: 'def').where(hgi: 123)
@c.should eq(where: { abc: 'def', hgi: 123 })
end
it 'should be able to replace all of its own keys with #replace' do
@c.foo(:bar).hello(:world)
@c.replace(:baz => 123, :hgi => 123).should == {:baz => 123, :hgi => 123}
@c.should == {:baz => 123, :hgi => 123}
@c.replace(baz: 123, hgi: 123).should eq(baz: 123, hgi: 123)
@c.should eq(baz: 123, hgi: 123)
@c[:foo].should be_nil
@c[:hello].should be_nil
end

View File

@ -7,15 +7,15 @@ Hashie::Hash.class_eval do
end
class DashTest < Hashie::Dash
property :first_name, :required => true
property :first_name, required: true
property :email
property :count, :default => 0
property :count, default: 0
end
class DashNoRequiredTest < Hashie::Dash
property :first_name
property :email
property :count, :default => 0
property :count, default: 0
end
class PropertyBangTest < Hashie::Dash
@ -23,29 +23,29 @@ class PropertyBangTest < Hashie::Dash
end
class Subclassed < DashTest
property :last_name, :required => true
property :last_name, required: true
end
class DashDefaultTest < Hashie::Dash
property :aliases, :default => ["Snake"]
property :aliases, default: ['Snake']
end
class DeferredTest < Hashie::Dash
property :created_at, :default => Proc.new { Time.now }
property :created_at, default: proc { Time.now }
end
describe DashTest do
subject { DashTest.new(:first_name => 'Bob', :email => 'bob@example.com') }
subject { DashTest.new(first_name: 'Bob', email: 'bob@example.com') }
it('subclasses Hashie::Hash') { should respond_to(:to_mash) }
its(:to_s) { should == '#<DashTest count=0 email="bob@example.com" first_name="Bob">' }
its(:to_s) { should eq '#<DashTest count=0 email="bob@example.com" first_name="Bob">' }
it 'lists all set properties in inspect' do
subject.first_name = 'Bob'
subject.email = 'bob@example.com'
subject.inspect.should == '#<DashTest count=0 email="bob@example.com" first_name="Bob">'
subject.inspect.should eq '#<DashTest count=0 email="bob@example.com" first_name="Bob">'
end
its(:count) { should be_zero }
@ -78,13 +78,13 @@ describe DashTest do
it 'works for an existing property using []=' do
subject['first_name'] = 'Bob'
subject['first_name'].should == 'Bob'
subject[:first_name].should == 'Bob'
subject['first_name'].should eq 'Bob'
subject[:first_name].should eq 'Bob'
end
it 'works for an existing property using a method call' do
subject.first_name = 'Franklin'
subject.first_name.should == 'Franklin'
subject.first_name.should eq 'Franklin'
end
end
@ -93,18 +93,18 @@ describe DashTest do
lambda { subject['nonexistent'] }.should raise_error(NoMethodError)
end
it "should be able to retrieve properties through blocks" do
subject["first_name"] = "Aiden"
it 'should be able to retrieve properties through blocks' do
subject['first_name'] = 'Aiden'
value = nil
subject.[]("first_name") { |v| value = v }
value.should == "Aiden"
subject.[]('first_name') { |v| value = v }
value.should eq 'Aiden'
end
it "should be able to retrieve properties through blocks with method calls" do
subject["first_name"] = "Frodo"
it 'should be able to retrieve properties through blocks with method calls' do
subject['first_name'] = 'Frodo'
value = nil
subject.first_name { |v| value = v }
value.should == "Frodo"
value.should eq 'Frodo'
end
end
@ -113,20 +113,20 @@ describe DashTest do
DeferredTest.new['created_at'].should be_instance_of(Time)
end
it "should not evalute proc after subsequent reads" do
it 'should not evalute proc after subsequent reads' do
deferred = DeferredTest.new
deferred['created_at'].object_id.should == deferred['created_at'].object_id
deferred['created_at'].object_id.should eq deferred['created_at'].object_id
end
end
describe '.new' do
it 'fails with non-existent properties' do
lambda { described_class.new(:bork => '') }.should raise_error(NoMethodError)
lambda { described_class.new(bork: '') }.should raise_error(NoMethodError)
end
it 'should set properties that it is able to' do
obj = described_class.new :first_name => 'Michael'
obj.first_name.should == 'Michael'
obj = described_class.new first_name: 'Michael'
obj.first_name.should eq 'Michael'
end
it 'accepts nil' do
@ -135,83 +135,83 @@ describe DashTest do
it 'accepts block to define a global default' do
obj = described_class.new { |hash, key| key.to_s.upcase }
obj.first_name.should == 'FIRST_NAME'
obj.first_name.should eq 'FIRST_NAME'
obj.count.should be_zero
end
it "fails when required values are missing" do
it 'fails when required values are missing' do
expect { DashTest.new }.to raise_error(ArgumentError)
end
it "does not overwrite default values" do
it 'does not overwrite default values' do
obj1 = DashDefaultTest.new
obj1.aliases << "El Rey"
obj1.aliases << 'El Rey'
obj2 = DashDefaultTest.new
obj2.aliases.should_not include "El Rey"
obj2.aliases.should_not include 'El Rey'
end
end
describe '#merge' do
it 'creates a new instance of the Dash' do
new_dash = subject.merge(:first_name => 'Robert')
subject.object_id.should_not == new_dash.object_id
new_dash = subject.merge(first_name: 'Robert')
subject.object_id.should_not eq new_dash.object_id
end
it 'merges the given hash' do
new_dash = subject.merge(:first_name => 'Robert', :email => 'robert@example.com')
new_dash.first_name.should == 'Robert'
new_dash.email.should == 'robert@example.com'
new_dash = subject.merge(first_name: 'Robert', email: 'robert@example.com')
new_dash.first_name.should eq 'Robert'
new_dash.email.should eq 'robert@example.com'
end
it 'fails with non-existent properties' do
expect { subject.merge(:middle_name => 'James') }.to raise_error(NoMethodError)
expect { subject.merge(middle_name: 'James') }.to raise_error(NoMethodError)
end
it 'errors out when attempting to set a required property to nil' do
expect { subject.merge(:first_name => nil) }.to raise_error(ArgumentError)
expect { subject.merge(first_name: nil) }.to raise_error(ArgumentError)
end
context "given a block" do
context 'given a block' do
it "sets merged key's values to the block's return value" do
subject.merge(:first_name => 'Jim') do |key, oldval, newval|
subject.merge(first_name: 'Jim') do |key, oldval, newval|
"#{key}: #{newval} #{oldval}"
end.first_name.should == 'first_name: Jim Bob'
end.first_name.should eq 'first_name: Jim Bob'
end
end
end
describe '#merge!' do
it 'modifies the existing instance of the Dash' do
original_dash = subject.merge!(:first_name => 'Robert')
subject.object_id.should == original_dash.object_id
original_dash = subject.merge!(first_name: 'Robert')
subject.object_id.should eq original_dash.object_id
end
it 'merges the given hash' do
subject.merge!(:first_name => 'Robert', :email => 'robert@example.com')
subject.first_name.should == 'Robert'
subject.email.should == 'robert@example.com'
subject.merge!(first_name: 'Robert', email: 'robert@example.com')
subject.first_name.should eq 'Robert'
subject.email.should eq 'robert@example.com'
end
it 'fails with non-existent properties' do
expect { subject.merge!(:middle_name => 'James') }.to raise_error(NoMethodError)
expect { subject.merge!(middle_name: 'James') }.to raise_error(NoMethodError)
end
it 'errors out when attempting to set a required property to nil' do
expect { subject.merge!(:first_name => nil) }.to raise_error(ArgumentError)
expect { subject.merge!(first_name: nil) }.to raise_error(ArgumentError)
end
context "given a block" do
context 'given a block' do
it "sets merged key's values to the block's return value" do
subject.merge!(:first_name => 'Jim') do |key, oldval, newval|
subject.merge!(first_name: 'Jim') do |key, oldval, newval|
"#{key}: #{newval} #{oldval}"
end.first_name.should == 'first_name: Jim Bob'
end.first_name.should eq 'first_name: Jim Bob'
end
end
end
describe 'properties' do
it 'lists defined properties' do
described_class.properties.should == Set.new([:first_name, :email, :count])
described_class.properties.should eq Set.new([:first_name, :email, :count])
end
it 'checks if a property exists' do
@ -229,7 +229,7 @@ describe DashTest do
end
it 'lists declared defaults' do
described_class.defaults.should == { :count => 0 }
described_class.defaults.should eq(count: 0)
end
it 'allows properties that end in bang' do
@ -238,28 +238,27 @@ describe DashTest do
end
describe '#replace' do
before { subject.replace(:first_name => "Cain") }
before { subject.replace(first_name: 'Cain') }
it 'return self' do
subject.replace(:email => "bar").to_hash.
should == {"email" => "bar", "count" => 0}
subject.replace(email: 'bar').to_hash.should eq('email' => 'bar', 'count' => 0)
end
it 'sets all specified keys to their corresponding values' do
subject.first_name.should == "Cain"
subject.first_name.should eq 'Cain'
end
it 'leaves only specified keys and keys with default values' do
subject.keys.sort.should == ['count', 'first_name']
subject.keys.sort.should eq %w(count first_name)
subject.email.should be_nil
subject.count.should == 0
subject.count.should eq 0
end
context 'when replacing keys with default values' do
before { subject.replace(:count => 3) }
before { subject.replace(count: 3) }
it 'sets all specified keys to their corresponding values' do
subject.count.should == 3
subject.count.should eq 3
end
end
end
@ -291,21 +290,21 @@ describe Hashie::Dash, 'inheritance' do
it 'allows overriding a default on an existing property' do
@top.property :echo
@middle.property :echo, :default => 123
@bottom.properties.to_a.should == [:echo]
@bottom.new.echo.should == 123
@middle.property :echo, default: 123
@bottom.properties.to_a.should eq [:echo]
@bottom.new.echo.should eq 123
end
it 'allows clearing an existing default' do
@top.property :echo
@middle.property :echo, :default => 123
@middle.property :echo, default: 123
@bottom.property :echo
@bottom.properties.to_a.should == [:echo]
@bottom.properties.to_a.should eq [:echo]
@bottom.new.echo.should be_nil
end
it 'should allow nil defaults' do
@bottom.property :echo, :default => nil
@bottom.property :echo, default: nil
@bottom.new.should have_key('echo')
end
@ -313,7 +312,7 @@ end
describe Subclassed do
subject { Subclassed.new(:first_name => 'Bob', :last_name => 'McNob', :email => 'bob@example.com') }
subject { Subclassed.new(first_name: 'Bob', last_name: 'McNob', email: 'bob@example.com') }
its(:count) { should be_zero }

View File

@ -2,12 +2,16 @@ require 'spec_helper'
describe Hashie::Extensions::Coercion do
class Initializable
attr_reader :coerced, :value
def initialize(obj, coerced = false)
@coerced = coerced
@value = obj.class.to_s
end
def coerced?; @coerced end
attr_reader :value
def coerced?
!!@coerced
end
end
class Coercable < Initializable
@ -22,8 +26,10 @@ describe Hashie::Extensions::Coercion do
include Hashie::Extensions::MergeInitializer
end
end
subject { ExampleCoercableHash }
let(:instance){ subject.new }
let(:instance) { subject.new }
describe '.coerce_key' do
it { subject.should be_respond_to(:coerce_key) }
@ -31,15 +37,15 @@ describe Hashie::Extensions::Coercion do
it 'should run through coerce on a specified key' do
subject.coerce_key :foo, Coercable
instance[:foo] = "bar"
instance[:foo] = 'bar'
instance[:foo].should be_coerced
end
it "should support an array of keys" do
it 'should support an array of keys' do
subject.coerce_keys :foo, :bar, Coercable
instance[:foo] = "bar"
instance[:bar] = "bax"
instance[:foo] = 'bar'
instance[:bar] = 'bax'
instance[:foo].should be_coerced
instance[:bar].should be_coerced
end
@ -47,14 +53,14 @@ describe Hashie::Extensions::Coercion do
it 'should just call #new if no coerce method is available' do
subject.coerce_key :foo, Initializable
instance[:foo] = "bar"
instance[:foo].value.should == "String"
instance[:foo] = 'bar'
instance[:foo].value.should eq 'String'
instance[:foo].should_not be_coerced
end
it "should coerce when the merge initializer is used" do
it 'should coerce when the merge initializer is used' do
subject.coerce_key :foo, Coercable
instance = subject.new(:foo => "bar")
instance = subject.new(foo: 'bar')
instance[:foo].should be_coerced
end
@ -63,22 +69,21 @@ describe Hashie::Extensions::Coercion do
before { subject.coerce_key :foo, :bar, Coercable }
let(:instance) do
subject.new(:foo => "bar").
replace(:foo => "foz", :bar => "baz", :hi => "bye")
subject.new(foo: 'bar').replace(foo: 'foz', bar: 'baz', hi: 'bye')
end
it "should coerce relevant keys" do
it 'should coerce relevant keys' do
instance[:foo].should be_coerced
instance[:bar].should be_coerced
instance[:hi].should_not respond_to(:coerced?)
end
it "should set correct values" do
instance[:hi].should == "bye"
it 'should set correct values' do
instance[:hi].should eq 'bye'
end
end
context "when used with a Mash" do
context 'when used with a Mash' do
class UserMash < Hashie::Mash
end
class TweetMash < Hashie::Mash
@ -86,26 +91,26 @@ describe Hashie::Extensions::Coercion do
coerce_key :user, UserMash
end
it "should coerce with instance initialization" do
tweet = TweetMash.new(:user => {:email => 'foo@bar.com'})
it 'should coerce with instance initialization' do
tweet = TweetMash.new(user: { email: 'foo@bar.com' })
tweet[:user].should be_a(UserMash)
end
it "should coerce when setting with attribute style" do
it 'should coerce when setting with attribute style' do
tweet = TweetMash.new
tweet.user = {:email => 'foo@bar.com'}
tweet.user = { email: 'foo@bar.com' }
tweet[:user].should be_a(UserMash)
end
it "should coerce when setting with string index" do
it 'should coerce when setting with string index' do
tweet = TweetMash.new
tweet['user'] = {:email => 'foo@bar.com'}
tweet['user'] = { email: 'foo@bar.com' }
tweet[:user].should be_a(UserMash)
end
it "should coerce when setting with symbol index" do
it 'should coerce when setting with symbol index' do
tweet = TweetMash.new
tweet[:user] = {:email => 'foo@bar.com'}
tweet[:user] = { email: 'foo@bar.com' }
tweet[:user].should be_a(UserMash)
end
end
@ -116,8 +121,8 @@ describe Hashie::Extensions::Coercion do
it 'should coerce any value of the exact right class' do
subject.coerce_value String, Coercable
instance[:foo] = "bar"
instance[:bar] = "bax"
instance[:foo] = 'bar'
instance[:bar] = 'bax'
instance[:hi] = :bye
instance[:foo].should be_coerced
instance[:bar].should be_coerced
@ -128,7 +133,7 @@ describe Hashie::Extensions::Coercion do
subject.coerce_value String, Coercable
instance[:foo] = :bar
instance.replace(:foo => "bar", :bar => "bax")
instance.replace(foo: 'bar', bar: 'bax')
instance[:foo].should be_coerced
instance[:bar].should be_coerced
end
@ -137,7 +142,7 @@ describe Hashie::Extensions::Coercion do
klass = Class.new(String)
subject.coerce_value klass, Coercable
instance[:foo] = "bar"
instance[:foo] = 'bar'
instance[:foo].should_not be_kind_of(Coercable)
instance[:foo] = klass.new
instance[:foo].should be_kind_of(Coercable)

View File

@ -3,19 +3,19 @@ require 'spec_helper'
describe Hashie::Extensions::DeepMerge do
class DeepMergeHash < Hash; include Hashie::Extensions::DeepMerge end
subject{ DeepMergeHash }
subject { DeepMergeHash }
let(:h1) { subject.new.merge(:a => "a", :a1 => 42, :b => "b", :c => { :c1 => "c1", :c2 => {:a => "b"}, :c3 => { :d1 => "d1" } }) }
let(:h2) { { :a => 1, :a1 => 1, :c => { :c1 => 2, :c2 => "c2", :c3 => { :d2 => "d2" } } } }
let(:expected_hash) { { :a => 1, :a1 => 1, :b => "b", :c => { :c1 => 2, :c2 => "c2", :c3 => { :d1 => "d1", :d2 => "d2" } } } }
let(:h1) { subject.new.merge(a: 'a', a1: 42, b: 'b', c: { c1: 'c1', c2: { a: 'b' }, c3: { d1: 'd1' } }) }
let(:h2) { { a: 1, a1: 1, c: { c1: 2, c2: 'c2', c3: { d2: 'd2' } } } }
let(:expected_hash) { { a: 1, a1: 1, b: 'b', c: { c1: 2, c2: 'c2', c3: { d1: 'd1', d2: 'd2' } } } }
it 'deep merges two hashes' do
h1.deep_merge(h2).should == expected_hash
h1.deep_merge(h2).should eq expected_hash
end
it 'deep merges another hash in place via bang method' do
h1.deep_merge!(h2)
h1.should == expected_hash
h1.should eq expected_hash
end
end

View File

@ -5,36 +5,35 @@ describe Hashie::Extensions::IndifferentAccess do
include Hashie::Extensions::MergeInitializer
include Hashie::Extensions::IndifferentAccess
end
subject{ IndifferentHash }
subject { IndifferentHash }
it 'should be able to access via string or symbol' do
h = subject.new(:abc => 123)
h[:abc].should == 123
h['abc'].should == 123
h = subject.new(abc: 123)
h[:abc].should eq 123
h['abc'].should eq 123
end
describe '#store' do
it 'should indifferently save values' do
h = subject.new
h.store(:abc, 123)
h[:abc].should == 123
h['abc'].should == 123
h[:abc].should eq 123
h['abc'].should eq 123
end
end
describe '#values_at' do
it 'should indifferently find values' do
h = subject.new(:foo => 'bar', 'baz' => 'qux')
h.values_at('foo', :baz).should == %w(bar qux)
h.values_at('foo', :baz).should eq %w(bar qux)
end
end
describe '#fetch' do
it 'should work like normal fetch, but indifferent' do
h = subject.new(:foo => 'bar')
h.fetch(:foo).should == h.fetch('foo')
h.fetch(:foo).should == 'bar'
h = subject.new(foo: 'bar')
h.fetch(:foo).should eq h.fetch('foo')
h.fetch(:foo).should eq 'bar'
end
end
@ -48,7 +47,7 @@ describe Hashie::Extensions::IndifferentAccess do
end
describe '#key?' do
let(:h) { subject.new(:foo => 'bar') }
let(:h) { subject.new(foo: 'bar') }
it 'should find it indifferently' do
h.should be_key(:foo)
@ -64,27 +63,27 @@ describe Hashie::Extensions::IndifferentAccess do
end
describe '#update' do
subject{ IndifferentHash.new(:foo => 'bar') }
subject { IndifferentHash.new(foo: 'bar') }
it 'should allow keys to be indifferent still' do
subject.update(:baz => 'qux')
subject['foo'].should == 'bar'
subject['baz'].should == 'qux'
subject.update(baz: 'qux')
subject['foo'].should eq 'bar'
subject['baz'].should eq 'qux'
end
it 'should recursively inject indifference into sub-hashes' do
subject.update(:baz => {:qux => 'abc'})
subject['baz']['qux'].should == 'abc'
subject.update(baz: { qux: 'abc' })
subject['baz']['qux'].should eq 'abc'
end
it 'should not change the ancestors of the injected object class' do
subject.update(:baz => {:qux => 'abc'})
subject.update(baz: { qux: 'abc' })
Hash.new.should_not be_respond_to(:indifferent_access?)
end
end
describe '#replace' do
subject do
IndifferentHash.new(:foo => 'bar').replace(:bar => 'baz', :hi => 'bye')
IndifferentHash.new(foo: 'bar').replace(bar: 'baz', hi: 'bye')
end
it 'returns self' do
@ -100,10 +99,10 @@ describe Hashie::Extensions::IndifferentAccess do
it 'creates new keys with indifferent access' do
[:bar, 'bar', :hi, 'hi'].each { |k| subject.key?(k).should be_true }
subject[:bar].should == 'baz'
subject['bar'].should == 'baz'
subject[:hi].should == 'bye'
subject['hi'].should == 'bye'
subject[:bar].should eq 'baz'
subject['bar'].should eq 'baz'
subject[:hi].should eq 'bye'
subject['hi'].should eq 'bye'
end
end
end

View File

@ -6,14 +6,14 @@ describe Hashie::Extensions::KeyConversion do
klass.send :include, Hashie::Extensions::KeyConversion
klass
end
let(:instance){ subject.new }
let(:instance) { subject.new }
describe '#stringify_keys!' do
it 'should convert keys to strings' do
instance[:abc] = 'abc'
instance[123] = '123'
instance.stringify_keys!
(instance.keys & %w(abc 123)).size.should == 2
(instance.keys & %w(abc 123)).size.should eq 2
end
it 'should do deep conversion within nested hashes' do
@ -21,7 +21,7 @@ describe Hashie::Extensions::KeyConversion do
instance[:ab][:cd] = subject.new
instance[:ab][:cd][:ef] = 'abcdef'
instance.stringify_keys!
instance.should == {'ab' => {'cd' => {'ef' => 'abcdef'}}}
instance.should eq('ab' => { 'cd' => { 'ef' => 'abcdef' } })
end
it 'should do deep conversion within nested arrays' do
@ -31,11 +31,11 @@ describe Hashie::Extensions::KeyConversion do
instance[:ab][0][:cd] = 'abcd'
instance[:ab][1][:ef] = 'abef'
instance.stringify_keys!
instance.should == {'ab' => [{'cd' => 'abcd'}, {'ef' => 'abef'}]}
instance.should eq('ab' => [{ 'cd' => 'abcd' }, { 'ef' => 'abef' }])
end
it 'should return itself' do
instance.stringify_keys!.should == instance
instance.stringify_keys!.should eq instance
end
end
@ -43,14 +43,14 @@ describe Hashie::Extensions::KeyConversion do
it 'should convert keys to strings' do
instance[:abc] = 'def'
copy = instance.stringify_keys
copy['abc'].should == 'def'
copy['abc'].should eq 'def'
end
it 'should not alter the original' do
instance[:abc] = 'def'
copy = instance.stringify_keys
instance.keys.should == [:abc]
copy.keys.should == %w(abc)
instance.keys.should eq [:abc]
copy.keys.should eq %w(abc)
end
end
@ -59,7 +59,7 @@ describe Hashie::Extensions::KeyConversion do
instance['abc'] = 'abc'
instance['def'] = 'def'
instance.symbolize_keys!
(instance.keys & [:abc, :def]).size.should == 2
(instance.keys & [:abc, :def]).size.should eq 2
end
it 'should do deep conversion within nested hashes' do
@ -67,7 +67,7 @@ describe Hashie::Extensions::KeyConversion do
instance['ab']['cd'] = subject.new
instance['ab']['cd']['ef'] = 'abcdef'
instance.symbolize_keys!
instance.should == {:ab => {:cd => {:ef => 'abcdef'}}}
instance.should eq(ab: { cd: { ef: 'abcdef' } })
end
it 'should do deep conversion within nested arrays' do
@ -77,11 +77,11 @@ describe Hashie::Extensions::KeyConversion do
instance['ab'][0]['cd'] = 'abcd'
instance['ab'][1]['ef'] = 'abef'
instance.symbolize_keys!
instance.should == {:ab => [{:cd => 'abcd'}, {:ef => 'abef'}]}
instance.should eq(ab: [{ cd: 'abcd' }, { ef: 'abef' }])
end
it 'should return itself' do
instance.symbolize_keys!.should == instance
instance.symbolize_keys!.should eq instance
end
end
@ -89,14 +89,14 @@ describe Hashie::Extensions::KeyConversion do
it 'should convert keys to symbols' do
instance['abc'] = 'def'
copy = instance.symbolize_keys
copy[:abc].should == 'def'
copy[:abc].should eq 'def'
end
it 'should not alter the original' do
instance['abc'] = 'def'
copy = instance.symbolize_keys
instance.keys.should == ['abc']
copy.keys.should == [:abc]
instance.keys.should eq ['abc']
copy.keys.should eq [:abc]
end
end
end

View File

@ -2,19 +2,19 @@ require 'spec_helper'
describe Hashie::Extensions::MergeInitializer do
class MergeInitializerHash < Hash; include Hashie::Extensions::MergeInitializer end
subject{ MergeInitializerHash }
subject { MergeInitializerHash }
it 'should initialize fine with no arguments' do
subject.new.should == {}
subject.new.should eq({})
end
it 'should initialize with a hash' do
subject.new(:abc => 'def').should == {:abc => 'def'}
subject.new(abc: 'def').should eq(abc: 'def')
end
it 'should initialize with a hash and a default' do
h = subject.new({:abc => 'def'}, 'bar')
h[:foo].should == 'bar'
h[:abc].should == 'def'
h = subject.new({ abc: 'def' }, 'bar')
h[:foo].should eq 'bar'
h[:abc].should eq 'def'
end
end

View File

@ -2,27 +2,29 @@ require 'spec_helper'
describe Hashie::Extensions::MethodReader do
class ReaderHash < Hash
def initialize(hash = {}); self.update(hash) end
def initialize(hash = {
}); update(hash)
end
include Hashie::Extensions::MethodReader
end
subject{ ReaderHash }
subject { ReaderHash }
it 'should read string keys from the method' do
subject.new('awesome' => 'sauce').awesome.should == 'sauce'
subject.new('awesome' => 'sauce').awesome.should eq 'sauce'
end
it 'should read symbol keys from the method' do
subject.new(:awesome => 'sauce').awesome.should == 'sauce'
subject.new(awesome: 'sauce').awesome.should eq 'sauce'
end
it 'should read nil and false values out properly' do
h = subject.new(:nil => nil, :false => false)
h.nil.should == nil
h.false.should == false
h = subject.new(nil: nil, false: false)
h.nil.should eq nil
h.false.should eq false
end
it 'should raise a NoMethodError for undefined keys' do
lambda{ subject.new.awesome }.should raise_error(NoMethodError)
lambda { subject.new.awesome }.should raise_error(NoMethodError)
end
describe '#respond_to?' do
@ -31,7 +33,7 @@ describe Hashie::Extensions::MethodReader do
end
it 'should be true for symbol keys' do
subject.new(:awesome => 'sauce').should be_respond_to(:awesome)
subject.new(awesome: 'sauce').should be_respond_to(:awesome)
end
it 'should be false for non-keys' do
@ -44,21 +46,21 @@ describe Hashie::Extensions::MethodWriter do
class WriterHash < Hash
include Hashie::Extensions::MethodWriter
end
subject{ WriterHash.new }
subject { WriterHash.new }
it 'should write from a method call' do
subject.awesome = 'sauce'
subject['awesome'].should == 'sauce'
subject['awesome'].should eq 'sauce'
end
it 'should convert the key using the #convert_key method' do
subject.stub!(:convert_key).and_return(:awesome)
subject.awesome = 'sauce'
subject[:awesome].should == 'sauce'
subject[:awesome].should eq 'sauce'
end
it 'should still NoMethodError on non equals-ending methods' do
lambda{ subject.awesome }.should raise_error(NoMethodError)
lambda { subject.awesome }.should raise_error(NoMethodError)
end
it 'should #respond_to? properly' do
@ -69,25 +71,27 @@ end
describe Hashie::Extensions::MethodQuery do
class QueryHash < Hash
def initialize(hash = {}); self.update(hash) end
def initialize(hash = {
}); update(hash)
end
include Hashie::Extensions::MethodQuery
end
subject{ QueryHash }
subject { QueryHash }
it 'should be true for non-nil string key values' do
subject.new('abc' => 123).should be_abc
end
it 'should be true for non-nil symbol key values' do
subject.new(:abc => 123).should be_abc
subject.new(abc: 123).should be_abc
end
it 'should be false for nil key values' do
subject.new(:abc => false).should_not be_abc
subject.new(abc: false).should_not be_abc
end
it 'should raise a NoMethodError for non-set keys' do
lambda{ subject.new.abc? }.should raise_error(NoMethodError)
lambda { subject.new.abc? }.should raise_error(NoMethodError)
end
it 'should respond_to? for existing string keys' do
@ -95,7 +99,7 @@ describe Hashie::Extensions::MethodQuery do
end
it 'should respond_to? for existing symbol keys' do
subject.new(:abc => 'def').should be_respond_to(:abc?)
subject.new(abc: 'def').should be_respond_to(:abc?)
end
it 'should not respond_to? for non-existent keys' do
@ -107,6 +111,6 @@ describe Hashie::Extensions::MethodAccess do
it 'should include all of the other method mixins' do
klass = Class.new(Hash)
klass.send :include, Hashie::Extensions::MethodAccess
(klass.ancestors & [Hashie::Extensions::MethodReader, Hashie::Extensions::MethodWriter, Hashie::Extensions::MethodQuery]).size.should == 3
(klass.ancestors & [Hashie::Extensions::MethodReader, Hashie::Extensions::MethodWriter, Hashie::Extensions::MethodQuery]).size.should eq 3
end
end

View File

@ -1,34 +1,34 @@
require 'spec_helper'
describe Hash do
it "should be convertible to a Hashie::Mash" do
mash = Hashie::Hash[:some => "hash"].to_mash
it 'should be convertible to a Hashie::Mash' do
mash = Hashie::Hash[some: 'hash'].to_mash
mash.is_a?(Hashie::Mash).should be_true
mash.some.should == "hash"
mash.some.should eq 'hash'
end
it "#stringify_keys! should turn all keys into strings" do
hash = Hashie::Hash[:a => "hey", 123 => "bob"]
it '#stringify_keys! should turn all keys into strings' do
hash = Hashie::Hash[:a => 'hey', 123 => 'bob']
hash.stringify_keys!
hash.should == Hashie::Hash["a" => "hey", "123" => "bob"]
hash.should eq Hashie::Hash['a' => 'hey', '123' => 'bob']
end
it "#stringify_keys should return a hash with stringified keys" do
hash = Hashie::Hash[:a => "hey", 123 => "bob"]
it '#stringify_keys should return a hash with stringified keys' do
hash = Hashie::Hash[:a => 'hey', 123 => 'bob']
stringified_hash = hash.stringify_keys
hash.should == Hashie::Hash[:a => "hey", 123 => "bob"]
stringified_hash.should == Hashie::Hash["a" => "hey", "123" => "bob"]
hash.should eq Hashie::Hash[:a => 'hey', 123 => 'bob']
stringified_hash.should eq Hashie::Hash['a' => 'hey', '123' => 'bob']
end
it "#to_hash should return a hash with stringified keys" do
hash = Hashie::Hash["a" => "hey", 123 => "bob", "array" => [1, 2, 3]]
it '#to_hash should return a hash with stringified keys' do
hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3]]
stringified_hash = hash.to_hash
stringified_hash.should == {"a" => "hey", "123" => "bob", "array" => [1, 2, 3]}
stringified_hash.should eq('a' => 'hey', '123' => 'bob', 'array' => [1, 2, 3])
end
it "#to_hash with symbolize_keys set to true should return a hash with symbolized keys" do
hash = Hashie::Hash["a" => "hey", 123 => "bob", "array" => [1, 2, 3]]
symbolized_hash = hash.to_hash(:symbolize_keys => true)
symbolized_hash.should == {:a => "hey", :"123" => "bob", :array => [1, 2, 3]}
it '#to_hash with symbolize_keys set to true should return a hash with symbolized keys' do
hash = Hashie::Hash['a' => 'hey', 123 => 'bob', 'array' => [1, 2, 3]]
symbolized_hash = hash.to_hash(symbolize_keys: true)
symbolized_hash.should eq(:a => 'hey', :"123" => 'bob', :array => [1, 2, 3])
end
end
end

View File

@ -6,223 +6,223 @@ describe Hashie::Mash do
@mash = Hashie::Mash.new
end
it "should inherit from hash" do
it 'should inherit from hash' do
@mash.is_a?(Hash).should be_true
end
it "should be able to set hash values through method= calls" do
@mash.test = "abc"
@mash["test"].should == "abc"
it 'should be able to set hash values through method= calls' do
@mash.test = 'abc'
@mash['test'].should eq 'abc'
end
it "should be able to retrieve set values through method calls" do
@mash["test"] = "abc"
@mash.test.should == "abc"
it 'should be able to retrieve set values through method calls' do
@mash['test'] = 'abc'
@mash.test.should eq 'abc'
end
it "should be able to retrieve set values through blocks" do
@mash["test"] = "abc"
it 'should be able to retrieve set values through blocks' do
@mash['test'] = 'abc'
value = nil
@mash.[]("test") { |v| value = v }
value.should == "abc"
@mash.[]('test') { |v| value = v }
value.should eq 'abc'
end
it "should be able to retrieve set values through blocks with method calls" do
@mash["test"] = "abc"
it 'should be able to retrieve set values through blocks with method calls' do
@mash['test'] = 'abc'
value = nil
@mash.test { |v| value = v }
value.should == "abc"
value.should eq 'abc'
end
it "should test for already set values when passed a ? method" do
it 'should test for already set values when passed a ? method' do
@mash.test?.should be_false
@mash.test = "abc"
@mash.test = 'abc'
@mash.test?.should be_true
end
it "should return false on a ? method if a value has been set to nil or false" do
it 'should return false on a ? method if a value has been set to nil or false' do
@mash.test = nil
@mash.should_not be_test
@mash.test = false
@mash.should_not be_test
end
it "should make all [] and []= into strings for consistency" do
@mash["abc"] = 123
it 'should make all [] and []= into strings for consistency' do
@mash['abc'] = 123
@mash.key?('abc').should be_true
@mash["abc"].should == 123
@mash['abc'].should eq 123
end
it "should have a to_s that is identical to its inspect" do
it 'should have a to_s that is identical to its inspect' do
@mash.abc = 123
@mash.to_s.should == @mash.inspect
@mash.to_s.should eq @mash.inspect
end
it "should return nil instead of raising an error for attribute-esque method calls" do
it 'should return nil instead of raising an error for attribute-esque method calls' do
@mash.abc.should be_nil
end
it "should return the default value if set like Hash" do
it 'should return the default value if set like Hash' do
@mash.default = 123
@mash.abc.should == 123
@mash.abc.should eq 123
end
it "should gracefully handle being accessed with arguments" do
@mash.abc("foobar").should == nil
it 'should gracefully handle being accessed with arguments' do
@mash.abc('foobar').should eq nil
@mash.abc = 123
@mash.abc("foobar").should == 123
@mash.abc('foobar').should eq 123
end
it "should return a Hashie::Mash when passed a bang method to a non-existenct key" do
it 'should return a Hashie::Mash when passed a bang method to a non-existenct key' do
@mash.abc!.is_a?(Hashie::Mash).should be_true
end
it "should return the existing value when passed a bang method for an existing key" do
@mash.name = "Bob"
@mash.name!.should == "Bob"
it 'should return the existing value when passed a bang method for an existing key' do
@mash.name = 'Bob'
@mash.name!.should eq 'Bob'
end
it "should return a Hashie::Mash when passed an under bang method to a non-existenct key" do
it 'should return a Hashie::Mash when passed an under bang method to a non-existenct key' do
@mash.abc_.is_a?(Hashie::Mash).should be_true
end
it "should return the existing value when passed an under bang method for an existing key" do
@mash.name = "Bob"
@mash.name_.should == "Bob"
it 'should return the existing value when passed an under bang method for an existing key' do
@mash.name = 'Bob'
@mash.name_.should eq 'Bob'
end
it "#initializing_reader should return a Hashie::Mash when passed a non-existent key" do
it '#initializing_reader should return a Hashie::Mash when passed a non-existent key' do
@mash.initializing_reader(:abc).is_a?(Hashie::Mash).should be_true
end
it "should allow for multi-level assignment through bang methods" do
@mash.author!.name = "Michael Bleigh"
@mash.author.should == Hashie::Mash.new(:name => "Michael Bleigh")
@mash.author!.website!.url = "http://www.mbleigh.com/"
@mash.author.website.should == Hashie::Mash.new(:url => "http://www.mbleigh.com/")
it 'should allow for multi-level assignment through bang methods' do
@mash.author!.name = 'Michael Bleigh'
@mash.author.should eq Hashie::Mash.new(name: 'Michael Bleigh')
@mash.author!.website!.url = 'http://www.mbleigh.com/'
@mash.author.website.should eq Hashie::Mash.new(url: 'http://www.mbleigh.com/')
end
it "should allow for multi-level under bang testing" do
it 'should allow for multi-level under bang testing' do
@mash.author_.website_.url.should be_nil
@mash.author_.website_.url?.should == false
@mash.author_.website_.url?.should eq false
@mash.author.should be_nil
end
it "should not call super if id is not a key" do
@mash.id.should == nil
it 'should not call super if id is not a key' do
@mash.id.should eq nil
end
it "should return the value if id is a key" do
@mash.id = "Steve"
@mash.id.should == "Steve"
it 'should return the value if id is a key' do
@mash.id = 'Steve'
@mash.id.should eq 'Steve'
end
it "should not call super if type is not a key" do
@mash.type.should == nil
it 'should not call super if type is not a key' do
@mash.type.should eq nil
end
it "should return the value if type is a key" do
@mash.type = "Steve"
@mash.type.should == "Steve"
it 'should return the value if type is a key' do
@mash.type = 'Steve'
@mash.type.should eq 'Steve'
end
context "updating" do
subject {
described_class.new :first_name => "Michael", :last_name => "Bleigh",
:details => {:email => "michael@asf.com", :address => "Nowhere road"}
}
context 'updating' do
subject do
described_class.new first_name: 'Michael', last_name: 'Bleigh',
details: { email: 'michael@asf.com', address: 'Nowhere road' }
end
describe "#deep_update" do
it "should recursively Hashie::Mash Hashie::Mashes and hashes together" do
subject.deep_update(:details => {:email => "michael@intridea.com", :city => "Imagineton"})
subject.first_name.should == "Michael"
subject.details.email.should == "michael@intridea.com"
subject.details.address.should == "Nowhere road"
subject.details.city.should == "Imagineton"
describe '#deep_update' do
it 'should recursively Hashie::Mash Hashie::Mashes and hashes together' do
subject.deep_update(details: { email: 'michael@intridea.com', city: 'Imagineton' })
subject.first_name.should eq 'Michael'
subject.details.email.should eq 'michael@intridea.com'
subject.details.address.should eq 'Nowhere road'
subject.details.city.should eq 'Imagineton'
end
it "should convert values only once" do
it 'should convert values only once' do
class ConvertedMash < Hashie::Mash
end
rhs = ConvertedMash.new({:email => "foo@bar.com"})
rhs = ConvertedMash.new(email: 'foo@bar.com')
subject.should_receive(:convert_value).exactly(1).times
subject.deep_update(rhs)
end
it "should make #update deep by default" do
subject.update(:details => {:address => "Fake street"}).should eql(subject)
subject.details.address.should == "Fake street"
subject.details.email.should == "michael@asf.com"
it 'should make #update deep by default' do
subject.update(details: { address: 'Fake street' }).should eql(subject)
subject.details.address.should eq 'Fake street'
subject.details.email.should eq 'michael@asf.com'
end
it "should clone before a #deep_merge" do
duped = subject.deep_merge(:details => {:address => "Fake street"})
it 'should clone before a #deep_merge' do
duped = subject.deep_merge(details: { address: 'Fake street' })
duped.should_not eql(subject)
duped.details.address.should == "Fake street"
subject.details.address.should == "Nowhere road"
duped.details.email.should == "michael@asf.com"
duped.details.address.should eq 'Fake street'
subject.details.address.should eq 'Nowhere road'
duped.details.email.should eq 'michael@asf.com'
end
it "regular #merge should be deep" do
duped = subject.merge(:details => {:email => "michael@intridea.com"})
it 'regular #merge should be deep' do
duped = subject.merge(details: { email: 'michael@intridea.com' })
duped.should_not eql(subject)
duped.details.email.should == "michael@intridea.com"
duped.details.address.should == "Nowhere road"
duped.details.email.should eq 'michael@intridea.com'
duped.details.address.should eq 'Nowhere road'
end
# http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-update
it "accepts a block" do
duped = subject.merge(:details => {:address => "Pasadena CA"}) {|key, oldv, newv| [oldv, newv].join(', ')}
duped.details.address.should == 'Nowhere road, Pasadena CA'
it 'accepts a block' do
duped = subject.merge(details: { address: 'Pasadena CA' }) { |key, oldv, newv| [oldv, newv].join(', ') }
duped.details.address.should eq 'Nowhere road, Pasadena CA'
end
end
describe "shallow update" do
it "should shallowly Hashie::Mash Hashie::Mashes and hashes together" do
subject.shallow_update(:details => {
:email => "michael@intridea.com", :city => "Imagineton"
describe 'shallow update' do
it 'should shallowly Hashie::Mash Hashie::Mashes and hashes together' do
subject.shallow_update(details: {
email: 'michael@intridea.com', city: 'Imagineton'
}).should eql(subject)
subject.first_name.should == "Michael"
subject.details.email.should == "michael@intridea.com"
subject.first_name.should eq 'Michael'
subject.details.email.should eq 'michael@intridea.com'
subject.details.address.should be_nil
subject.details.city.should == "Imagineton"
subject.details.city.should eq 'Imagineton'
end
it "should clone before a #regular_merge" do
duped = subject.shallow_merge(:details => {:address => "Fake street"})
it 'should clone before a #regular_merge' do
duped = subject.shallow_merge(details: { address: 'Fake street' })
duped.should_not eql(subject)
end
it "regular merge should be shallow" do
duped = subject.shallow_merge(:details => {:address => "Fake street"})
duped.details.address.should == "Fake street"
subject.details.address.should == "Nowhere road"
it 'regular merge should be shallow' do
duped = subject.shallow_merge(details: { address: 'Fake street' })
duped.details.address.should eq 'Fake street'
subject.details.address.should eq 'Nowhere road'
duped.details.email.should be_nil
end
end
describe '#replace' do
before do
subject.replace(:middle_name => "Cain",
:details => {:city => "Imagination"})
subject.replace(middle_name: 'Cain',
details: { city: 'Imagination' })
end
it 'return self' do
subject.replace(:foo => "bar").to_hash.should == {"foo" => "bar"}
subject.replace(foo: 'bar').to_hash.should eq('foo' => 'bar')
end
it 'sets all specified keys to their corresponding values' do
subject.middle_name?.should be_true
subject.details?.should be_true
subject.middle_name.should == "Cain"
subject.middle_name.should eq 'Cain'
subject.details.city?.should be_true
subject.details.city.should == "Imagination"
subject.details.city.should eq 'Imagination'
end
it 'leaves only specified keys' do
subject.keys.sort.should == ['details', 'middle_name']
subject.keys.sort.should eq %w(details middle_name)
subject.first_name?.should be_false
subject.should_not respond_to(:first_name)
subject.last_name?.should be_false
@ -245,22 +245,22 @@ describe Hashie::Mash do
end
end
it "should convert hash assignments into Hashie::Mashes" do
@mash.details = {:email => 'randy@asf.com', :address => {:state => 'TX'} }
@mash.details.email.should == 'randy@asf.com'
@mash.details.address.state.should == 'TX'
it 'should convert hash assignments into Hashie::Mashes' do
@mash.details = { email: 'randy@asf.com', address: { state: 'TX' } }
@mash.details.email.should eq 'randy@asf.com'
@mash.details.address.state.should eq 'TX'
end
it "should not convert the type of Hashie::Mashes childs to Hashie::Mash" do
it 'should not convert the type of Hashie::Mashes childs to Hashie::Mash' do
class MyMash < Hashie::Mash
end
record = MyMash.new
record.son = MyMash.new
record.son.class.should == MyMash
record.son.class.should eq MyMash
end
it "should not change the class of Mashes when converted" do
it 'should not change the class of Mashes when converted' do
class SubMash < Hashie::Mash
end
@ -270,7 +270,7 @@ describe Hashie::Mash do
record['submash'].should be_kind_of(SubMash)
end
it "should respect the class when passed a bang method for a non-existent key" do
it 'should respect the class when passed a bang method for a non-existent key' do
record = Hashie::Mash.new
record.non_existent!.should be_kind_of(Hashie::Mash)
@ -281,7 +281,7 @@ describe Hashie::Mash do
son.non_existent!.should be_kind_of(SubMash)
end
it "should respect the class when passed an under bang method for a non-existent key" do
it 'should respect the class when passed an under bang method for a non-existent key' do
record = Hashie::Mash.new
record.non_existent_.should be_kind_of(Hashie::Mash)
@ -292,172 +292,172 @@ describe Hashie::Mash do
son.non_existent_.should be_kind_of(SubMash)
end
it "should respect the class when converting the value" do
it 'should respect the class when converting the value' do
record = Hashie::Mash.new
record.details = Hashie::Mash.new({:email => "randy@asf.com"})
record.details = Hashie::Mash.new(email: 'randy@asf.com')
record.details.should be_kind_of(Hashie::Mash)
end
it "should respect another subclass when converting the value" do
it 'should respect another subclass when converting the value' do
record = Hashie::Mash.new
class SubMash < Hashie::Mash
end
son = SubMash.new({:email => "foo@bar.com"})
son = SubMash.new(email: 'foo@bar.com')
record.details = son
record.details.should be_kind_of(SubMash)
end
describe "#respond_to?" do
describe '#respond_to?' do
it 'should respond to a normal method' do
Hashie::Mash.new.should be_respond_to(:key?)
end
it 'should respond to a set key' do
Hashie::Mash.new(:abc => 'def').should be_respond_to(:abc)
Hashie::Mash.new(abc: 'def').should be_respond_to(:abc)
end
it 'should respond to a set key with a suffix' do
%w(= ? ! _).each do |suffix|
Hashie::Mash.new(:abc => 'def').should be_respond_to(:"abc#{suffix}")
Hashie::Mash.new(abc: 'def').should be_respond_to(:"abc#{suffix}")
end
end
it 'should not respond to an unknown key with a suffix' do
%w(= ? ! _).each do |suffix|
Hashie::Mash.new(:abc => 'def').should_not be_respond_to(:"xyz#{suffix}")
Hashie::Mash.new(abc: 'def').should_not be_respond_to(:"xyz#{suffix}")
end
end
it "should not respond to an unknown key without a suffix" do
Hashie::Mash.new(:abc => 'def').should_not be_respond_to(:xyz)
it 'should not respond to an unknown key without a suffix' do
Hashie::Mash.new(abc: 'def').should_not be_respond_to(:xyz)
end
it "should not respond to permitted?" do
it 'should not respond to permitted?' do
Hashie::Mash.new.should_not be_respond_to(:permitted?)
end
end
context "#initialize" do
it "should convert an existing hash to a Hashie::Mash" do
converted = Hashie::Mash.new({:abc => 123, :name => "Bob"})
converted.abc.should == 123
converted.name.should == "Bob"
context '#initialize' do
it 'should convert an existing hash to a Hashie::Mash' do
converted = Hashie::Mash.new(abc: 123, name: 'Bob')
converted.abc.should eq 123
converted.name.should eq 'Bob'
end
it "should convert hashes recursively into Hashie::Mashes" do
converted = Hashie::Mash.new({:a => {:b => 1, :c => {:d => 23}}})
it 'should convert hashes recursively into Hashie::Mashes' do
converted = Hashie::Mash.new(a: { b: 1, c: { d: 23 } })
converted.a.is_a?(Hashie::Mash).should be_true
converted.a.b.should == 1
converted.a.c.d.should == 23
converted.a.b.should eq 1
converted.a.c.d.should eq 23
end
it "should convert hashes in arrays into Hashie::Mashes" do
converted = Hashie::Mash.new({:a => [{:b => 12}, 23]})
converted.a.first.b.should == 12
converted.a.last.should == 23
it 'should convert hashes in arrays into Hashie::Mashes' do
converted = Hashie::Mash.new(a: [{ b: 12 }, 23])
converted.a.first.b.should eq 12
converted.a.last.should eq 23
end
it "should convert an existing Hashie::Mash into a Hashie::Mash" do
initial = Hashie::Mash.new(:name => 'randy', :address => {:state => 'TX'})
it 'should convert an existing Hashie::Mash into a Hashie::Mash' do
initial = Hashie::Mash.new(name: 'randy', address: { state: 'TX' })
copy = Hashie::Mash.new(initial)
initial.name.should == copy.name
initial.__id__.should_not == copy.__id__
copy.address.state.should == 'TX'
initial.name.should eq copy.name
initial.__id__.should_not eq copy.__id__
copy.address.state.should eq 'TX'
copy.address.state = 'MI'
initial.address.state.should == 'TX'
copy.address.__id__.should_not == initial.address.__id__
initial.address.state.should eq 'TX'
copy.address.__id__.should_not eq initial.address.__id__
end
it "should accept a default block" do
initial = Hashie::Mash.new { |h,i| h[i] = []}
it 'should accept a default block' do
initial = Hashie::Mash.new { |h, i| h[i] = [] }
initial.default_proc.should_not be_nil
initial.default.should be_nil
initial.test.should == []
initial.test.should eq []
initial.test?.should be_true
end
it "should convert Hashie::Mashes within Arrays back to Hashes" do
initial_hash = {"a" => [{"b" => 12, "c" =>["d" => 50, "e" => 51]}, 23]}
it 'should convert Hashie::Mashes within Arrays back to Hashes' do
initial_hash = { 'a' => [{ 'b' => 12, 'c' => ['d' => 50, 'e' => 51] }, 23] }
converted = Hashie::Mash.new(initial_hash)
converted.to_hash["a"].first.is_a?(Hashie::Mash).should be_false
converted.to_hash["a"].first.is_a?(Hash).should be_true
converted.to_hash["a"].first["c"].first.is_a?(Hashie::Mash).should be_false
converted.to_hash['a'].first.is_a?(Hashie::Mash).should be_false
converted.to_hash['a'].first.is_a?(Hash).should be_true
converted.to_hash['a'].first['c'].first.is_a?(Hashie::Mash).should be_false
end
end
describe "#fetch" do
let(:hash) { {:one => 1, :other => false} }
describe '#fetch' do
let(:hash) { { one: 1, other: false } }
let(:mash) { Hashie::Mash.new(hash) }
context "when key exists" do
it "returns the value" do
context 'when key exists' do
it 'returns the value' do
mash.fetch(:one).should eql(1)
end
it "returns the value even if the value is falsy" do
it 'returns the value even if the value is falsy' do
mash.fetch(:other).should eql(false)
end
context "when key has other than original but acceptable type" do
it "returns the value" do
context 'when key has other than original but acceptable type' do
it 'returns the value' do
mash.fetch('one').should eql(1)
end
end
end
context "when key does not exist" do
it "should raise KeyError" do
context 'when key does not exist' do
it 'should raise KeyError' do
error = RUBY_VERSION =~ /1.8/ ? IndexError : KeyError
expect { mash.fetch(:two) }.to raise_error(error)
end
context "with default value given" do
it "returns default value" do
context 'with default value given' do
it 'returns default value' do
mash.fetch(:two, 8).should eql(8)
end
it "returns default value even if it is falsy" do
it 'returns default value even if it is falsy' do
mash.fetch(:two, false).should eql(false)
end
end
context "with block given" do
it "returns default value" do
mash.fetch(:two) {|key|
"block default value"
}.should eql("block default value")
context 'with block given' do
it 'returns default value' do
mash.fetch(:two) do|key|
'block default value'
end.should eql('block default value')
end
end
end
end
describe "#to_hash" do
let(:hash) { { "outer" => { "inner" => 42 }, "testing" => [1, 2, 3] } }
describe '#to_hash' do
let(:hash) { { 'outer' => { 'inner' => 42 }, 'testing' => [1, 2, 3] } }
let(:mash) { Hashie::Mash.new(hash) }
it "returns a standard Hash" do
it 'returns a standard Hash' do
mash.to_hash.should be_a(::Hash)
end
it "includes all keys" do
it 'includes all keys' do
mash.to_hash.keys.should eql(%w(outer testing))
end
it "converts keys to symbols when symbolize_keys option is true" do
mash.to_hash(:symbolize_keys => true).keys.should include(:outer)
mash.to_hash(:symbolize_keys => true).keys.should_not include("outer")
it 'converts keys to symbols when symbolize_keys option is true' do
mash.to_hash(symbolize_keys: true).keys.should include(:outer)
mash.to_hash(symbolize_keys: true).keys.should_not include('outer')
end
it "leaves keys as strings when symbolize_keys option is false" do
mash.to_hash(:symbolize_keys => false).keys.should include("outer")
mash.to_hash(:symbolize_keys => false).keys.should_not include(:outer)
it 'leaves keys as strings when symbolize_keys option is false' do
mash.to_hash(symbolize_keys: false).keys.should include('outer')
mash.to_hash(symbolize_keys: false).keys.should_not include(:outer)
end
it "symbolizes keys recursively" do
mash.to_hash(:symbolize_keys => true)[:outer].keys.should include(:inner)
mash.to_hash(:symbolize_keys => true)[:outer].keys.should_not include("inner")
it 'symbolizes keys recursively' do
mash.to_hash(symbolize_keys: true)[:outer].keys.should include(:inner)
mash.to_hash(symbolize_keys: true)[:outer].keys.should_not include('inner')
end
end
end

View File

@ -2,7 +2,7 @@ require 'spec_helper'
describe Hashie::Trash do
class TrashTest < Hashie::Trash
property :first_name, :from => :firstName
property :first_name, from: :firstName
end
let(:trash) { TrashTest.new }
@ -32,124 +32,124 @@ describe Hashie::Trash do
describe 'writing to properties' do
it 'does not write to a non-existent property using []=' do
lambda{trash['abc'] = 123}.should raise_error(NoMethodError)
lambda { trash['abc'] = 123 }.should raise_error(NoMethodError)
end
it 'writes to an existing property using []=' do
lambda{trash['first_name'] = 'Bob'}.should_not raise_error
lambda { trash['first_name'] = 'Bob' }.should_not raise_error
end
it 'writes to a translated property using []=' do
lambda{trash['firstName'] = 'Bob'}.should_not raise_error
lambda { trash['firstName'] = 'Bob' }.should_not raise_error
end
it 'reads/writes to an existing property using a method call' do
trash.first_name = 'Franklin'
trash.first_name.should == 'Franklin'
trash.first_name.should eq 'Franklin'
end
it 'writes to an translated property using a method call' do
trash.firstName = 'Franklin'
trash.first_name.should == 'Franklin'
trash.first_name.should eq 'Franklin'
end
it 'writes to a translated property using #replace' do
trash.replace(:firstName => 'Franklin')
trash.first_name.should == 'Franklin'
trash.replace(firstName: 'Franklin')
trash.first_name.should eq 'Franklin'
end
it 'writes to a non-translated property using #replace' do
trash.replace(:first_name => 'Franklin')
trash.first_name.should == 'Franklin'
trash.replace(first_name: 'Franklin')
trash.first_name.should eq 'Franklin'
end
end
describe ' initializing with a Hash' do
it 'does not initialize non-existent properties' do
lambda{TrashTest.new(:bork => 'abc')}.should raise_error(NoMethodError)
lambda { TrashTest.new(bork: 'abc') }.should raise_error(NoMethodError)
end
it 'sets the desired properties' do
TrashTest.new(:first_name => 'Michael').first_name.should == 'Michael'
TrashTest.new(first_name: 'Michael').first_name.should eq 'Michael'
end
context "with both the translated property and the property" do
context 'with both the translated property and the property' do
it 'sets the desired properties' do
TrashTest.new(:first_name => 'Michael', :firstName=>'Maeve').first_name.should == 'Michael'
TrashTest.new(first_name: 'Michael', firstName: 'Maeve').first_name.should eq 'Michael'
end
end
it 'sets the translated properties' do
TrashTest.new(:firstName => 'Michael').first_name.should == 'Michael'
TrashTest.new(firstName: 'Michael').first_name.should eq 'Michael'
end
end
describe 'translating properties using a proc' do
class TrashLambdaTest < Hashie::Trash
property :first_name, :from => :firstName, :with => lambda { |value| value.reverse }
property :first_name, from: :firstName, with: lambda { |value| value.reverse }
end
let(:lambda_trash) { TrashLambdaTest.new }
it 'should translate the value given on initialization with the given lambda' do
TrashLambdaTest.new(:firstName => 'Michael').first_name.should == 'Michael'.reverse
TrashLambdaTest.new(firstName: 'Michael').first_name.should eq 'Michael'.reverse
end
it 'should not translate the value if given with the right property' do
TrashTest.new(:first_name => 'Michael').first_name.should == 'Michael'
TrashTest.new(first_name: 'Michael').first_name.should eq 'Michael'
end
it 'should translate the value given as property with the given lambda' do
lambda_trash.firstName = 'Michael'
lambda_trash.first_name.should == 'Michael'.reverse
lambda_trash.first_name.should eq 'Michael'.reverse
end
it 'should not translate the value given as right property' do
lambda_trash.first_name = 'Michael'
lambda_trash.first_name.should == 'Michael'
lambda_trash.first_name.should eq 'Michael'
end
end
describe 'translating properties without from option using a proc' do
class TrashLambdaTest2 < Hashie::Trash
property :first_name, :transform_with => lambda { |value| value.reverse }
property :first_name, transform_with: lambda { |value| value.reverse }
end
let(:lambda_trash) { TrashLambdaTest2.new }
it 'should translate the value given as property with the given lambda' do
lambda_trash.first_name = 'Michael'
lambda_trash.first_name.should == 'Michael'.reverse
lambda_trash.first_name.should eq 'Michael'.reverse
end
it 'should transform the value when given in constructor' do
TrashLambdaTest2.new(:first_name => 'Michael').first_name.should == 'Michael'.reverse
TrashLambdaTest2.new(first_name: 'Michael').first_name.should eq 'Michael'.reverse
end
context "when :from option is given" do
context 'when :from option is given' do
class TrashLambdaTest3 < Hashie::Trash
property :first_name, :from => :firstName, :transform_with => lambda { |value| value.reverse }
property :first_name, from: :firstName, transform_with: lambda { |value| value.reverse }
end
it 'should not override the :from option in the constructor' do
TrashLambdaTest3.new(:first_name => 'Michael').first_name.should == 'Michael'
TrashLambdaTest3.new(first_name: 'Michael').first_name.should eq 'Michael'
end
it 'should not override the :from option when given as property' do
t = TrashLambdaTest3.new
t.first_name = 'Michael'
t.first_name.should == 'Michael'
t.first_name.should eq 'Michael'
end
end
end
it "should raise an error when :from have the same value as property" do
expect {
it 'should raise an error when :from have the same value as property' do
expect do
class WrongTrash < Hashie::Trash
property :first_name, :from => :first_name
property :first_name, from: :first_name
end
}.to raise_error(ArgumentError)
end.to raise_error(ArgumentError)
end
end