<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 3.2 表單 ## 概要: 本課時講解 Rails 如何通過表單(Form)傳遞數據,以及表單中的輔助方法使用,并實現登陸注冊功能。 ## 知識點: 1. 表單 1. 表單中的輔助方法(helper) 1. 表單綁定模型(Model) 1. 注冊和登錄 ## 正文 ### 3.2.1 搜索表單(Form) 如果我們的表單不產生某個資源的狀態改變,我們可以使用 GET 發送表單,這么說很抽象,比如一個搜索表單,就可以是 GET 表單。 我們在頁面的導航欄上,增加一個搜索框: ~~~ <%= form_tag(products_path, method: "get") do %> <%= label_tag(:q) %> <%= text_field_tag(:q) %> <%= submit_tag("搜索") %> <% end %> ~~~ `form_tag` 產生了一個表單,我們設定它的 `method` 是 `get`,它的 `action` 地址是 `products_path`,我們也可以設定一個 hash 來制定地址,比如: ~~~ form_tag({action: "search"}, method: "get") do ~~~ 這需要你在 `products` 里再增加一個 `search` 方法,否則,你會得到一個 `No route matches {:action=>"search", :controller=>"products"}` 的提示,這告訴我們,`form_tag` 的第一個參數需要是一個可解析的 `routes` 地址。當然,你也可以給它一個字符串,這個地址即便不存在,也不會造成 `no route` 提示了。 ~~~ form_tag("/i/dont/know", method: "get") do ~~~ 這并不是我們最終的代碼,我們還需要增加一些附加的屬性,讓我們的式樣看起來正常一些。而且我用了 `params[:q]` 這個方法,獲得地址中的 `q` 參數,把搜索的內容放回到搜索框中。 ![](https://box.kancloud.cn/2015-08-18_55d2e47fc19bf.png) 我們可以在 controller 里,使用 ActiveRecord 的 where 方法查詢傳入的參數,我們頁可以使用 ()[[https://github.com/activerecord-hackery/ransack](https://github.com/activerecord-hackery/ransack)] 這種 gem 來實現搜索功能。 ransack 是一個 metasearch 的 gem,實現它非常的方便。我們把它加入到 gemfile 里: ~~~ gem 'ransack' ~~~ 我們在視圖里,使用 ransack 提供的輔助方法,來實現表單: ~~~ <%= search_form_for @q, html: { class: "navbar-form navbar-left" } do |f| %> <div class="form-group"> <%= f.search_field :name_cont, class: "form-control", placeholder: "輸入商品名稱" %> </div> <% end %> ~~~ 提示:如果每個頁面都包含這個搜索框,但是不見得每個頁面都有 @q 這個實例,所以我們可以自己寫一個表單,實現搜索: ~~~ <%= form_tag products_path, method: :get, class: "navbar-form navbar-left" do %> <div class="form-group"> <%= text_field_tag "q[name_cont]", params["q"] && params["q"]["name_cont"], class: "form-control input-sm search-form", placeholder: "輸入商品名稱" %> </div> <% end %> ~~~ 在商品的 controller 中,我們修改 index 方法: ~~~ def index @q = Product.ransack(params[:q]) @products = @q.result(distinct: true) end ~~~ 好了,一個簡單的查詢實現了。這里我們使用的是 `name_cont` 來實現模糊查詢,[文檔](https://github.com/activerecord-hackery/ransack) 上提供了詳盡的方法,實現更復雜的查詢。 ### 3.2.2 常用的表單輔助方法 在我們使用 `form_tag` 的同時,我們還需要一些輔助方法來生成表單控件。 ~~~ <%= 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) %> ~~~ 解析后的代碼是: ~~~ <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" /> ~~~ 更多的表單輔助方法,建議大家直接查看這個部分的 [源代碼](https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/form_tag_helper.rb),我一直認為源代碼是最好的教材。 ### 3.2.3 模型(Model)的輔助方法 我們還可以使用不帶有 `_tag` 結尾的輔助方法,來顯示一個模型(Model) 實例(Instance),比如我們的 `@product`,可以在它的編輯頁面中這樣來寫: ~~~ <%= text_field(:product, :name) %> ~~~ 他會給我們 ~~~ <input type="text" value="測試商品" name="product[name]" id="product_name"> ~~~ 它接受兩個參數,并把它拼裝成 `product[name]`,并且把 `value` 賦予這個屬性的值。我們提交表單的時候,Rails 會把它解釋成 `product: {name: '測試商品', ...}`,這樣,`Product.create(...)` 可以添加這個商品信息到數據庫中了。 不過這樣做會有個問題,這個商品會有很多屬性需要我們填寫,會讓代碼變得“啰嗦”。這時,我們可以把這個實例,綁定到表單上。 注:說模型對象,通常指 `Product` 這個模型,說模型實例,指 `@product`。一些文檔上并不區分這種稱呼,個人覺得容易混淆。 ### 3.2.4 把模型(Model)綁定到表單上 來看看我們的商品添加界面使用的表單吧,它在這里 `app/views/products/_form.html.erb` ~~~ <%= form_for @product, :html => { :class => 'form-horizontal' } do |f| %> ~~~ 這里我們用了 `form_for` 這個方法,它可以將一個資源和表單綁定,這里我們將 `controller` 中的 @product 和它綁定。`form_for` 會判斷 @product 是否為一個新的實例(你可以看看 `@product.new_record?`),從而將 `form` 的地址指向 `create` 還是 `update` 方法,這是符合我們之前提到的 REST 風格。 當然,大多數瀏覽器是不支持`PUT`,`PATCH`,`DELETE` 方法的,瀏覽器在提交表單時,只會是 `GET` 或 `POST`,這時,form_tag 會創建一個隱藏空間,來告訴 Rails 這是一個什么動作。而 `form_for` 會根據實例,來自動判斷。 ~~~ <input name="_method" type="hidden" value="patch" /> ~~~ 在我們顯示商品屬性的時候,用到了 `f.text_field :name` 這個輔助方法,這樣,我們不用再為每一個 `text_field` 去聲明這是哪個實例了。`f` 是一個表單構造器(Form Builder)實例,你可以在 [這里](http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html) 看到更多它的介紹。 我們可以自己定義 `FormBuilder`,以節省更多的代碼,也可以使用 [simple form](https://github.com/plataformatec/simple_form),[formtastic](https://github.com/justinfrench/formtastic) 這種 Gem。推薦 [ruby-toolbox.com](https://www.ruby-toolbox.com) 這個網站,你可以發現其他的好用的 Gem。 ### 3.2.5 注冊和登錄 現在,我們實現一個很重要的功能,注冊和登錄。我們不需要從頭實現它,因為我們有 Rails 十大必備 Gem 中的第一位:[Devise](https://github.com/plataformatec/devise) 可以選擇。 在 `Gemfile` 中增加 ~~~ gem 'devise' ~~~ 在 `bundle install` 之后,我們需要創建配置文件:用戶(User) ~~~ % rails generate devise:install User create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> 4. If you are deploying on Heroku with Rails 3.2 only, you may want to set: config.assets.initialize_on_precompile = false On config/application.rb forcing your application to not access the DB or load models when precompiling your assets. 5. You can copy Devise views (for customization) to your app by running: rails g devise:views =============================================================================== ~~~ 之后,我們創建用戶(User)模型: ~~~ % rails generate devise User invoke active_record create db/migrate/20150224071758_devise_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml insert app/models/user.rb route devise_for :users ~~~ 之后,我們創建用戶(User)需要的 `views`: ~~~ % rails g devise:views invoke Devise::Generators::SharedViewsGenerator create app/views/users/shared create app/views/users/shared/_links.html.erb invoke form_for create app/views/users/confirmations create app/views/users/confirmations/new.html.erb create app/views/users/passwords create app/views/users/passwords/edit.html.erb create app/views/users/passwords/new.html.erb create app/views/users/registrations create app/views/users/registrations/edit.html.erb create app/views/users/registrations/new.html.erb create app/views/users/sessions create app/views/users/sessions/new.html.erb create app/views/users/unlocks create app/views/users/unlocks/new.html.erb invoke erb create app/views/users/mailer create app/views/users/mailer/confirmation_instructions.html.erb create app/views/users/mailer/reset_password_instructions.html.erb create app/views/users/mailer/unlock_instructions.html.erb ~~~ 最后,更新 db: ~~~ rake db:migrate ~~~ 在使用注冊登錄功能前,我們修改一下布局頁面,增加幾個鏈接: ~~~ <% if user_signed_in? %> <li><%= link_to current_user.email, profile_path %></li> <li><%= link_to "退出", destroy_user_session_path, method: :delete %></li> <% else %> <li><%= link_to "登錄", new_user_session_path %></li> <li><%= link_to "注冊", new_user_registration_path %></li> <% end %> ~~~ 現在,我們可以使用注冊登錄功能了,是不是很簡單呢? 接下來,我們對 Devise 創建的頁面做一點修改,同時看看 Rails 如何實現表單的。 我們登錄界面在 `app/views/users/sessions/new.html.erb`,我們把它改一下,符合我們頁面風格,具體如何使用 html 代碼,可以參考 [http://bootswatch.com/simplex/](http://bootswatch.com/simplex/)。 本章的代碼在[這里](https://github.com/liwei78/rails-practice-code/tree/master/chapter_3/shop2),希望可以幫助大家理解表單和其使用。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看