惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - Franky
WordPress大学
WordPress大学
Jina AI
Jina AI
Google DeepMind News
Google DeepMind News
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Fortinet All Blogs
博客园 - 【当耐特】
IT之家
IT之家
G
Google Developers Blog
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
云风的 BLOG
云风的 BLOG
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
V
Visual Studio Blog
U
Unit 42
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
GbyAI
GbyAI
雷峰网
雷峰网

Nic Lin's Blog

謝明真 - 高效領導力的課後筆記 NFT 開發實戰!基礎智能合約入門 (3) NFT 開發實戰!基礎智能合約入門 (2) NFT 開發實戰!基礎智能合約入門 (1) 如何自我檢測 log4j CVE 漏洞 Rails 如何在資料寫入時記錄來源 IP 位置 如何經營工程師 Youtube 頻道 - Part 8 營收篇 如何經營工程師 Youtube 頻道 - Part 7 酸民文化篇 如何經營工程師 Youtube 頻道 - Part 5 設備器材篇 如何經營工程師 Youtube 頻道 - Part 4 後製剪輯篇 如何經營工程師 Youtube 頻道 - Part 3 文案企劃篇 如何經營工程師 Youtube 頻道 - Part 2 設備器材篇 如何經營工程師 Youtube 頻道 - Part 1 制訂頻道方向篇 如何經營工程師 Youtube 頻道 - Part 0 Rails 中避免 race condition 的最佳實踐(二) Rails 中避免 race condition 的最佳實踐(一) 10 分鐘整合 google sheet 做自動化開發功能週報 經營 Side Project 300 天所帶來的收穫及挑戰 我的 Youtube 影片製作流程 API 設計時必須注意的 HTTP header 底線問題 如何提升你的程式可讀性之實務技巧(三) 如何提升你的程式可讀性之實務技巧(二) 如何提升你的程式可讀性之實務技巧(一) Ruby 中使用 freeze 優化效能的時機 避免 React 中的 useEffect 無限 render 在 Rails 內輕量使用 Vue Component 的最佳實踐 如何在區域網路用 Docker 架設有 SSL 的 Gitlab 從被問到問人,那些我常問的面試問題 [Rails] 如何漂亮寫出可維護的 query (Maintainable Rails Query) 在已知長度情況下優化 slice 的性能
不要再佔用 controller action 與 route 來更新資料了
Nic Lin · 2017-07-27 · via Nic Lin's Blog

常見更新數據狀態的作法

一般來說,除了狀態機(AASM)變更狀態以外,有一種情況是針對這筆資料進行狀態變更,通常的設計是這樣子的,有一個按鈕,按下去之後觸發功能。

  1. 按鈕按下去,找到 route
  2. route 進到該對應的 controller action
  3. action 內觸發 ActiveRecord 裡的 method 進行數據 update

比方說 user 可以創建很多 group,但我想要讓 group 在畫面顯示的時候可以由後台進行控制,公開或是隱藏

所以這時候就會出現


def publish
  @group.publish!
end

def hide
  @group.hide!
end
resources :groups do
  member do
    post :publish
    post :hide
  end
end

那麼如果我要控制這筆 group 的 position 呢?比方說往上一筆,往下一筆 你有可能會使用到acts_as_list這隻 gem 來完成。

那麼我的 controller 裡面豈不是又要加入這兩個 action 變成


def publish
  @group.publish!
end

def hide
  @group.hide!
end

def move_up
  @group.move_higher # acts_as_list 裡面的 helper method
end

def move_down
  @group.move_lower # acts_as_list 裡面的 helper method
end

然而 routes 也得變成這樣…

resources :groups do
  member do
    post :publish
    post :hide
    post :move_up
    post :move_down
  end
end

如果我在來個將 position 置頂、置底呢

move_top, move_bottom ?

沒完沒了的佔用了很多 controller 中的 action 還有其 routes

其實在上述的例子,一般新手或是以前的我都會這樣寫,那麼這個東西既不好維護,又容易讓程式碼越來越長,卻只為了更新某一筆資料的狀態或是位置?

有沒有更好的作法?

我認為這些單純更新數據的行為,在 HTTP 動詞裡面應該用 patch 而不是 post,這個 Rails guide 裡面有提到。

所以我的想法是,把所有這樣的行為,透過傳遞 params 的方式來做選擇,而這個最適合做選擇的地方,就是 CRUD 裡面的 update ,我認為既符合原意,又不浪費 action 與 routes。

首先將你的觸發連結,全部導向 update action

利用 link_to,在 path 中夾帶 value,並且打 patch 出去


<%= link_to "公開", group_path(@group, status: "public"), method: :patch %>

<%= link_to "隱藏", group_path(@group, status: "hide"), method: :patch %>

在將 controller 裡的 update 改寫一下


def update
status = params[:status].nil? ? "update" : params[:status]

  success =
   case status
   when "update"
     @group.update(group_params)
   when "publish"
     @group.publish!
   when "hide"
     @group.hide!
   else
     false
   end
 
  if success
    flash[:notice] = "#{@group}更新成功。"
    redirect_to groups_path
  else
    render :edit
  end
end

如此一來,你只要遵循這樣的設計模式,就可以減少 controller action 與 routes 的濫用

  1. 於連結中傳入 status 參數(publish/hide/move_up/move_down/…),並使用 HTTP 中 patch 動詞
  2. 於 controller 中的 update action 裡面設定 status 只接受何種狀態(如上述程式碼中的 case when )

如此一來,就不會因為變更狀態而寫了一堆 routes 與 controller action 了

你只需要維護 update 中的部分,畢竟變更狀態,就是 update 一筆資料中的相關欄位嘛

喔對,你的 routes 裡就只要一行

resources :groups

就是這麼的乾淨!