简体   繁体   English

如何使用Grape on Rails创建动态API路由并验证自定义参数

[英]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. 我正在使用Grape进行我的Rails api开发,该模型对于除动态模型形式之外的所有模型都运行良好。 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. product_typeproduct_fieldsproducts模型都具有has_many关联。 While creating a new product_type we can create various field attributes for that product . 在创建新的product_type我们可以为该product创建各种字段属性。 Each product has different attributes, but we store them in sing table "products". 每个product都有不同的属性,但是我们将它们存储在“产品”表中。 I want to generate the API dynamically whenever any product_type is added. 每当添加任何product_type时,我都希望动态生成API。

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. 据我了解,您打算为每种产品类型创建一个API路由。 However, your approach will not work as you planned. 但是,您的方法将无法按计划进行。 Grape generates the API routes only during the application initialization phase and not at runtime. Grape仅在应用程序初始化阶段而不在运行时生成API路由。

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. 产品类型必须只有一个API路由才能覆盖所有当前和将来的对象实例。 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. 这解决了您创建动态API路由的问题,但是根据是否需要ProductType的字段,它不涉及参数验证。 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. 不过,您也可以编写您的自定义验证程序,该验证程序加载ProductType实例,然后验证其余参数。 I recently described this approach in How to validate this hash parameter? 我最近在“ 如何验证此哈希参数?”中介绍了这种方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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