Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Hashie::Extensions::Mash::SafeAssignment #205

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@
* [#197](https://github.com/intridea/hashie/pull/197): Dont convert keys to string on initalization of mash - [@gregory](https://github.com/gregory).
* [#201](https://github.com/intridea/hashie/pull/201): Hashie::Trash transforms can be inherited - [@fobocaster](https://github.com/fobocaster).
* [#189](https://github.com/intridea/hashie/pull/189): Added Rash#fetch - [@medcat](https://github.com/medcat).
* [#205](http://github.com/intridea/hashie/pull/205): Added Hashie::Extensions::Mash::SafeAssignment - [@michaelherold](https://github.com/michaelherold).
* Your contribution here.

## 3.2.0 (7/10/2014)
Expand Down
15 changes: 15 additions & 0 deletions README.md
Expand Up @@ -267,6 +267,21 @@ mash = Mash.load('data/user.csv', parser: MyCustomCsvParser)
mash[1] #=> { name: 'John', lastname: 'Doe' }
```

### Mash Extension: SafeAssignment

This extension can be mixed into a Mash to guard the attempted overwriting of methods by property setters. When mixed in, the Mash will raise an `ArgumentError` if you attempt to write a property with the same name as an existing method.

#### Example:

```ruby
class SafeMash < ::Hashie::Mash
include Hashie::Extensions::Mash::SafeAssignment
end

safe_mash = SafeMash.new
safe_mash.zip = 'Test' # => ArgumentError
```

## Dash

Dash is an extended Hash that has a discrete set of defined properties and only those properties may be set on the hash. Additionally, you can set defaults for each property. You can also flag a property as required. Required properties will raise an exception if unset.
Expand Down
4 changes: 4 additions & 0 deletions lib/hashie.rb
Expand Up @@ -31,5 +31,9 @@ module Parsers
module Dash
autoload :IndifferentAccess, 'hashie/extensions/dash/indifferent_access'
end

module Mash
autoload :SafeAssignment, 'hashie/extensions/mash/safe_assignment'
end
end
end
13 changes: 13 additions & 0 deletions lib/hashie/extensions/mash/safe_assignment.rb
@@ -0,0 +1,13 @@
module Hashie
module Extensions
module Mash
module SafeAssignment
def assign_property(name, value)
fail ArgumentError, "The property #{name} clashes with an existing method." if methods.include?(name)

self[name] = value
end
end
end
end
end
7 changes: 6 additions & 1 deletion lib/hashie/mash.rb
Expand Up @@ -160,6 +160,11 @@ def deep_update(other_hash, &blk)
alias_method :update, :deep_update
alias_method :merge!, :update

# Assigns a value to a key
def assign_property(name, value)
self[name] = value
end

# Performs a shallow_update on a duplicate of the current mash
def shallow_merge(other_hash)
dup.shallow_update(other_hash)
Expand Down Expand Up @@ -201,7 +206,7 @@ def method_missing(method_name, *args, &blk)
name, suffix = method_suffix(method_name)
case suffix
when '='
self[name] = args.first
assign_property(name, args.first)
when '?'
!!self[name]
when '!'
Expand Down
17 changes: 17 additions & 0 deletions spec/hashie/extensions/mash/safe_assignment_spec.rb
@@ -0,0 +1,17 @@
require 'spec_helper'

describe Hashie::Extensions::Mash::SafeAssignment do
class MashWithSafeAssignment < Hashie::Mash
include Hashie::Extensions::Mash::SafeAssignment
end

context 'when included in Mash' do
subject { MashWithSafeAssignment.new }

context 'when attempting to override a method' do
it 'raises an error' do
expect { subject.zip = 'Test' }.to raise_error(ArgumentError)
end
end
end
end