チェックボックス機能を実装
どうもこんにちは、たけのこです。今日はとても暑いです...汗 Railsは学び始めて半年経ってないくらいですが、学んできたこと、最近実装したものを少しずつ記事にできれば良いなと思って始めました。
ここでは、プログラムを書いたときに、そのプログラムがどんな種類なのかタグをつけるという例でチェックボックス機能を実装していきたいと思います
完成形
ER図の関係とモデル部分の実装
まず、プログラムの内容に関連したcodesテーブル、タグの種類が格納されているtagsテーブルがあり、その中間テーブルにcodes_tagsテーブルがある多対多の関係を想定して進めていきます。さらに、ユーザのテーブルであるusersテーブルとcodesテーブルは1対多の関係が成立しているものとして話を進めています。 また、選べるタグの内容は決まっているものとします。これは、ユーザが好きにタグを設定しても良いことにしてしまうと、爆発的にデータ数が増えてしまうため、RDBMSでは対処できないからです(NoSQLとかが必要になってくると思います)
tag.rb
class Tag < ApplicationRecord validates :name, presence: true, length: { maximum: 20 } has_many :code_tags has_many :codes, through: :code_tags, source: :code end
code.rb
class Code < ApplicationRecord has_many :code_tags has_many :tags, through: :code_tags, source: :tag end
code_tag.rb
class CodeTag < ApplicationRecord belongs_to :code belongs_to :tag end
コントローラ部分の実装
newアクションでは、コードの空のインスタンスを生成し、タグの内容を全て呼び出しています。 createアクションでは、実際に完成形として見せたビューに内容を入力したときの内容となっています。
codes_controller.rb
class CodesController < ApplicationController def new @code = User.codes.build @tags = Tag.all end def create @code = current_user.codes.build(code_params) if @code.save flash[:success] = 'コードを公開しました。' redirect_to root_url else #今までのユーザのプログラムの投稿内容に関するインスタンスを生成してトップページに表示させている @codes = User.codes.order('created_at DESC').page(params[:page]) flash[:danger] = 'コードの公開に失敗しました。' render 'toppages/index' end end private def code_params params.require(:code).permit(:content, :summary, :program, :data, {tag_ids: []}) end
ここで重要なのは、codesのコントローラファイルにおけるストロングパラメータで以下を記載することが重要です。
def code_params params.require(:code).permit(:content, :summary, :program, :data, {tag_ids: []}) end
これによって、タグの配列のパラメータを許可しており、複数のチェックボックスに入力しても処理を可能にしています。
ビュー部分の実装
codesフォルダの中のnew.html.erbのコード内容
<div class="text-center"> <h1>コードを公開する</h1> </div> <div class="row"> <div class="col-md-6 col-md-offset-3"> <%=form_for(@code) do |f| %> <%= render 'layouts/error_messages', model: f.object %> <div class="form-group"> <%= f.label :program, 'プログラム' %> <%= f.text_area :program, class: 'form-control', placeholder: 'Markdown形式での入力(```の間にプログラムを納入する形式)', rows: 15 %> </div> <div class="form-group"> <%= f.label :data, 'データ' %> <%= f.file_field :data %> </div> <div class="form-group"> <%= f.label :tags, class: 'control-label' %> <div class="checkbox"> <%= collection_check_boxes(:code, :tag_ids, Tag.all, :id, :name) do |b| %> <%= b.label { b.check_box + b.text } %> <% end %> </div> </div> <%= f.submit '公開する', class: 'btn btn-primary btn-block' %> <% end %> </div> </div>
ここで、以下のようにチェックボックスを作成しています。
<div class="form-group"> <%= f.label :tags, class: 'control-label' %> <div class="checkbox"> <%= collection_check_boxes(:code, :tag_ids, Tag.all, :id, :name) do |b| %> <%= b.label { b.check_box + b.text } %> <% end %> </div> </div>
<%= collection_check_boxes(:code, :tag_ids, Tag.all, :id, :name) do |b| %>
は多対多の関係を前提としたビューヘルパーで、引数の説明は以下のようになっています
第一引数(:code)...オブジェクト
第二引数(:tag_ids)...チェックされたTagのidを処理するのに必要(code_tagのtag_id)
第三引数(Tag.all)...inputタグの元となるオブジェクト配列
第四引数(:id)...作成されたinputタグのvalueとなる値を指定。ここでは、各tagのidが入力されます
第五引数(:name)...作成されたinputタグのテキストを指定。ここでは、各tagのnameが入力されます
つまり、Tagを取得して、code[tag_ids][]とし、valueにtag_id,テキストにtag.nameを使用しています。
タグの名前の生成
最後に、完成形にあるようにタグの名前を生成するため、 db/seeds.rbで記載します。
Tag.create(name: '機械学習') Tag.create(name: '最適化') Tag.create(name: 'スクレイピング') Tag.create(name: 'データ分析') Tag.create(name: 'アプリ開発') Tag.create(name: 'API') Tag.create(name: 'ライブラリ・パッケージ') Tag.create(name: 'ディープラーニング') Tag.create(name: 'デバッグ') Tag.create(name: 'セキュリティ')
上記を書いたら、rails db:seed
を実行すれば、無事にタグの名前(チェック項目)が記録されます。もしもherokuでもデプロイする場合には、heroku run rals db:seed
と実行すれば問題ありません。
まとめ
今回は、Railsでチェックボックス機能を実装する手順を説明しました。チェックボックスはアンケートでも頻繁に使用されると思うので、覚えておいて損はないと思いました。