Grape: Errors with using entity documentation

Created on 4 Mar 2016  路  15Comments  路  Source: ruby-grape/grape

I was trying to migrate my params to using entities and I'm getting different types of errors. Is this grape-entity error or grape?

#...
      requires :all, using: Entity::Activity.documentation.except(:id)
#...
module Entity
  class Activity < Base
    expose :id, documentation: {type: 'integer', desc: 'id'}
    expose :active, documentation: {type: 'Boolean', desc: 'id'}
# ...

This is error happens first of all.

lib/grape/validations/types.rb:114:in `recognized?': undefined method `ancestors' for "string":String (NoMethodError)

This error happens when I'm changing type to classes. I get it we don't have Boolean type in ruby and grape uses virtus, but with Integer and String type there is no errors.

`<class:Activity>': uninitialized constant Entity::Activity::Boolean (NameError)
bug?

Most helpful comment

One more thing. This will fail if one of your parameters is type: Boolean. Based on what I read in #1144, I changed to type: Grape::API::Boolean.

All 15 comments

To me Entity::Activity.documentation.except(:id) looks suspicious, why would that even work?

@dblock I took this line from readme.

      requires :all, except: [:ip], using: API::Entities::Status.documentation.except(:id)

Ok, I guess this needs a spec in Grape or Grape::Entity. You should try to do that next.

@dblock I should write a spec? I don't understand. Documentation is a bit misleading.
Here what I found.
This works.

    desc 'Returns your public timeline.' do
      detail 'more details'
      params Entity::Value.documentation.except(:id, :errors)
    end

If i want to overwrite or make field required i could do params block below but it add new param instead of overwriting previous params.

And i can't use params block within desc block.

    desc 'Returns your public timeline.' do
      params do
        requires :all, Entity::Value.documentation.except(:id, :errors)
      end
    end

This gives error

lib/grape/util/strict_hash_configuration.rb:48:in `block (2 levels) in simple_settings_methods': wrong number of arguments (given 0, expected 1) (ArgumentError)

I haven't dug through this. If the documentation says something that you're trying to do and it doesn't work, it's a bug in either the code or the doc. I'll take a look later in depth, but feel free to do what you think is right and make pull requests. I know I am not being very helpful here ;)

@onemanstartup Did you ever find a solution to this? I'm trying to do something similar, and running into the same problem.

I'm still working on my issue, but I've figured out a couple things:

  • Make sure type in your Grape::Entity is class, not a string (ie: type: String, not type: 'String')
  • It appears that the keys of the documentation hash in your Grape::Entity are used as validators. So, in my case, required: true was failing, because there was no required validator. I fixed that by changing that to presence: true
  • In params do, you can use optional or required, with the first param being :all or :none, and it will process those accordingly. (ie: optional :all will make all of the params from your entity optional, except the ones specified in the except array, whereas optional :none will make all of them required)
  • I think the documentation is flat-out wrong for the .except part. I haven't confirmed yet.

I'm still trying to fix my problem, but if/when I do, I will submit a PR to either fix some bugs, or update the readme, or maybe both.

Alright, I've fixed my issue. It turns out that there's a known bug with grape and active_model 4+. To fix it, I added the hashie-forbidden-attributes gem to my project.


Before I found that, I wrote this little helper method. I hope it helps someone in the future:

  def validators_from_documentation(doc_hash)
    validators = Grape::Validations.validators.keys.map(&:to_sym)
    doc_hash.map do |k, v|
      [k, v.select { |validator| validators.include?(validator) }]
    end.to_h
  end

@dkniffin Yours doesn't look like a problem identical to this issue, or did I miss something?

@dblock I did originally start with an error very similar to this: lib/grape/validations/types.rb:114:in 'recognized?': undefined method 'ancestors' for "string":String (NoMethodError) I fixed it with my first bullet above:

Make sure type in your Grape::Entity is class, not a string (ie: type: String, not type: 'String')

Then I ran into several other issues.

@onemanstartup Anty of this helps? What do we want to do with this bug?

For me almost everything worked correctly after following @dkniffin's advice.

  • I named types as classes instead of strings.
  • I removed all uses of required from documentation, using instead requires or optional in params.
  • The .documentation.except part worked without problems.
  • I was able to keep the Swagger example with a nested documentation, like expose :deadline, documentation: { type: Date, desc: 'Completion deadline', documentation: { example: '2017-12-31' } }.

The only issue is that because required was removed from the documentation, the Swagger response class model says that the parameters are optional, but it's obviously not a big deal.

@onemanstartup I'd like to close this, thanks @guavabot. Reopen with details of anything you cannot figure out.

One more thing. This will fail if one of your parameters is type: Boolean. Based on what I read in #1144, I changed to type: Grape::API::Boolean.

Just want to make sure there's nothing to do in grape proper for that @guavabot.

Was this page helpful?
0 / 5 - 0 ratings