---
# System prepended metadata

title: 20220728 Rails 無名小站實作 (Rich) 文章CRUD
tags: [Rails, Ruby]

---

# 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
```


### 傳進來資料未經處理便試圖存入資料庫
![](https://i.imgur.com/wB7vQij.png)

```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

![](https://i.imgur.com/HV6NYGt.png)

![](https://i.imgur.com/upoYpbI.png)

### 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" />
```