Share
Embed
Reconsider REST: 一种构建大型Rails应用的方式
Michael Chen
September 23, 2016
Transcript
53 slides
-
Rails Programming Model GET POST PATCH DELETE show create update
destroy SELECT INSERT UPDATE DELETE -
resources :topics do member do post :reply post :favorite delete
:unfavorite post :follow delete :unfollow end resources :replies end -
某知名Ruby论坛 resources :topics do member do post :reply post :favorite
delete :unfavorite post :follow delete :unfollow post :action end collection do get :no_reply get :popular get :excellent get :favorites get :feed, defaults: { format: 'xml' } post :preview end resources :replies end -
某知名Ruby论坛 class TopicsController < ApplicationController before_action :authenticate_user!, only: [:new, :edit,
:create, :update, :destroy, :favorite, :unfavorite, :follow, :unfollow, :action, :favorites] load_and_authorize_resource only: [:new, :edit, :create, :update, :destroy, :favorite, :unfavorite, :follow, :unfollow, :action] before_action :set_topic, only: [:ban, :edit, :update, :destroy, :follow, :unfollow, :action] def index @suggest_topics = [] if params[:page].to_i <= 1 @suggest_topics = Topic.without_hide_nodes.suggest.fields_for_list.limit(3) end @topics = Topic.last_actived.without_suggest @topics = if current_user @topics.without_nodes(current_user.blocked_node_ids) .without_users(current_user.blocked_user_ids) else @topics.without_hide_nodes end -
class Inboxes def index end def pendings end end class
InboxesController < ApplicationControlle def index end end class Inboxes::PendingsController < Applicatio def index end end -
某知名Ruby论坛 resources :topics do member do post :reply post :favorite
delete :unfavorite post :follow delete :unfollow post :action end collection do get :no_reply get :popular get :excellent get :favorites get :feed, defaults: { format: 'xml' } post :preview end resources :replies -
r resources :topics do member do post :reply post :favorite
delete :unfavorite post :follow delete :unfollow post :action end collection do get :no_reply get :popular get :excellent get :favorites get :feed, defaults: { format: 'xml' } post :preview end resources :replies end resources :favorites resources :followers -
r resources :topics do member do post :reply post :favorite
delete :unfavorite post :follow delete :unfollow post :action end collection do get :no_reply get :popular get :excellent get :favorites get :feed, defaults: { format: 'xml' } post :preview end resources :replies end resources :popular_topics resources :excellent_topics resources :favorite_topics -
某知名Ruby论坛 resources :topics do resources :replies resources :favorites, only: [:create,
:destroy] resources :followers, only: [:create, :destroy] end resources :no_reply_topics, only: :index resources :popular_topics, only: :index resources :favorite_topics, only: :index -
resources :forms do member do get :data_collection_status, :print, :reports, :field_attribut
get 'qrcode/:size', to: 'forms#qrcode', as: 'qrcode' post :clear_data, :copy end collection do get :participated, :all_names, :associable_data post :preview end resource :theme, controller: 'themes', only: [:update] resources :rules, controller: 'field_rules', only: [:index] do collection do patch :save_field_rules, :save_redirect_rules end end patch :toggle, to: 'form_settings#toggle' resource :setting, controller: 'form_settings', only: [:show, :u -
重构约束 • routes中没有动词 • 最多只使⽤用7个⽅方法: new, create, edit, update, destroy,
index, show • 让 HTTP Verb + Resource 表达业务 语意 -
resources :forms, except: :index do scope module: 'form' do resources
:roles, except: :index resources :cooperators resources :recommended_cooperators, only: [:index] resource :wording, only: [:show, :update] resource :after_submission, only: [:show, :update] resources :webhooks, only: [:index, :update] resources :trackings, only: [:index, :update] resource :publish, only: :show resources :field_rules, :redirect_rules, only: [:index, :crea resource :payment_setting, only: [:show, :update] resources :payment_rules, only: :create resources :open_results, only: [:index, :update] resources :open_searches, only: :update resource :notification_setting, only: :show resource :symbol, only: [:create, :update] resource :theme, only: :update resources :reports, only: :index -
Case #1: 图⽚片/打印/RSS Feed def show respond_to do |format| format.html.none
{ render_overview } format.html.print { render_print } format.png { render_qrcode } end end 只是呈现(Representation)问题 -
Case #2: 批量量编辑 resources :entries do collection do post :bulk_delete
patch :bulk_update end end resources :batch_updates, only: [:new, :create] resources :batch_deletions, only: [:create] 将「批量量」看做资源 -
Case #3: 审批 POST /membership_requests 201 Created Location /membership_requests/123 GET
/membership_requests/123 { status: 'pending' } GET /membership_requests/123 Link: </memberships/100>; rel="membership" { status: 'approved' } 在Header中包含Link信息 -
Case #4: lock/unlock/pin/unpin 使⽤用Resource resource :lock, only: [:create, :destroy] class
LocksController < ApplicationController def create @form.lock! end def destroy @form.unlock! end end -
Case #4: lock/unlock/pin/unpin ⽣生成⼤大量量 Controller 在某些情况并⽆无意义 resources :topics do resources
:favorites resources :bans resources :excellences resources :closures end -
Case #4: lock/unlock/pin/unpin 使⽤用PATCH resources :forms resource :setting, only: [:update]
end PATCH /forms/abcdef/setting { status: 'lock' } class SettingsController < ApplicationController def update @form.settings.update_attributes form_settings_params end end -
Case #5: 移动 对「移动」单独建模,但不不必存储 resources :moves class Move include ActiveModel::Validations
attr_accessor :card_id, :from, :to validates :from, :to, presence: true end class MovesController < ApplicationController def create move = Move.new move_params if move.valid? card = Card.find(move.card_id) card.update_attribute column: move.to end -
#1: 微信公众号开放平台 # 标签管理理 POST https://api.weixin.qq.com/cgi-bin/tags/create GET https://api.weixin.qq.com/cgi-bin/tags/get POST https://api.weixin.qq.com/cgi-bin/tags/update
POST https://api.weixin.qq.com/cgi-bin/tags/delete # 获取标签下的粉丝列列表 POST https://api.weixin.qq.com/cgi-bin/user/tag/get # 为⽤用户打标签 POST https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging WTF???? -
#1: 微信公众号开放平台 resources :tags do resources :users end resources :taggings
应该的样⼦子 GET /tags POST /tags GET /tags/1234 DELETE /tags/1234 GET /tags/1234/users POST /taggings { users: [1,2,3,4], tag_id: 1234 } -
#2: 钉钉开放平台 # 部⻔门管理理 GET https://oapi.dingtalk.com/department/list GET https://oapi.dingtalk.com/department/get?id=2 POST https://oapi.dingtalk.com/department/create
POST https://oapi.dingtalk.com/department/update GET https://oapi.dingtalk.com/department/delete # WHAAAAAAT??? -
#2: 钉钉开放平台 # 部⻔门管理理 GET https://oapi.dingtalk.com/department/list GET https://oapi.dingtalk.com/department/get?id=2 POST https://oapi.dingtalk.com/department/create
POST https://oapi.dingtalk.com/department/update GET https://oapi.dingtalk.com/department/delete # WHAAAAAAT??? WTF???? -
Rails Programming Model GET POST PATCH DELETE show create update
destroy SELECT INSERT UPDATE DELETE -
Thinking about REST GET POST PATCH DELETE show create update
destroy SELECT INSERT UPDATE DELETE -
总结 思考资源的含义,⽽而不不是动作 思考资源的业务意义,⽽而不不是数据表 routes.rb 中不不出现动词 使⽤用标准HTTP Verb + Resource 组装业务逻辑
每个 Controller 不不超过7个标准⽅方法