简体   繁体   中英

How to create dynamic API routes with Grape on Rails and validate custom params

I am using grape for my rails api development which is working pretty good for all the model except dynamic model form. We have following models..

1- product_type
2- product_fields
3- products

The product_type is having having has_many association with both product_fields and products model. While creating a new product_type we can create various field attributes for that product . Each product has different attributes, but we store them in sing table "products". I want to generate the API dynamically whenever any product_type is added.

I have tried as shown below but keep getting errors while posting the record. Appreciate any suggestion.

require 'grape'

module API  
    module V1
        class Products < Grape::API
            include API::V1::Defaults            
            @product_type=ProductType.all
            @product_type.each do |producttype|
                resource :"#{producttype.name}" do
                    desc "Create a new product for #{producttype.name}"
                    params do
                        requires :product_type_id , type: "Integer",  desc: "product type Id"
                        producttype.productfields.each do |field|
                            if field.is_required? 
                              requires :"#{field.field_name}" , type: "#{field.filed_type}",  desc: "#{field.field_name}"
                            else
                              optional :"#{field.field_name}", type: "#{field.filed_type}", desc: "#{field.field_name}"
                            end
                        end
                    end
                    post do
                        Products.create!({
                            product_type_id:params[:product_type_id],
                            ........
                            ........
                            ........
                        })
                    end
                end
            end
        end
    end
end   

Error:

  NoMethodError - undefined method `collect' for nil:NilClass:
  grape-swagger (0.10.1) lib/grape-swagger.rb:70:in `block in combine_namespace_routes'
  grape-swagger (0.10.1) lib/grape-swagger.rb:65:in `combine_namespace_routes'
  grape-swagger (0.10.1) lib/grape-swagger.rb:39:in `add_swagger_documentation'
  app/controllers/api/v1/base.rb:10:in `<class:Base>'
  app/controllers/api/v1/base.rb:6:in `<module:V1>'
  app/controllers/api/v1/base.rb:5:in `<module:API>'
  app/controllers/api/v1/base.rb:4:in `<top (required)>'

Okay, thx for updating your question, now one can see the problem.

As far as I understood, what you intend to do is to create an API route for each product type. However, your approach will not work as you planned. Grape generates the API routes only during the application initialization phase and not at runtime.

What you would have to do instead is define your route as follows:

params do
  requires :producttype_id, type: Integer, desc: "The product type's ID"
end
post '/:producttype_id' do
  # check if params[:producttype_id] is valid, otherwise raise 404
  ProductType.find([params[:producttype_id]])

  # raise an error if the ProductType was not found
  error! 'ProductType not found', 404

  # do some stuff...

  # return your response
  { producttype_id: params[:producttype_id] }
end

There must be only one API route for the ProductTypes to cover all current and future object instances. However, you then need to validate the instance's existence!

This solves your problem to create the dynamic API routes, but does not cover the parameter validation depending on whether the ProductType's field is required or not. Personally I would embed this validation logic in the code, rather than the route itself. Nevertheless you could also write your custom validator which loads the ProductType instance and then validates the remaining parameters. I recently described this approach in How to validate this hash parameter?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM