Skip to content

Remove hashie dependency #1448

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

Closed
wants to merge 1 commit into from
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#### Features

* [#1448](https://github.com/ruby-grape/grape/pull/1448): Remove Hashie dependency - [@etehtsea](https://github.com/etehtsea).
* [#1440](https://github.com/ruby-grape/grape/pull/1441): Supports only Ruby 2.2.2 and later - [@jlfaber](https://github.com/jlfaber).
* [#1393](https://github.com/ruby-grape/grape/pull/1393): Middleware can be inserted before or after default Grape middleware - [@ridiculous](https://github.com/ridiculous).
* [#1390](https://github.com/ruby-grape/grape/pull/1390): Allow inserting middleware at arbitrary points in the middleware stack - [@Rosa](https://github.com/Rosa).
Expand Down
21 changes: 7 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,6 @@ Modify `config/routes`:
mount Twitter::API => '/'
```

Additionally, if the version of your Rails is 4.0+ and the application uses the default model layer of ActiveRecord, you will want to use the [hashie-forbidden_attributes gem](https://github.com/Maxim-Filimonov/hashie-forbidden_attributes). This gem disables the security feature of `strong_params` at the model layer, allowing you the use of Grape's own params validation instead.

```ruby
# Gemfile
gem 'hashie-forbidden_attributes'
```

See [below](#reloading-api-changes-in-development) for additional code that enables reloading of API changes in development.

### Modules
Expand Down Expand Up @@ -492,7 +485,7 @@ post 'users/signup' do
end
````

If we do not specify any params, `declared` will return an empty `Hashie::Mash` instance.
If we do not specify any params, `declared` will return an empty `ActiveSupport::HashWithIndifferentAccess` instance.

**Request**

Expand Down Expand Up @@ -545,10 +538,10 @@ curl -X POST -H "Content-Type: application/json" localhost:9292/users/signup -d
}
````

The returned hash is a `Hashie::Mash` instance, allowing you to access parameters via dot notation:
The returned hash is a `ActiveSupport::HashWithIndifferentAccess` instance, allowing you to access parameters via both `Symbol` and `String` keys:

```ruby
declared(params).user == declared(params)['user']
declared(params)[:user] == declared(params)['user']
```


Expand Down Expand Up @@ -866,10 +859,10 @@ params do
requires :avatar, type: File
end
post '/' do
# Parameter will be wrapped using Hashie:
params.avatar.filename # => 'avatar.png'
params.avatar.type # => 'image/png'
params.avatar.tempfile # => #<File>
# Parameter will be wrapped using `ActiveSupport::HashWithIndifferentAccess`:
params[:avatar][:filename] # => 'avatar.png'
params[:avatar][:type] # => 'image/png'
params[:avatar][:tempfile] # => #<File>
end
```

Expand Down
6 changes: 6 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ Upgrading Grape

### Upgrading to >= 0.16.0

#### Removed dependency from hashie gem

It means that `Grape::Request#params` became instance of `ActiveSupport::HashWithIndifferentAccess`
instead of `Hashie::Mash`. After this change `params` fields should be accessed
using usual `Hash` methods. Both `String` and `Symbol` keys are supported.

#### Removed official support for Ruby < 2.2.2

Since 0.16.3 Grape is no longer automatically tested against versions of Ruby prior to 2.2.2.
Expand Down
1 change: 0 additions & 1 deletion grape.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'activesupport'
s.add_runtime_dependency 'multi_json', '>= 1.3.2'
s.add_runtime_dependency 'multi_xml', '>= 0.5.2'
s.add_runtime_dependency 'hashie', '>= 2.1.0'
s.add_runtime_dependency 'virtus', '>= 1.0.0'
s.add_runtime_dependency 'builder'

Expand Down
1 change: 0 additions & 1 deletion lib/grape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
require 'rack/accept'
require 'rack/auth/basic'
require 'rack/auth/digest/md5'
require 'hashie'
require 'set'
require 'active_support/version'
require 'active_support/core_ext/hash/indifferent_access'
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/dsl/inside_route.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def declared(params, options = {}, declared_params = nil)
declared(param || {}, options, declared_params)
end
else
declared_params.each_with_object(Hashie::Mash.new) do |key, hash|
declared_params.each_with_object(ActiveSupport::HashWithIndifferentAccess.new) do |key, hash|
key = { key => nil } unless key.is_a? Hash

key.each_pair do |parent, children|
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def headers
private

def build_params
params = Hashie::Mash.new(rack_params)
params = rack_params.with_indifferent_access
if env[Grape::Env::GRAPE_ROUTING_ARGS]
args = env[Grape::Env::GRAPE_ROUTING_ARGS].dup
# preserve version from query string parameters
Expand Down
41 changes: 1 addition & 40 deletions lib/grape/validations/types/custom_type_coercer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,7 @@ def self.build(type, method = nil)
# @param method [#parse,#call]
# optional coercion method. See class docs.
def initialize(type, method = nil)
coercion_method = infer_coercion_method type, method

@method = enforce_symbolized_keys type, coercion_method

@method = infer_coercion_method type, method
@type_check = infer_type_check(type)
end

Expand Down Expand Up @@ -143,42 +140,6 @@ def infer_type_check(type)
->(value) { value.is_a? type }
end
end

# Enforce symbolized keys for complex types
# by wrapping the coercion method such that
# any Hash objects in the immediate heirarchy
# are passed through +Hashie.symbolize_keys!+.
# This helps common libs such as JSON to work easily.
#
# @param type see #new
# @param method see #infer_coercion_method
# @return [#call] +method+ wrapped in an additional
# key-conversion step, or just returns +method+
# itself if no conversion is deemed to be
# necessary.
def enforce_symbolized_keys(type, method)
# Collections have all values processed individually
if type == Array || type == Set
lambda do |val|
method.call(val).tap do |new_value|
new_value.each do |item|
Hashie.symbolize_keys!(item) if item.is_a? Hash
end
end
end

# Hash objects are processed directly
elsif type == Hash
lambda do |val|
Hashie.symbolize_keys! method.call(val)
end

# Simple types are not processed.
# This includes Array<primitive> types.
else
method
end
end
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions lib/grape/validations/types/file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ def coerce(input)
def value_coerced?(value)
# Rack::Request creates a Hash with filename,
# content type and an IO object. Grape wraps that
# using hashie for convenience. Do a bit of basic
# duck-typing.
value.is_a?(Hashie::Mash) && value.key?(:tempfile)
# using ActiveSupport::HashWithIndifferentAccess for convenience.
# Do a bit of basic duck-typing.
value.is_a?(::Hash) && value.key?(:tempfile)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/grape/validations/validators/coerce_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ class User
requires :file, type: Rack::Multipart::UploadedFile
end
subject.post '/upload' do
params[:file].filename
params[:file][:filename]
end

post '/upload', file: Rack::Test::UploadedFile.new(__FILE__)
Expand All @@ -302,7 +302,7 @@ class User
requires :file, coerce: File
end
subject.post '/upload' do
params[:file].filename
params[:file][:filename]
end

post '/upload', file: Rack::Test::UploadedFile.new(__FILE__)
Expand Down