Rails 求 grape-entity 使用经验分享

42thcoder · November 03, 2014 · Last by iBachue replied at November 06, 2014 · 6119 hits

目前做得项目重度使用了 grape-entity, 一边看 wiki, 一边翻源码,写得倒也顺利。但是始终有几个问题解决不好,还请论坛里的高手,分享下自己的经验,谢谢~

主要的问题:

  • 多个 entity 放在同一个文件里,会出现 NameError
  • 代码中出现 bug, 服务器 ( thin ) 假死,只能 kill + 重启。
  • 不同版本的 API 如何共享 entity
  • 使用 Grape::Entity::DSL 直接在 model 中定义 entity. 这样做,好不好

#1 楼 @iBachue

频繁报 NameError (uninitialized constant V1::App::Entity::User) 这样的错误。

entity.rb 里面定义了

module V1
  module App
    module Entity

      # 用户
      class User < Grape::Entity
        expose :id, :nick, :avatar
      end

    end
end

#2 楼 @42thcoder 你能把发生错误的代码贴出嘛?

#3 楼 @iBachue 谢谢回复~

endpoint 定义在 users.rb 文件中,大致的逻辑是这样的:

require_relative "entity"

module V1
  module App
    class Works < Grape::API
      user = User.first

      present user, with: Entity::User
    end
  end
end

entity.rb 文件中定义了许多 entity, 大概像这样:

module V1
  module App
    module Entity
      # 商家
      class MerchantSummary < Grape::Entity
        expose :id, :name, :address, :logo_path
      end

      class Merchant < MerchantSummary
        expose :rating
      end


      # 用户
      class UserSummary < Grape::Entity
        expose :id, :nick, :avatar
      end

      class User < UserSummary
        expose :created_at
      end

    end
  end
end

#4 楼 @42thcoder 抱歉 凭肉眼没能看出错误的根源,能够贴下 backtrace 就是堆栈信息?

#5 楼 @iBachue

NameError (uninitialized constant V1::App::Entity::User):
  /Users/hacker/work/app/api/v1/app/works.rb:32:in `block (2 levels) in <class:Works>'
  /Users/hacker/.rvm/gems/[email protected]/gems/grape-0.9.0/lib/grape/endpoint.rb:45:in `call'
  /Users/hacke/.rvm/gems/[email protected]/gems/grape-0.9.0/lib/grape/endpoint.rb:45:in `block in generate_api_method'
  # 剩下的删掉了, 基本上没啥用

#6 楼 @42thcoder 你的出错点在 /Users/hackerZhang/work/app/api/v1/app/works.rb 第 32 行嘛 你把那个文件贴上来 应该就可以发现问题了。。

#7 楼 @iBachue

32 行就是下面代码中的 present user, with: Entity::User

require_relative "entity"

module V1
  module App
    class Works < Grape::API
      user = User.first

      present user, with: Entity::User
    end
  end
end

#8 楼 @42thcoder 在这种情况下,你尝试下替换成 ::V1::App::Entity::User 是不是就对了,如果对的话,就逐一削减搜索条件直到错误为止。 蛮奇怪的,我本地试类似代码都没有问题。

#9 楼 @iBachue 也是不行的,我在 rails console 中做过各种实验,打印 V1::App::Entity.constants V1::App::Entity::User 之类的,有时可以找到,有时候找不到,十分神奇。

百思不得其解,整个人都不好了

我现在把代码写到models/user.rb中,就可以了,类似这样:

class User < ActiveRecord::Base
  include Grape::Entity::DSL

  entity :id, :nick, :avatar do
    root 'authors', 'author'
  end
end

#10 楼 @42thcoder 其实写 Ruby 你不用思考这么多 不用瞎猜 也不用整个人都不好 直接 Debug 就可以。

require_relative "entity"

module V1
  module App
    class Works < Grape::API
      user = User.first
require 'pry'; binding.pry unless defined?(::V1::App::Entity::User)
      present user, with: Entity::User
    end
  end
end

pry-byebug,只要代码在断点处停下 就可以通过研究那一刻的 $LOADED_FEATURES,来看那个文件是否已经加载。如果没加载,研究为什么之前的require_relative没有出错,它到底加载了那个文件,这样就可以了。

@iBachue pry 真是神器,谢谢~

文件已经加载了,但没找到类。

[25] pry(V1::App::Entity):3> $LOADED_FEATURES.select{|file| file.include? 'entity' }
=> ["/Users/hacker/.rvm/gems/[email protected]/gems/pry-0.10.1/lib/pry/commands/ls/ls_entity.rb",
 "/Users/hacker/work/app/api/v1/app/entity.rb"]
[26] pry(V1::App::Entity):3> ls
constants:  Product
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_

/Users/hacker/work/app/api/v1/app/entity.rb 这个文件是对的. 找到那个类Product, 是在 API 文件products.rb中直接定义的。

13 Floor has deleted

#12 楼 @42thcoder 那就更加神奇了 一个文件被加载过 定义的类却不见了 你可以尝试再次加载 看看有没有出现,如果出现就表示之前哪里把定义的类删掉了。如果没有出现,你检查是不是代码里有错别字神马的。。。

You need to Sign in before reply, if you don't have an account, please Sign up first.