フォーム - lanchester/rails_environment GitHub Wiki
https://github.com/rails/strong_parameters
mass assignment対策用の機能です。元々はgemでしたがrails 4以降ではコア機能として取り込まれました。
フォームからのパラメータをDBに登録するようなコントローラにおいて
User.new(params.require(:user).permit(:name, email))のようにホワイトリスト形式で記述します。
配列の指定やネストしたパラメータも指定できます。
params.require(:user).permit(:name, emails: [], friend: [:name, :email])permit!を使うことによってすべてのパラメータを許可することもできます。
params.require(:user).permit!ただし、mass assignment脆弱性への危険はあります。
https://github.com/plataformatec/simple_form
フォームの記述を少なくできるgemです。
gem 'simple_form'
bundle install
rails generate simple_form:installでプロジェクトにインストール。
以下のファイルが生成されます。
create config/initializers/simple_form.rb
exist config/locales
create config/locales/simple_form.en.yml
create lib/templates/erb/scaffold/_form.html.erbtwitter-bootstrapと連携する場合は以下のようにオプション付きでインストールします。
rails generate simple_form:install --bootstrap
viewでform_forの代わりにsimple_form_forと記述します。
<%= simple_form_for @model, url: { controller: :[コントローラ名], action: :[アクション名] } do |f| %>
<%= f.input :name %>
<%= f.input :sex, collection: [["男", 1], ["女", 2]], as: :radio_buttons, checked: @model.sex %>
<%= f.input :job, collection: Job.all.map { |j| [j.name, j.id]}, as: :select, selected: @model.job %>
<% end %>これで<label>まで含めてタグが生成されます。ラジオボタンやセレクトボックスの場合collectionに配列を指定します。I18n等で日本語化する場合、modelでメソッドを定義しておくと良いです。
バリデート失敗時等に入力情報を保つ場合はcheckedやselectedオプションを指定します。enumerizeを使っているカラムの場合は、@model.sexとすると文字列が返ってくるので@model.sex_valueなどで実際にDBに保存する値と比較します。
ブロックを取ることでrailsのヘルパーも使えます。
<%= f.input :role do %>
<%= f.select :role, Role.all.map { |r| [r.name, r.id, { class: r.company.id }] }, include_blank: true %>
<% end %>
<%= f.input :hoge, input_html: {value: "fuga", id: "piyo"} %>remote: trueただし、ファイルアップロード時には非同期宣言を無視して画面遷移しようとしてmissing templateエラーとなるため上記は使えない。
viewでフォーム要素を動的に追加して子テーブルに持つことができるgemです。
# Gemfile
gem 'nested_form'application.jsに以下を追加します。
//= require jquery_nested_form対象となるモデルにはhas_manyとaccepts_nested_attributes_forを指定しておきます。関連モデルの削除を許可するならallow_destroy: trueを指定します。
class Blog < ActiveRecord::Base
has_many :articles
accepts_nested_attributes_for :articles, allow_destroy: true
endnested_form_forヘルパーが使えるようになります。
# view
<%= nested_form_for(@blog) do |f| %>simple_formやformtasticを使用している場合はそれぞれ
simple_nested_form_for
semantic_nested_form_forで使用可能になります。
# view
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<%= f.fields_for :blogs do |blog| %>
<%= blog.text_field :name %>
<%= blog.link_to_remove "Remove this" %>
<% end %>
<%= f.link_to_add "Add article", :articles %>
<div class="actions">
<%= f.submit %>
</div>コントローラではstrong_parameterを許可しておきます。
# controller
def blog_params
params.require(:blog).permit(:title, :articles_attributes => [:id, :name, :blog_id, :_destroy])
end以下のように通常のバリデーションと同じように指定できます。関連モデルにバリデーションを指定しておくことで、そのバリデートを実行できます。
class Blog < ActiveRecord::Base
has_many :articles
accepts_nested_attributes_for :articles, allow_destroy: true
validates :blog_title, presence: true
validates :articles, presence: true
end
class Article < ActiveRecord::Base
belongs_to :blog
validates :title, presence: true
end以下のFormtasticのヘルパーにより自動でバリデーションエラー時のメッセージを表示できます。
<%= f.semantic_errors *f.object.errors.keys %>関連モデルのattributeの日本語化は以下のように/でモデル同士を繋げて指定します。
# config/locales/ja.yml
ja:
activerecord:
attributes:
blog:
blog_title: hoge
blog/articles:
title: fugarequestにはリクエストオブジェクトが色々入っています。これを使ってリクエストメソッドによって処理を分けることもできます。
# controller
def new
if request.get? # 他にはpost?など
@model = Model.new
else
@model = Model.new(params)
end
endただしフォームでリクエストを分ける場合POST、PUT、PATCHはrailsがフォームによって自動で変えているためハマりポイントになりやすいです。get?で判定するのが無難そうです。