# Rails ###### tags: `Rails` ### ==專案記錄== - ++test\test_01++ 已上 github 測試 - ++test\cart_415a++ 使用 postgresql 的購物車程式,已用 git 版控 - ++test\cart_416c++ 使用 postgresql 的購物車程式,可加減數量,已用 git 版控 - ++ruby\task\book_v2++ 測試 tailwindcss 和 daisyUI - ++ruby\vote_me++ 線上課程範例 --- 4/21 優先把購物車的介面刻出來 用cartproduct(parent去撈saleinfo的id與資料)用find_by找 後續要接user_id --- 1. 建立新的 Rails 專案: rails new 專案名稱 --database=postgresql cd 專案名稱 2. 建立資料庫: rails db:create --- ### 3/21 - `gem install rails -v 6.1.7.3` `rails -v` `rails new jobbank` `rails _6.1.7.3_ new jobbank` - `ubuntu 20.04` `wsl --list --verbose` `wsl --set-version Ubuntu-20.04 1` `Ruby 3.2.2` `Rails 6.1.7.3` `Node 16` `npm install -g yarn` - 加 readme 資料 語意化版本 - `gem install XXXX` <= Gemfile/Gemfile.lock `gem uninstall XXXX` - 全部安裝 `bundle install` 自動下載某個套件 `bundle add XXXX` `yarn add / npm install` - Ctrl+p 可以搜尋 - 連結資料庫(migrate),這個指令不會重作 `rails db:migrate` 若想清除需要使用以下指令 (倒退一步) `rails db:rollback` --- ### Rails的規則,table會小寫+複數s | Model | Table | | -------- | -------- | | Book | books | | Student | students | | Rusume | resumes | - 慣例優於設定(COC),不要重複code(DRY) - 後續想要加新欄位,正確的做法應該開一個新的migrate `rails g migration 修改說明文字` (g=generate) `rails d migration 修改說明文字` (刪除) - `rails -T` 可看Rails有哪些指令 - 在vscode內的 view > source control 可顯示GIT符號 - 看誰用了3000 port 並砍掉 `lsof -n -i:3000 | grep LISTEN` `kill 754` ### 在rails內新增model - `$ rails g model Resume name:string email:string tel:string skill:string intro:text city:string education:text experience:text portfolio:text` 上面為完整指令,若資料為 string 型別可以省略,以下為省略後指令 - `$ rails g model Resume name email tel skill intro:text city education:text experience:text portfolio:text` --- ### 換 node 16 執行流程 1. 換用 node 16 2. 刪除 node_modules 目錄 3. 執行 yarn install -> 產生新的 node_module 4. 重開 rails s ### 在 nvm 中安裝 node 16 - `nvm install 16.19.0` 使用 node v16 `nvm use 16` 查詢 node 版本 `nvm ls` 設定預設 node 版本 `nvm alias default 16.19.0` ### 3/21 rails 進度 * `$ rails new ____` `$ rails g model ____` `$ rails g migration ____` `$ rails db:migrate` `$ rails db:rollback` `edit routes.rb` `$ rails g controller ____` `edit controller ____` `add app/____/views/___.html.erb` ### 檔案位置 * `migrate:db > migrate` `routes.rb:config > routes.rb` `xxxx_controller.rb:app > controllers > xxxx_controller.rb` `zzzz.html.erb:app > views > xxxx資料夾 > zzzz.html.erb` ### Rails Route * 設定首頁路徑 `root "welcome#index"` 把"/users"轉址到"/accounts" `get '/users', to: redirect('/accounts')` - 在Route進行比對的時候,在前面先查到的就會先生效 - 在route內使用resources可一次製作8個路徑,如下 ```ruby= Rails.application.routes.draw do resources :users end ``` | Prefix | Verb | URI Pattern | Controller#Action | | --------- | ------ | ------------------------ | ----------------- | | users | GET | /users(.:format) | user#index | | | POST | /users(.:format) | user#create | | new_user | GET | /users/new(.:format) | user#new | | edit_user | GET | /users/:id/edit(.:format)| user#edit | | user | GET | /users/:id(.:format) | user#show | | | PATCH | /users/:id(.:format) | user#update | | | PUT | /users/:id(.:format) | user#update | | | DELETE | /users/:id(.:format) | user#desroy | * 若不需要8個路由,可使用以下指令修改 ```ruby= Rails.application.routes.draw do resources :products, only: [:index, :show] ``` * 或是反過來這樣寫也行 ```ruby= resources :products, except: [:new, :create, :edit, :update, :destroy] end ``` ### rails c (控制台模式) * exit / ctrl + d (離開) Post.first (顯示第一篇文章的資訊) Post.all (顯示全部文章的資訊) p1 = Post.first (取得第一篇文章) p1.user (找出該篇文章的作者) u1 = User.first (取得第一個會員) u1 (列出第一個會員的資料) u1.name (列出第一個會員的name) u1.email (列出第一個會員的email) ### 下拉式選單 * 在veiw的html.erb內,可做下拉式選單列出所有user ```rbuy= form.label :user_id form.collection_select(:user_id, User.all, :id, :name) ``` ### 解決 N + 1 問題 (重複撈資料造能效能浪費問題) * 在controllers的posts_controller.rb內,可在撈文章時順便撈使用者名稱,改寫如下 (上→下) `@posts = Post.all` `@posts = Post.all.includes(:user)` ### 驗證器 * 希望名字 / email不能填空白 在 controllers 的 user_controller.rb 內加上 `validates :name, presence: true, length: { in: 6..20 }` 名字長度在 6~20 字之間 `validates :email, presence: true` (驗證欄位必須要填資料,若空白則跳錯 "name / email can’t be blank") --- ### 3/23 - Route - xxxx_path vs xxxx_url - xxxx_path 優缺點 - link_to - Form - <form action method> - GET vs POST - HTTP 狀態 - <%= form_for %> - 保護機制 - AuthenticityToken - skip 驗證(小心用) - 給 token - 用 form_for - ForbiddenAttributeError - 用 permit ### 局部渲染 * `<%= render 'shared/navbar' %>` `shared > _navbar.html.erb` (額外新增的模組檔名前要加底線) 用的時候不用加底線 - 文字判斷可用regex(101) - 一般的搜尋網頁功能都用get做,例如google搜尋引擎 post 傳送資料不會顯示在網址列上 - http狀態 204 not connect 404 not found - 串接金流時可能會skip authenticity_token(驗證),其他情況不建議skip - 打debugger可下中斷點 可打參數測試 `params` `params[‘resume’]` --- ### 3/27 - `rails c --sandbox ` 控制台(沙盒模式) 離開會清除設定 `r1 = Resume.new` `r1.save` =>false `r1.errors.any?` =>true `r1.errors.full_messages` =>列出所有錯誤 * 用間接給參數 達到模組化 重複利用 局部渲染 erb 內不要放實體變數 (@xxxx),可以用餵的方式給他,以下使用廣告為例 ```ruby= <%= render ‘shared/ads/square’, content: @ad1 %> <%= render ‘shared/ads/banner_large’, content: @ad2 %> <%= render ‘shared/ads/banner_small’, content: @ad3 %> ``` ### clone github上的專案 - 在終端機下指令 `git clone https://XXXXXX.git` 專案連結在github綠色按鈕內的http下複製 - 在 github 下載完專案後 `bundle install` `yarn install` `rails db:migrate` `rails s` --- ### 3/28 - rails 錯誤訊息頁面下方可以打字 例如 "params" - 有動態id的router系統不會給名字 要自己取 有相同路徑時不用再給一次 as - Query String `/resume/123?a=1&b=2` - "?"前面的是路徑,後面是id資料 - `.where` 會撈出多筆資料,並放進一個陣列 `.find()` 只能找出一筆資料 `.find_by(number)` 只能找出一筆資料 - `rescue_from`是rails提供的功能 可處理錯誤訊息 - `Turbolinks`是加速連結的rails功能,可能造成某些 javascript損壞 - 要有表單才能做POST - 局部渲染其他檔案時,檔名前需要加底線 `<%=render 'resumes/data' %>` 若是要渲染有相關的檔案,可以不用寫資料夾名稱 - 作業 (已完成) 用 Rails new 一個專案 book 的 CRUD,書名(name)、作者(author)、簡介(introduction) 25分鐘完成 --- ### 3/30 - resources 和 resouce 產出的路徑差別為,前者有id,後者沒有 collection 和 menber 可建立路徑,前有無id後者有id - annotate 套件,可在model備註資料 - ruby 使用 digest 函式庫需要 `require 'digest'` - `self.password` 的 self 指的是自己本身,而非類別變數,self.password 指的是一個欄位,把左邊前面的 self 拿掉會變成區域變數,就不會生效了 - devise 套件 可快速做 會員登入/查詢密碼 功能 - hash 取值時要填 `keyword:` - paranoia 套件 可快速設定軟刪除 --- ### 3/31 - 增加 migrate 檔案需要使用指令 - Authentication 認證、憑證 Authorization 授權 - pundit 套件 可處理憑證/授權問題 - foreman 套件 可一次開啟多個server `bundle add foreman` 安裝 foreman `foreman s` 使用指令開啟 server - 建立一個`Procfile.dev`檔案,內容如下 `web: rails server -p 3000` `webpack: bin/webpack-dev-server` `css: bin/rails tailwindcss:watch` (tailwindcss使用) - 建立一個`.foreman`檔案,內容如下 `procfile: Procfile.dev` --- ### 4/6 - rake `rake task` 可幫忙自動生產履歷 `rake -T` 可查看 rake 指令 - tailwind 回去測試 `tailwind` 的使用方式,可查看官網和上課影片安裝,可取代傳統 css - 看 form_for 和 form_with 的用法與差異 - `rails routes -c xxxxx` 查詢跟 xxxxx 相關的路徑 - 在新增路徑時,加上 `shallow` 可以自動做出縮短路徑的巢狀結構 - comment 同時與 resume 和 user 產生關聯,給資料時兩個同時都要給 - js.erb 在 rails 中寫 js 時,render 時在 "" 中加 `j` 可跳脫 單引號和雙引號 - 設定變數時要使用`var`,不然重複宣告變數會出現錯誤 - `stimulus` 方便使用 js 的套件 - 用 `bin/dev` 開 server --- ### 4/7 - foreman 套件 可一次開啟多個server `css: bin/rails tailwindcss:watch` - action table 互動式聊天室窗套件 - hotwire 可對 html 的取用進行優化 - turbo-frame 可立即在目前的視窗顯示其他視窗的內容 trubo-stream 刪除可用,也是立即更新 - delete-at 刪除使用套件 (軟刪除) - thubmb 套件 可快速使用各種向量圖 要先裝 fortawesome - axios 套件 用來代替 fetch - rubocop-rails 套件 整理程式碼 `rubocop -A` 自動修正程式 --- ### 4/10 - friendly_id 套件 優化網址路徑 `rails g magration add_liug_to_users slug:uniq` - Rails Internationalization (I18n) 多國語系 - sortableJS 套件 各種拖曳物件效果 - acts_as_list 套件 拖拉排序用套件 - rails_request.js 套件 - ngrok 套件 可產生一個臨時的網址,用來測試金流或其他功能 --- ### 4/11 - braintree 串 paypal 金流 測試卡號:4111-1111-1111-1111 - dotenv 可存放變數(token) - aasm 狀態機套件 - kaminari 分頁套件 --- ### 4/17 - carrierwave 套件 上傳圖片 - active storage - Amazon S3 放照片的地方 - marked 套件 --- ### Docker - image (only read) - `container = image.new` - `docker run hello-world` - `which docker` - `docker image ls` 查看電腦裡有哪些image - `docker container ls` 查看電腦裡有那些正在執行的 - `docker container ls -a` - `docker run nginx` - `docker run -p 777:80 nginx` 將localhost port 777 對到 外部的port 80 - 連到 `http://localhost:777/` 會有 nginx 的預設頁面 `docker run -v ${PWD}:/user/share/nginx/html -p 777:80 nginx` - `docker run -it nginx /bin/sh` 可打字互動 不要執行預設行為 - `docker build -t` --- ### 4/18 - rails 7 import maps hotwire - rails g stimulus - polymorphic 多型關聯 - STI single type ixxxx 單一表格繼承關聯 - 在 model 中不要亂用 type 當欄位 --- ### 4/20 - 使用hotwire時,turbo預設會打開,若無法開啟網頁可關閉 `data: { turbo: false }` - 到 `config/initializers/inflecions.rb` 檔案內 解開第6行 `ActiveSupport::Inflrctor.inflections(:en) do |inflect|` 解開第11行 `end` 改第9行的 `inflect.irregular 'aaa', 'bbb'` 設定 rails 專案內的 aaa 複數為 bbb --- ### vote_me 線上課程 * 建立候選人的 magration `rails g model Candidate name party age:integer politics:text votes:integer` * 建立選票的 magration `rails g model VoteLog candidate_id:integer ip_address` 改寫為下面方法,效果與上面相同 `rails g model VoteLog candidate:references ip_address` * `candidate:references` 此寫法會產生一個 candidate 的 id 欄位,會參照指向候選人的 id (references為複數) * `rails c` 開控制台 `VoteLog.all` 查詢所有投票記錄 `VoteLog.count` 查詢投票數量 `c1 = Candidate.first` `c1.vote_logs` 第一個候選人的投票記錄 `c1.vote_logs.count` 第一個候選人的票數 * Counter Cache 可在數據庫做一個簡單的計數器,減少資料庫的存取 - 在資料表中增加一個欄位 `rails g migration add_counter_cache_to_candidate` - 在 migration 表內增加欄位資料如下 ```ruby= class AddCounterCacheToCandidate < ActiveRecord::Migration[6.1] def change add_column :candidates, :vote_logs_count, :integer, default: 0 end end ``` - 執行 `rails db:migrate` 在 `model/vote_log.rb` 內增加資料 `counter_cache: true` 會在寫入票數的同時,去 `vote_logs_count` 欄位更新票數 - 在 `veiw/cansidates/index.html.erb` 內增加 `<td><%= candidate.vote_logs_count %></td>`