#author("2016-04-21T16:37:52+09:00","default:wikiwriter","wikiwriter")
&tag(Rails/フォーム);
*目次 [#zc5cb8b4]
#contents
*関連ページ [#tbe1b391]
*参考情報 [#v2e8a01d]

*Tips [#r6205d0d]

**フォーム内のボタンをsubmit以外にする [#t773b6f7]
-[[RailsのForm内のbuttonでsubmit以外のことをさせたい(link_to的なこと) - Qiita:http://qiita.com/t_oginogin/items/b682f664ce8244a7c2bd]]
-結局link_toの中にbutton_tagを書くしかない?
#pre{{
<%= link_to (button_tag "ボタン", type: 'button'), { controller: :books, action: :new } %>
}}
**データの保存時に空白をnullに変換 [#sb3131d6]
-[[mysql - Rails: Force empty string to NULL in the database - Stack Overflow:http://stackoverflow.com/questions/7202319/rails-force-empty-string-to-null-in-the-database]]によると簡単に実行する方法はない?
-[[rubiety/nilify_blanks:https://github.com/rubiety/nilify_blanks]]…nifty blanksというgemがあるらしいけど。

**複数Submitボタンが存在するForm [#xd43d26a]
-ビュー側
#pre{{
<%= form_tag(operate_url) do %>
    <%= submit_tag('移動')%>
    <%= submit_tag('削除',  {name: 'delete'})%>
<% end %>
}}
-コントローラー側
#pre{{
    if params[:delete]
      #削除処理
      redirect_to(folder_path(@folder), notice: "削除しました")
    else
     #通常処理
      redirect_to(folder_path(@folder), notice: "移動しました")
    end
}}


**2重保存を防ぐ [#d65bc4c1]

***double submit protectionを使う [#h97eedea]
-Submitを無効化するのではなく、戻る=>保存の2重登録を防ぐ方法。
--[[herval/double_submit_protection:https://github.com/herval/double_submit_protection]]
--[[実録!Railsのはまりポイント10選:http://www.slideshare.net/drecom/edgerails2]]
--[[browser - Rails: Prevent duplicate inserts due to pressing back button and save again - Stack Overflow:http://stackoverflow.com/questions/4657758/rails-prevent-duplicate-inserts-due-to-pressing-back-button-and-save-again]]
-全部同じアイデアでセッションにトークンを保存して、保存時に確認する処理を入れる。しかしかなり古いし、最近の情報はあまり見つからない。より良い方法があるか確認する。
-ちなみにRedmineでも戻る、保存で連続作成できてしまう。何もしないのが定石?

***ハッシュ値を計算して2重登録を防ぐ方法 [#aa8c6cb2]
-[[Prevent double data submission in Rails 3 - hibbard.eu:http://hibbard.eu/prevent-double-data-submission-in-rails-3/]]にて提唱されている方法。
-JavaScriptでボタンを無効化した上直前に登録されたデータとハッシュ値の比較を行うことで防ぐ。
-モデルに以下を追加
#pre{{
def make_hash
  res = []
  columns_to_skip = ["created_at", "updated_at", "hash"]
  for column in Applicant.content_columns
    next if columns_to_skip.include?(column.name) or 
            self[column.name].nil? or self[column.name].blank?
    res << self[column.name]
  end
  res.hash.to_s
end
}}
-コントローラーに以下を追加。
#pre{{
def create
  @applicant = Applicant.new(params[:applicant])
  a = Applicant.last
  @previous_applicant_hash = (a.nil?)? 0 : a.applicant_hash
  if @applicant.valid?
    unless @applicant.applicant_hash == @previous_applicant_hash
      @applicant.save
      ApplicantMailer.admin_notification(@applicant).deliver
      ApplicantMailer.application_confirmation(@applicant).deliver
    end
    redirect_to :action => "success"
  else
    render action: "new"
  end
end
}}

***Redisを使う [#s049eb5c]
-redisを使う
#pre{{
Redis.current.lock("#{current_user.id}.action_name") do
   # Some code
end
}}

***PHPの方法 [#cd9b087c]
-[[PHPでの二重送信対策が、効いていない?(追記あり) - Qiita:http://qiita.com/cufh/items/e04f544ff3f68ff4a883]]などなど。チケット、トークンなどで検索。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS