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

Modifying params in the endpoint will change the default #1438

Closed
ashkan18 opened this issue Jul 12, 2016 · 5 comments
Closed

Modifying params in the endpoint will change the default #1438

ashkan18 opened this issue Jul 12, 2016 · 5 comments

Comments

@ashkan18
Copy link
Contributor

When using default of a param, modifying the param within the request will change the default. Here is a spec for the issue:

require 'spec_helper'

module FreezeDefaultForParamsSpec

  class Users < Grape::API
    resource :users do
      params do
        optional :sort, default: '-created_at'
      end
      get do
        params[:sort].slice!(0)
        params[:sort]
      end
    end
  end

  class Main < Grape::API
    mount Users
  end
end

describe Grape::API do
  subject { FreezeDefaultForParamsSpec::Main }

  def app
    subject
  end

  it 'should not change the default for the param' do
    get '/users'
    expect(last_response.status).to eql 200
    expect(last_response.body).to eql 'created_at'

    get '/users'
    expect(last_response.status).to eql 200
    expect(last_response.body).to eql 'created_at'
  end
end

For the first get in the spec, default is correct which is -created_at but on the second get, default sort param has changed to created_at because of params[:sort].slice!(0) in get.

Ideally we'd need to pass a clone of params, as an alternative we may need to freeze default.

@dblock
Copy link
Member

dblock commented Jul 12, 2016

I think we probably don't want to clone the default every time, which could be unnecessarily expensive for every request, but definitely freeze it.

@jlfaber
Copy link
Contributor

jlfaber commented Jul 14, 2016

@dblock If we freeze default, that might cause existing client code to suddenly start throwing RuntimeErrors (if they are mutating param values). Admittedly, they're probably not getting the behavior they expect on subsequent calls after the default has been modified. So there's already an error present. But it seems to me that the best course is to clone the default when it is assigned to a param.

This is also appealing because it means that params are uniformly modifiable whether they have a default value or not. Freezing the default would cause the two cases to behave differently, which I think is a much more confusing semantic.

Also, I haven't actually verified it, but I think the test spec above will only pass if default is cloned. If we freeze default, the slice! call is going to raise a RuntimeError.

@dblock
Copy link
Member

dblock commented Jul 14, 2016

I worry about unintentional performance overheads, but maybe I am worried about nothing. Either way I'll take a PR.

@dblock
Copy link
Member

dblock commented Jul 20, 2016

This was fixed in 8b72144.

@ashkan18
Copy link
Contributor Author

awesome! Thanks! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants