Help us understand the problem. What is going on with this article?

【Ruby on Rails】collection_check_boxes で 詰まったから...

More than 1 year has passed since last update.

はじめに

Rails 4.0.2以降から使用できる
ViewHelper の collection_check_boxes を使用しようとして少し詰まったので、
簡単なアプリケーションを作成してみて、楽しく覚えてみた。

環境

  • Ruby: 2.4.0
  • RoR: 5.0.6
  • haml

やりたいこと

User を 作成するときに 飲み物(Drink)を 選択して create できる。

プラスα - 選択肢にない飲み物(Drink)が 出てきたら 飲み物も新規登録できるように。

2018-01-24 17.14.15.png

いわゆる、

パシリの為の パシリによるアプリケーション

- タケシは、 コーラ。
- サトルは、コーヒーと水。
- ハナコは、お茶。

あれ、、、全部覚えてられないな。。。orz

やってみた

scaffold で User, Drink, DrinkUser を 作成
多 対 多 の関係性を 記していく。

Model

user.rb
class User < ApplicationRecord

  has_many :drink_users
  has_many :drinks, through: :drink_users
  accepts_nested_attributes_for :drink_users, allow_destroy: true


end

drink.rb
class Drink < ApplicationRecord

  has_many :drink_users
  has_many :users, through: :drink_users

end


drink_user.rb
class DrinkUser < ApplicationRecord

  belongs_to :user, optional: true
  belongs_to :drink, optional: true

end


Controller

users の new に Drink を 用意しておく

users_controller.rb
class UsersController < ApplicationController

  def new
    @user = User.new
    @drinks = Drink.all
  end

... ... ... ...

  private

  def user_params
    params.require(:user).permit(:name, drink_ids: [])
  end

end

scaffold で 作成された Controllerに
@drinks = Drink.all (チェックボックスの選択に使用)と
StrongParametersに drink_ids: [] (配列のパラメーターを許可) を足した。

View

users/_from.haml
= form_for(user) do |f|
  - if user.errors.any?
    #error_explanation
      %h2
        = pluralize(user.errors.count, "error")
        prohibited this user from being saved:
      %ul
        - user.errors.full_messages.each do |message|
          %li= message
  .field
    = f.label :name
    = f.text_field :name

    = f.collection_check_boxes :drink_ids, @drinks, :id, :name, include_hidden: false do |b|
      = b.label { b.check_box + b.text }

  .actions
    = f.submit


= f.collection_check_boxes の チェックボックスの記述を追加。

Seed

db/seeds.rb
%W[コーヒ コーラ お茶 紅茶 ミルクティ 水].each { |a| Drink.create(name: a) }

よく お頼みになる飲み物を seedファイルで予め用意しておく。
rails db:seed の実行を忘れずに。

drinks_tables.
+----+--------------------+---------------------+---------------------+
| id | name               | created_at          | updated_at          |
+----+--------------------+---------------------+---------------------+
|  1 | コーヒ               | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  2 | コーラ               | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  3 | お茶                | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  4 | 紅茶                | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  5 | ミルクティ            | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  6 | 水                 | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
+----+--------------------+---------------------+---------------------+


これだけで
/users/newに アクセスすると、
人の名前を入力して、飲みモノを 選んで, データを作成することができる。




collection_check_boxes の使い方

下記、HTMLのような、チェックボックスを collection_check_boxesを使用して、いい感じに表示させる。

sample.html
<form action="cgi-bin/abc.cgi" method="post">
  <p>
    <input type="checkbox" name="riyu" value="1">選択肢 - 1
  </p>
  <p>
    <input type="checkbox" name="riyu" value="2">選択肢 - 2
  </p>
  <p>
    <input type="checkbox" name="riyu" value="3">選択肢 - 3
  </p>
  <p>
    <input type="submit" value="送信する">
  </p>
</form>


スクリーンショット
2018-01-24 18.16.03.png

collection_check_boxes を用いてみる


check_boxes.haml
= form_for(user) do |f|
  = f.label :name
  = f.text_field :name

  = f.collection_check_boxes :drink_ids, @drinks, :id, :name do |b|
    = b.label { b.check_box + b.text }

  = f.submit '送信', class: 'btn'

btn.css
.btn{
    display: inline-block;
    padding: 0.5em 1em;
    text-decoration: none;
    background: #668ad8;
    color: #FFF;
    border-bottom: solid 4px #627295;
    border-radius: 3px;
}


スクリーンショット
2018-01-24 15.17.29 1.png

なんだか、チェックボックス と テキストの感覚が ギュン と近すぎて気持ち悪い...orz


check_boxes.haml
= form_for @user do |f|
  = f.collection_check_boxes :reason_ids, @choices, :id, :content do |b|
    = b.check_box
    = b.label { box.text }
  = f.submit '送信', class: 'btn'


スクリーンショット

2018-01-24 15.06.16.png

いい感じになった☺

Option

上記の form のままだと パラメーターの配列の先頭に ' '
空の 値が含まれるので, option で

check_boxes_option.rb
  f.collection_check_boxes :reason_ids, @choices, :id, :content, include_hidden: false do |b|

のように option で 先頭の空の値をなくすことができる。

また, 1行で 書くこともできる

check_boxes_one_line.rb
  = f.collection_check_boxes :drink_ids, @drinks, :id, :name, include_hidden: false, class: 'hoge'

1行で書くと, classなど html のoptionの与え方がややこしくなるので、僕は ネストさせた方が好きです。


余談

users_table.
+----+-----------+---------------------+---------------------+
| id | name      | created_at          | updated_at          |
+----+-----------+---------------------+---------------------+
|  1 | タケシ     | 2018-01-24 09:22:21  | 2018-01-24 09:22:21 |
|  2 | サトル     | 2018-01-24 09:22:41  | 2018-01-24 09:22:41 |
|  3 | ハナコ     | 2018-01-24 09:23:11  | 2018-01-24 09:23:11 |
+----+-----------+---------------------+---------------------+

drinks_table.
+----+--------------------+---------------------+---------------------+
| id | name               | created_at          | updated_at          |
+----+--------------------+---------------------+---------------------+
|  1 | コーヒ               | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  2 | コーラ               | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  3 | お茶                | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  4 | 紅茶                | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  5 | ミルクティ            | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
|  6 | 水                 | 2018-01-24 09:01:14 | 2018-01-24 09:01:14 |
+----+--------------------+---------------------+---------------------+

drink_users_table.
+----+----------+---------+---------------------+---------------------+
| id | drink_id | user_id | created_at          | updated_at          |
+----+----------+---------+---------------------+---------------------+
|  1 |        2 |       1 | 2018-01-24 09:22:21 | 2018-01-24 09:22:21 |
|  2 |        1 |       2 | 2018-01-24 09:22:41 | 2018-01-24 09:22:41 |
|  3 |        6 |       2 | 2018-01-24 09:22:41 | 2018-01-24 09:22:41 |
|  4 |        3 |       3 | 2018-01-24 09:23:11 | 2018-01-24 09:23:11 |
+----+----------+---------+---------------------+---------------------+

こんな感じ🤔

スクリーンショット
2018-01-24 18.35.20.png

drinks/new も動かせば, 飲み物の選択肢を 増やすことができるので、イレギュラーにも対応できます☺




参考

shunn_93
gashoo
僕たちはクリエイターの働き方、生き方を開発する企業です。
https://gashoo.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした