在 git 上找了很久没有找到一个 grape 的片段缓存方案,所以才有想法自己写一个。刚刚起步开始写,很多想法还未实现。但是已经可以配合 rails 使用了。 https://github.com/u2/grape-present_cache 使用方法:
module MyApi < Grape::API
format :json
include Grape::Present::Cache
resources :posts do
desc "Return a post"
get ":id" do
post = Post.find(params[:id])
car_brands = CarBrand.where(popular: true).all
present_cache(key: "api:posts:#{post.id}", expires_in: 2.hours) do
present :post, post, with: API::Entities::Post
end
present_cache(key: "v1:api:app:cars:b", expires_in: 2.hours) do
present car_brands, with: Entities::Car::CarBrand
end
present ApiMeta.new, with: Entities::Meta::Base
end
end
end
顺便分享一下平时 grape 缓存的一个小技巧: 技巧一:
class Product < Grape::Entity
root 'products', 'product'
expose :id, :photo_path, :price, :width, :height
expose :favorites_count, as: :like_count
expose :like do |product, options|
if options[:favorites]
options[:favorites].map(&:product_id).include?(product.id)
else
false
end
end
end
class Products < Grape::API
resource :products do
desc "首页商品列表"
params do
optional :per_page, type: Integer, default: 20
optional :sort, type: Integer, default: 0
optional :page, type: Integer, default: 1
end
get do
favorites = current_user.favorites if current_user
case params[:sort].to_i
when 0
products = Product.ranking
end
products = products.paginate(:page => params[:page], :per_page => params[:per_page])
present products, with: Entities::Common::Product, favorites: favorites
end
end
对于上面的 api,返回的 entity 里 like 字段是根据登陆用户来判断的,这样不便于将这段代码缓存。可以将 like 字段从 Product 这个 Entity 里拿出来,然后增加一个字段 like_ids,将有 like 的 id 单独返回。
present_cache(key: "v1:api:app:products:#{page}:{per_page}", expires_in: 2.hours)
present products, with: Entities::Common::Product
end
present :like_ids, favorites.map(&:product_id)