[Rails]如何使用Rails中的params

in cn •  7 years ago  (edited)

什麼是params

params是一個包含用戶所有傳進來的參數Hash(事實上params是來自於ActiveSupport::HashWithIndifferentAccess的object)。

一個params,至少一定會包含:controller和:action兩個key。我們可以直接透過params知道這個request是對應哪個controller跟action

# 對pages/index送出請求後得到的params
=> <ActionController::Parameters {"controller"=>"pages", "action"=>"index"} permitted: false>

兩種params來源

Rails透過兩種方式來透過params傳遞訊息,Query String參數或 POST參數。而在Rails並不區分,兩者都可以在controller中被取用。我們待會會針對兩種方式分別介紹。

Query String Parameters

第一種是透過url,又稱做作query string parameters。Query String 是url中?號後面的任何字串,通常是透過HTTP GET傳遞。

舉例來說,當我們對以下的url送出請求

localhost:3000/pages?state=cool

我們可以得到以下的params

params
=> <ActionController::Parameters {"state"=>"cool", "controller"=>"pages", "action"=>"index"} permitted: false>

使用form表單送出get request

假設你使用get的form表單,你也可以透過query string parameters來傳遞訊息到params中。

<%= form_tag "/", method: :get do %>
  <%= label_tag :name %>
  <%= text_field_tag :name %>
  <%= label_tag :age %>
  <%= text_field_tag :age %>
  <%= submit_tag "Submit" %>
<% end %>

接著在controller中下byebug

class PagesController < ApplicationController
  def index
    byebug
  end
end

頁面看起來像這樣

送出請求後在byebug停下來的地方下params指令會得到

<ActionController::Parameters {"utf8"=>"✓", "name"=>"Franklin Graham", "age"=>"43", "commit"=>"Submit", "controller"=>"homes", "action"=>"show"} permitted: false>

讓指令繼續跑完,照理說你的url會變成這樣

所以即使你是透過form表單送出get request,最後也是變成query string parameters的方式傳遞訊息。

HTTP Post

另外一種傳遞params的方式,是透過Rails的HTTP Post方法。

讓我們建立一個表單和對應的action。

<%= form_for @page do |f| %>
  <%= f.label :user %>
  <%= f.text_field :user %>
  <%= f.submit "送出" %>
<% end %>
# controller/pages_controller.rb
Class PagesController < ApplicationController
  def create
    @page = Page.new(page_params)
    @page.save
  end
end

而我們在controller可以得到params如下

params
=> <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"nZgtu+hFRmIbLcZU+uVcfRLdXXYW0J4U005GzeoCFu2eY9kW7Nu2niJu9Bf+aCvCxlsc2QclvCQGzBYU5z2+xQ==", "page"=>{"user"=>"Elon Musk"}, "commit"=>"送出", "controller"=>"pages", "action"=>"create"} permitted: false>

如果你仔細觀察的話你會發現,透過query string parameter跟Post request傳遞的params基本上沒有太大的差異,這也是為什麼我們說Rails並不區分兩者的原因。

Hash and Array Parameters

如果想要在params中產生nested array的話,你可以這樣做

https://example.com/clients?ids[]=1&ids[]=2&ids[]=3

這樣的話,透過params我們就可以得到

params[:ids]
=> ["1", "2", "3"]
<form accept-charset="UTF-8" action="/clients" method="post">
  <input type="text" name="client[name]" value="Acme" />
  <input type="text" name="client[phone]" value="12345" />
  <input type="text" name="client[address][postcode]" value="12345" />
  <input type="text" name="client[address][city]" value="Carrot City" />
</form>

When this form is submitted, the value of params[:client] will be { "name" => "Acme", "phone" => "12345", "address" => { "postcode" => "12345", "city" => "Carrot City" } }. Note the nested hash in params[:client][:address].

路徑路由(Routing Parameters)

前面提到了兩種不同傳遞params的方式,這邊我們介紹透過路由的設定,達到預先設定params的key和value的方法。

另外,還會講解path

預先設定key

先讓我們設定以下的路徑

get '/pages/:status' => 'pages#index'

當使用者送出一個get request到/clients/active時,params[:state]的value就會被設定成active。

所以我們可以透過params得到

params[:state]
=> "active"

預先設定key、value

依舊是跟剛剛相同的路由,但我們而外加入一個hash{foo: bar}

get '/pages/:status' => 'pages#index', foo: 'bar'

這樣params[:foo]就會被設定成"bar"

params[:foo]
=> "bar"

傳遞參數到url helper中

寫過一段時間Rails的人,一定對這樣的寫法感到不陌生

link_to "Edit Page", edit_page_path(@page)

當我們點擊了Edit Page之後,我們基本上會被帶到以下的網址。

localhost:3000/pages/3/edit

我們可以仔細觀查這個路由的uri pattern

/pages/:id/edit(.:format)

這表示當我們把object塞到path裡時,這個edit_page_path會透過塞進來的object,得到該object的id,並產生對應的路由。也就是說edit_page_path(@page)會變成

edit_page_path(@page)
=> localhost:3000/pages/3/edit

雖然這個效果很方便,但這神奇的效果是怎麼做到的?

這個效果是因為在產生路徑的過程當中,Rails會觸發一個to_params的方法,將object轉換成該object的id。

def to_param
  id && id.to_s
end

此外,我們也可以另外path設定額外的params key和value。

edit_page_path(@page, state: "active")
=> localhost:3000/pages/3/edit?state=active

參考資料

Action Controller 概覽
路由(Routing)
Friendly URLs

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

@linjiahung, 这就是文章该有的气质!