统计数据分组
创建路由
打开routes.rb
修改内容,修改后可以在终端执行bin/rails routes
命令,进行查看。使用了collection,可以在items后面添加参数来组成路由。
ruby
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
# root "articles#index"
get '/' ,to: 'home#index'
namespace :api do
namespace :v1 do
resources :validation_codes, only: [:create]
resource :session, only: [:create, :destory]
resource :me, only: [:show]
resources :items do
collection do
get :summary
end
end
resources :tags
end
end
end
按时间分组
get /api/v1/items/summary
- 写测试用例
ruby
require 'rails_helper'
RSpec.describe "Items", type: :request do
describe "统计数据" do
it '按天分组' do
user = User.create! email: '1@qq.com'
tag = Tag.create name: 'tag', sign: 'x', user_id:
Item.create! amount: 100, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 100, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-20T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-20T00:00:00+08:00', user_id: user.id
Item.create! amount: 100, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-19T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-19T00:00:00+08:00', user_id: user.id
get '/api/v1/items/summary', params: {
happened_after: '2018-01-01',
happened_before: '2019-01-01',
kind: 'expenses',
group_by: 'happen_at'
}, headers: user.generate_auth_header
expect(response).to have_http_status 200
json = JSON.parse response.body
expect(json['groups'].size).to eq 3
expect(json['groups'][0]['happen_at']).to eq '2018-06-18'
expect(json['groups'][0]['amount']).to eq 300
expect(json['groups'][1]['happen_at']).to eq '2018-06-19'
expect(json['groups'][1]['amount']).to eq 300
expect(json['groups'][2]['happen_at']).to eq '2018-06-20'
expect(json['groups'][2]['amount']).to eq 300
expect(json['total']).to eq 900
end
end
end
- 写代码
创建了一个hash表,用于处理数据。获取到时间后由于有时区的问题,要指定时区,于是使用in_time_zone(..)
然后在进行格式化。但是指定时区还是有问题的,若是用户去了其他时区就会发现bug。其中%y-%m-%d
来表示时间,也可以用ruby的简单写法%F
。
<=>
可以理解为比较,sort
的返回值也是三个,和JavaScript的类似,具体详细内容可以查看链接。
处理好hash表后在进行map
和sort
处理得到根据happen_at
的字段排好序的groups。
ruby
class Api::V1::ItemsController < ApplicationController
def summary
hash = Hash.new
items = Items
.where(user_id: request.env['current_user_id'])
.where(kind: params[:kind])
.where(happen_at: params[:happen_after]..params[:happen_before])
items.each do |item|
#获取到时间后由于有时区的问题,要指定时区,然后格式化。
key = item.happen_at.in_time_zone('Beijing').strftime('%F')
# hash[key] = hash[key] || 0 ruby简写如下
hash[key] ||= 0
hash[key] += item.amount
end
groups = hash
.map { |key, value| { "happen_at": key, amount: value } }
.sort { |a, b| a[:happen_at] <=> b[:happen_at] }
render json: {
groups: groups,
total: items.sum(:amount)
}
end
end
按tag_id分组
接口还是同一个。
- 写测试用例
ruby
require 'rails_helper'
RSpec.describe "Items", type: :request do
describe "统计数据" do
it '按标签ID分组' do
user = User.create! email: '1@qq.com'
tag1 = Tag.create! name: 'tag1', sign: 'x', user_id: user.id
tag2 = Tag.create! name: 'tag2', sign: 'x', user_id: user.id
tag3 = Tag.create! name: 'tag3', sign: 'x', user_id: user.id
Item.create! amount: 100, kind: 'expenses', tags_id: [tag1.id, tag2.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag2.id, tag3.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 300, kind: 'expenses', tags_id: [tag3.id, tag1.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
get '/api/v1/items/summary', params: {
happened_after: '2018-01-01',
happened_before: '2019-01-01',
kind: 'expenses',
group_by: 'tag_id'
}, headers: user.generate_auth_header
expect(response).to have_http_status 200
json = JSON.parse response.body
expect(json['groups'].size).to eq 3
expect(json['groups'][0]['tag_id']).to eq tag3.id
expect(json['groups'][0]['amount']).to eq 500
expect(json['groups'][1]['tag_id']).to eq tag1.id
expect(json['groups'][1]['amount']).to eq 400
expect(json['groups'][2]['tag_id']).to eq tag2.id
expect(json['groups'][2]['amount']).to eq 300
expect(json['total']).to eq 600
end
end
end
- 写代码
ruby
class Api::V1::ItemsController < ApplicationController
def summary
hash = Hash.new
items = Item
.where(user_id: request.env['current_user_id'])
.where(kind: params[:kind])
.where(happen_at: params[:happened_after]..params[:happened_before])
items.each do |item|
if params[:group_by] == 'happen_at'
key = item.happen_at.in_time_zone('Beijing').strftime('%F')
hash[key] ||= 0
hash[key] += item.amount
else
item.tags_id.each do |tag_id|
key = tag_id
hash[key] ||= 0
hash[key] += item.amount
end
end
end
groups = hash
.map { |key, value| {"#{params[:group_by]}": key, amount: value} }
if params[:group_by] == 'happen_at'
groups.sort! { |a, b| a[:happen_at] <=> b[:happen_at] }
elsif params[:group_by] == 'tag_id'
groups.sort! { |a, b| b[:amount] <=> a[:amount] }
end
render json: {
groups: groups,
total: items.sum(:amount)
}
end
end
更新API文档
ruby
require 'rails_helper'
require 'rspec_api_documentation/dsl'
resource "账目" do
let(:current_user) { User.create email: '1@qq.com' }
let(:auth) { "Bearer #{current_user.generate_jwt}" }
get "/api/v1/items/summary" do
authentication :basic, :auth
parameter :happened_after, '时间起点', required: true
parameter :happened_before, '时间终点', required: true
parameter :kind, '账目类型', enum: ['expenses', 'income'], required: true
parameter :group_by, '分组依据', enum: ['happen_at', 'tag_id'], required: true
response_field :groups, '分组信息'
response_field :total, "总金额(单位:分)"
let(:happened_after) { '2018-01-01' }
let(:happened_before) { '2019-01-01' }
let(:kind) { 'expenses' }
example "统计信息(按happen_at分组)" do
user = current_user
tag = Tag.create! name: 'tag1', sign: 'x', user_id: user.id
Item.create! amount: 100, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 100, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-20T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-20T00:00:00+08:00', user_id: user.id
Item.create! amount: 100, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-19T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag.id], happen_at: '2018-06-19T00:00:00+08:00', user_id: user.id
do_request group_by: 'happen_at'
expect(status).to eq 200
json = JSON.parse response_body
expect(json['groups'].size).to eq 3
expect(json['groups'][0]['happen_at']).to eq '2018-06-18'
expect(json['groups'][0]['amount']).to eq 300
expect(json['groups'][1]['happen_at']).to eq '2018-06-19'
expect(json['groups'][1]['amount']).to eq 300
expect(json['groups'][2]['happen_at']).to eq '2018-06-20'
expect(json['groups'][2]['amount']).to eq 300
expect(json['total']).to eq 900
end
example "统计信息(按tag_id分组)" do
user = current_user
tag1 = Tag.create! name: 'tag1', sign: 'x', user_id: user.id
tag2 = Tag.create! name: 'tag2', sign: 'x', user_id: user.id
tag3 = Tag.create! name: 'tag3', sign: 'x', user_id: user.id
Item.create! amount: 100, kind: 'expenses', tags_id: [tag1.id, tag2.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 200, kind: 'expenses', tags_id: [tag2.id, tag3.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
Item.create! amount: 300, kind: 'expenses', tags_id: [tag3.id, tag1.id], happen_at: '2018-06-18T00:00:00+08:00', user_id: user.id
do_request group_by: 'tag_id'
expect(status).to eq 200
json = JSON.parse response_body
expect(json['groups'].size).to eq 3
expect(json['groups'][0]['tag_id']).to eq tag3.id
expect(json['groups'][0]['amount']).to eq 500
expect(json['groups'][1]['tag_id']).to eq tag1.id
expect(json['groups'][1]['amount']).to eq 400
expect(json['groups'][2]['tag_id']).to eq tag2.id
expect(json['groups'][2]['amount']).to eq 300
expect(json['total']).to eq 600
end
end
end
然后重新执行bin/rails rake docs:generate
,然后执行http-server doc/api
进行查看。