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

时间:2015-08-10 04:24:21

标签: ruby-on-rails rest grape grape-api

我正在使用grape进行我的rails api开发,除了动态模型形式之外,它对所有模型都有效。 我们有以下型号..

1- product_type
2- product_fields
3- products

product_typehas_manyproduct_fields模型有products关联。在创建新product_type时,我们可以为product创建各种字段属性。每个product都有不同的属性,但我们将它们存储在唱歌表"产品"中。我希望每当添加任何product_type时动态生成API。

我已尝试如下所示,但在发布记录时不断出错。感谢任何建议。

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   

错误:

  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)>'

1 个答案:

答案 0 :(得分:0)

好的,更新你的问题,现在可以看到问题。

据我了解,您打算为每种产品类型创建一个API路由。但是,您的方法无法按计划运行。 Grape仅在应用程序初始化阶段生成API路由,而不是在运行时生成。

您需要做的是定义您的路线,如下所示:

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

ProductTypes必须只有一个API路由才能涵盖所有当前和未来的对象实例。但是,您需要验证实例的存在!

这解决了创建动态API路由的问题,但不包括参数验证,具体取决于是否需要ProductType的字段。 我个人会将这个验证逻辑嵌入到代码中,而不是路由本身。不过,您也可以编写自定义验证器来加载ProductType实例,然后验证其余参数。我最近在How to validate this hash parameter?

中描述了这种方法