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

推荐订阅源

L
LangChain Blog
Recent Announcements
Recent Announcements
GbyAI
GbyAI
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Microsoft Azure Blog
Microsoft Azure Blog
N
Netflix TechBlog - Medium
人人都是产品经理
人人都是产品经理
MongoDB | Blog
MongoDB | Blog
D
DataBreaches.Net
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
U
Unit 42
腾讯CDC
D
Docker
The GitHub Blog
The GitHub Blog
阮一峰的网络日志
阮一峰的网络日志
Vercel News
Vercel News
I
InfoQ
Jina AI
Jina AI
爱范儿
爱范儿
宝玉的分享
宝玉的分享
博客园 - Franky
G
Google Developers Blog
P
Proofpoint News Feed

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 的性能
不需在創建 new or edit path 的 helper, 交給 controller 決...
Nic Lin · 2017-08-06 · via Nic Lin's Blog

new or edit path helper? We can creating easy more path!

我們可能常常會需要在 view 裡面寫到 edit or new 的 link,這是我們在常見不過的一段判斷式了

<% if @project.presnet? %>
    <%= link_to 'edit', edit_project_path(@project) %>
<% else %>
    <%= link_to 'new', new_project_path %>
<% end %>

然而我們認為更棒的作法,就是把這判斷式放進 helper 裡面,只為了讓 view 看起來更簡單一些,也許可以參照這篇 StackOverFlow

例如

def render_new_or_edit_project_path(project)
    if project.present?
      link_to 'edit', edit_project_path(project)
    else
      link_to 'new', new_project_path
    end
end

然後我們在頁面只要載入這個 helper 就好了,對吧?

<%= render_new_or_edit_project_path(@project) %>

看起來一切完美,將 view 做了個 Refactor

but…轉折處就在這個 but

如果你未來繼續使用這樣的 Refactor 的方式,那麼 helper 裡面就會出現一堆

render_new_or_edit_xxxxxx_path 的這種鬼東西

或許你會認為可以把他用動態(dynamic)的方式生成,但得考慮到

  1. 如果遇到有 namespace 的 routes ?
  2. evalsend,是不是有 security issue 的問題? ,也許你會說使用 public_send,但畢竟這都是 ruby 的 meta-programming,對未來維護的時候,或許不是這麼好找尋?

那麼這個 helper 看起來又不是這麼好用了,變成只專門 for 某個頁面的方法,這樣真的是 refactor 嗎?

更好的方法

面對 new or edit 這個方法,我認為有更好的選擇

  • 使用 simple_form
  • 將 new or edit 交給 object 決定

我們可以統一把 path 交給某個 action 處理,個人偏好使用 newedit (如果你有更好的作法可以試試看自己設置的 action )

所以我們不需要花時間在判斷上面,只要連結一律導向 new_project_path

然後在 controller 裡面寫

def new
 @project = Project.find_by_id(params[:id]) || Project.new
end

如此一來,在你的 simple_form_for 裡面

<% simple_form_for @project do |f| %>
...
<% end %>

他就能在 submit 時,自動選擇「new(新建)」或是「update(更新)」行為

因為這個自動選擇,是取決於你的 Object, Simple Form 會在將 object 傳送進來時,決定你的 action 以及 method

我們在 simple form 傳進去的 object ,在這裡定義為 record

action = record.respond_to?(:persisted?) && record.persisted? ? :edit : :new

也因為在這裡就做好選擇,所以一切是這麼智能,如果你想更了解,請詳見 simple form 的 source code 是如何因 object 決定行為

補充一下,如何知道這個 object 是已經存在?或是剛 new 出來的?

Project.new.new_record? # true
Project.new.persisted? # false

# 假定數據id為1的 project 存在的情況

Project.find(1).new_record? # false
Project.find(1).persisted? # true

如此一來,就不用寫這麼多的 new_or_edit_path 的 helper 啦!