# 20220728 Rails 無名小站實作 (Rich) 文章CRUD
###### tags: `Ruby` `Rails`
## View Helper
```ruby
<%= link_to "新增文章", "/blog/new" %> 不建議使用字串型式
<%= link_to "新增文章", blog_new_path %> 建議使用,一打錯就知道
```
## REST
* resources自動生成8條路徑,對應7個action
* get,post,patch...都是ruby的function
* 路徑比對由上而下,使用:id比對需要注意,id可以自己改任何字,都可以拿來比對英文字母跟數字,可以一直往後擴增
* 常被存取的可以擺在最前面
* $rails routes -c 名稱 篩選指定名稱相關的路徑
```ruby
# get "/blog", to: "blog#index"
# get "/blog/new", to: "blog#new"
# post "/blog", to: "blog#create"
# get "/blog/:id", to: "blog#show"
# get "/blog/:id/edit", to: "blog#edit"
# patch "/blog/:id", to: "blog#update"
# delete "/blog/:id", to: "blog#destory"
#REST 直接用resources生出對應路徑,建議用複數,但前面檔名跟內容都要改
resources :blogs
```
```ruby
resources :blog, only:[:index, :show], path:"路徑"
resources :blog, except: [:index,:new], path:"路徑"
# 可用only 和 except控制那些要開啟
```
`form_tag` 自動可以生成帶有token的連結
```ruby
<%= form_tag "/blogs" do %>
<input type="submit" value="新增">
<% end %>
```
### form 傳遞資料
1. 按下 `form` 中的 `submit` 時,會傳送表單中有 `name` 屬性的值
2. 而在 `Controller` 中可以用 parmas 拿到傳送過來的值(hash的形式)
3. 處理之後在渲染(`render`)至 `View` 或轉址去其他地方
### erb render params
```ruby
render html: params[:content]
render html: params["content"]
# params是類hash的東西,符號拿法是ruby特有,其他程式語言習慣用""拿
# symbol 是有名字的物件,如同數字
```
### 產生model
$ rails g model Article title:string content:text
= $ rails g model Article title content:text
生成相關檔案
/app/models/articles.rb
/db/migrate/...rb
產生對應類別
Class ArticlePost
file article_post
table article_posts
### db:migrate
產生描述(要準備對資料庫操作的事)
$ rails generate migration {name}
具象化
$ rails db:migrate
砍掉表格(退一步),沒事不要亂用
$ rails db:rollback
查詢哪些描述被執行了
$ rails db:migrate:status
如果你己經db:migrate,但你突然想加開欄位
$ rails g migration add_user_id_to_articles user_id:integer:index
`add...to...` 加你想要的欄位名稱到哪個資料表
`remove...from...`在哪個資料表刪除你想要的欄位
`user_id:integer:index`會同時長出user_id及
終端機當掉解決方法
$spring stop
資料庫extention: SQLite Viewer
:::info
migration 要解決的事
紀錄 資料庫(欄位) 變動
如同 git
紀錄 source code 的 變動
:::
> config / database.yml
`adapter` 決定使用何種資料庫
```yaml=
# ...
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
# ...
```
```ruby=
<%= form_for @article do %>
<% end %>
```
> https://rails.ruby.tw/form_helpers.html
### 進入 Rails 終端機
```shell=
$ rails console
$ rails c --sandbox
```
### 傳進來資料未經處理便試圖存入資料庫

```ruby=
清洗params髒東西
clean_params = params[:article].permit(:title,:content)
下面那個為「業界中常用的」
private
def article_params
params.require(:article).permit(:title, :content)
# 不常用
params[:article].pertmit(:title, :content)
end
```
### 表單傳送至後端驗證失敗,回傳上一步輸入結果
```ruby=
class ArticlesController < ApplicationController
def create
if @article.save
redirect_to "/"
else
render new_blog_path
# 借 new_blog_path 來用
end
end
# ...
end
```
https://rails.ruby.tw/form_helpers.html#%E5%85%B6%E5%AE%83%E7%9B%B8%E9%97%9C%E8%BC%94%E5%8A%A9%E6%96%B9%E6%B3%95


### 1.4 其它相關輔助方法
其它值得一提的表單控件有:textareas、password fields、hidden fields、search fields、telephone fields、date fields、time fields、color fields、datetime fields、datetime-local fields、month fields、week fields、url fields、email fields、number fields 以及 range fields:
```ruby=
<%= text_area_tag(:message, "Hi, nice site", size: "24x6") %>
<%= password_field_tag(:password) %>
<%= hidden_field_tag(:parent_id, "5") %>
<%= search_field(:user, :name) %>
<%= telephone_field(:user, :phone) %>
<%= date_field(:user, :born_on) %>
<%= datetime_field(:user, :meeting_time) %>
<%= datetime_local_field(:user, :graduation_day) %>
<%= month_field(:user, :birthday_month) %>
<%= week_field(:user, :birthday_week) %>
<%= url_field(:user, :homepage) %>
<%= email_field(:user, :address) %>
<%= color_field(:user, :favorite_color) %>
<%= time_field(:task, :started_at) %>
<%= number_field(:product, :price, in: 1.0..20.0, step: 0.5) %>
<%= range_field(:product, :discount, in: 1..100) %>
```
產生的 HTML:
```htmlmixed=
<textarea id="message" name="message" cols="24" rows="6">Hi, nice site</textarea>
<input id="password" name="password" type="password" />
<input id="parent_id" name="parent_id" type="hidden" value="5" />
<input id="user_name" name="user[name]" type="search" />
<input id="user_phone" name="user[phone]" type="tel" />
<input id="user_born_on" name="user[born_on]" type="date" />
<input id="user_meeting_time" name="user[meeting_time]" type="datetime" />
<input id="user_graduation_day" name="user[graduation_day]" type="datetime-local" />
<input id="user_birthday_month" name="user[birthday_month]" type="month" />
<input id="user_birthday_week" name="user[birthday_week]" type="week" />
<input id="user_homepage" name="user[homepage]" type="url" />
<input id="user_address" name="user[address]" type="email" />
<input id="user_favorite_color" name="user[favorite_color]" type="color" value="#000000" />
<input id="task_started_at" name="task[started_at]" type="time" />
<input id="product_price" max="20.0" min="1.0" name="product[price]" step="0.5" type="number" />
<input id="product_discount" max="100" min="1" name="product[discount]" type="range" />
```