質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

2034閲覧

1つのカラムにデータを配列で入れるには?

Gr.

総合スコア89

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

1グッド

1クリップ

投稿2018/09/09 00:18

編集2018/09/09 04:51

1つのカラムに複数のテキストデータを入れたい

すごく初歩的な質問だと思います。

例)ユーザー登録フォームで"行ったことのある国"を入力してもらうケース
ユーザーAさんの行ったことのある国が「アメリカ」「イギリス」「中国」だったとし、そのデータをUserモデルのvisitedカラムに入れたいのですが、どうすればいいでしょうか。

そのデータをもとにやりたいことは...

  1. ユーザーAさんが何か国行ったことがあるかカウントしたい。
  2. "行ったことのある国"でユーザーの絞り込み検索がしたい。

この場合、あらかじめ選択肢で国名を設けておくと200近い選択肢が必要になりますよね。
かと言って、フォームに直接入力してもらおうとすると、「アメリカ、イギリス、中国」と書かれてはこれで一つの国になってしまいカウントできませんし、「アメリカ」に行ったことがある人としてユーザーAさんを取り出せません。

※質問の趣旨から逸れないために、ユーザーによる国名表記は別にガイド等を設けて一致しているものと仮定します。(「アメリカ」「アメリカ合衆国」「米国」など書き方は様々ですがみんな「アメリカ」と書いてくれる、などとここでは仮定する)

ユーザーAさんのvisitedカラムに "アメリカ", "イギリス", "中国" と入れられれば上記1,2は解決するのですが、それにはどうしたらいいのでしょうか。

教えていただきたいこと

  • 「複数選択可の選択肢を設ける」がベストソリューションの場合、たぶんcheckboxを使用すると思うのですが、複数選択してカラムに配列でデータを送る書き方がわかりません。
  • 仮に登録できる上限を5か国までとし、text_fieldを5つ設け、それぞれをvisitedカラムに関連付けるとしたらどう書けばいいのでしょうか。

質問内容からお察しいただけるかと思いますが、全くの初心者ですのでお手柔らかにお願いします。

例示用コード

コメントありがとうございます。
以下にコードを追記します。
たとえばチェックボックスで複数選択可にする場合、今の自分の知識では下記のように書くしかありません。

html

1<%= form_for(@users) do |f| %> 2 <label>アメリカ<%= f.check_box 'visited1', {}, "アメリカ" %></label> 3 <label>イギリス<%= f.check_box 'visited2', {}, "イギリス" %></label> 4 <label>中国<%= f.check_box 'visited3', {}, "中国" %></label> 5 <%= f.submit %> 6<% end %>

つまり、カラムをvisited1、visited2、visited3...と用意してそこに値を入れていくという何とも非効率なやり方です。選択肢が3つ程度ならこれでもいいのでしょうが、国名全てを選択肢にするとなると、これでは到底現実的ではなく、もっといい書き方があるはずです。

そこで、登録できる上限を5か国までとし、下記のようにtext_fieldを使ったほうがいいのかなと思ったのですが、、、

html

1<%= form_for(@users) do |f| %> 2 <p>行ったことのある国1</p> 3 <p><%= f.text_field :visited %></p> 4 <p>行ったことのある国2</p> 5 <p><%= f.text_field :visited %></p> 6 <p>行ったことのある国3</p> 7 <p><%= f.text_field :visited %></p> 8 <p>行ったことのある国4</p> 9 <p><%= f.text_field :visited %></p> 10 <p>行ったことのある国5</p> 11 <p><%= f.text_field :visited %></p> 12 <%= f.submit %> 13<% end %>

これでは最後のフィールドに入れた値しか受け取れませんよね...
この5つのフィールドに入れられた値をvisitedカラムに "アメリカ", "イギリス", "中国" といった形で保存したいのです。

1つのtext_fieldで「ユーザーが単語をスペースで区切って入力すれば配列で保存できる」なんてことはできないのでしょうかね。

ド素人のレベルの低い質問で恐縮です。
コードのサンプルなど無くても、「〇〇使えば出来るよ」「こんな感じで書けば?」的なヒントだけでもいただければ自力で調べてみますので何とぞよろしくお願いいたします。

jays_seiya👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun68ykt

2018/09/09 02:11

こんにちは。「ここまで作ってみたけど、意図どおりうまく動かなくて困ってる」とか、「ここまで出来たけど、ここから、こうする方法が分からない」といったような、今の段階を明らかにするような、作りかけのRailsアプリのコードはありますでしょうか?あれば、ご質問に追記をお願いいたします。
guest

回答1

0

ベストアンサー

こんにちは。

質問への追記・修正依頼にお応え頂いてのソースコードの掲示、ありがとうございます。

「〇〇使えば出来るよ」「こんな感じで書けば?」的なヒントだけでもいただければ自力で調べてみますので

とありましたので、以下、「自分ならこう作るかな」というアイディアレベルの、あくまで私見になります。

(なお当方は、ふだんの業務時間の7〜8割がたフロントエンド開発に従事し、残り2〜3割をバックエンド開発のヘルプに入る的な立ち位置です。バックエンドは近年、Railsが多いです。)

1.バックエンド開発

1.1 国マスターテーブルの作成

  • Country モデルを作成し、 countriesテーブルに国のマスターデータを格納する。
  • 最低限、名前を入れる name カラムを用意する。
  • 元になるデータは、たとえば ISO 3166-1 の表などをスクレイピングさせて頂くなどして入手

例) countries テーブル

idname
1アメリカ合衆国
2中華人民共和国
3オーストラリア
4フランス

1.2 users テーブルの visited カラムに入れる配列データの形式

  • visitedカラムの型は文字列で、countriesテーブルの id をCSV形式(カンマ区切りの文字列)で入れることにします。

例) 中国(country_id:2)とフランス(country_id:4)に行ったことのある鈴木(id=100)さんの場合

idnamevisited
100鈴木2,4

他の形式も考えられます。 たとえばJSONの配列形式にするのであれば、visitedには [2,4]という文字列が入ります。

1.3 ユーザーの訪問したことのある国として、ある国を追加または削除するAPIの設計と実装

1.3.1 設計

メソッドとURLはざっくり以下のようなものになるかと思います。

  • 鈴木さん(user_id:100)が行ったことのある国のリストに オーストラリア(country_id:3)を追加する。
POST /users/100/countries/3
  • 鈴木さん(user_id:100)が行ったことのある国のリストから オーストラリア(country_id:3)を削除する。
DELETE /users/100/countries/3

上記のURLとメソッド、さらにこれにパラメータの加わった、APIの設計は諸説意見の別れがちな所ではありますが、この回答では、とりあえず上記で進めます。

1.3.2 実装

上記 1.3.1 のURLとメソッドからルーティングされる UsersController のアクションでは、以下を行うことになるでしょう。

国の追加

  • user_id :100 のUserインスタンスを取得。 その visitedのCSVに 3 が無ければ追加したCSVを作って、この新しいCSV文字列でvisitedを更新

国の除外

  • user_id : 100 のUserインスタンスを取得。 その visitedのCSVに 3 があればこれを除外したCSVを作って、この新しいCSV文字列でvisitedを更新

2. フロントエンド開発

  • 先の1.3 で設計したAPIを使って、各チェックボックスの選択状態が変更されたら、すぐにDBに反映されるようなUIを想定します。

  • もちろん、すべてのチェックボックスについて「チェックする・しない」を入力し終わったあとに、「保存」ボタンをクリックしてもらって、各国の「訪問した or していない」を、まとめていっぺんに送る方法もありますが、この回答では、そのための説明は割愛します。

2.1 チェックボックス

並べ方として最も簡単なのは、以下のように Country.order(:id) で得られる配列を単純にループして、チェックボックスを作成します。

html

1アメリカ合衆国: <input type="checkbox" class="country_check" value="1" /> 2中華人民共和国: <input type="checkbox" class="country_check" value="2" /> 3オーストラリア: <input type="checkbox" class="country_check" value="3" /> 4フランス: <input type="checkbox" class="country_check" value="4" />
  • 各チェックボックスの classは “country_check” で統一し、value属性の値は country_id とします。

  • また、画面のどこかに user_id と ユーザー名を持っている hidden の<input> を書いておきます。以下は鈴木さん(user_id: 100)の場合です。

html

1<input type="hidden" id="user_id" value="100" data-user-name="鈴木" />

2.2 チェックボックスの変化からAPIをリクエスト

チェックボックスの選択状態の変化にあわせて、1.3 で設計、実装したAPIを呼ぶようにします。JQuery を使うとすると、以下のような感じです。(APIエラー時の処理等、細かいところは書いていません。あくまで概要を示すコードです。)

javascript

1$(".country_check").on("change", function() { 2 3 const countryId = $(this).val(); // country id の取得 4 const userId = $("#user_id").val(); // ユーザーidの取得 5 const userName = $("#user_id").data("user-name"); // ユーザー名の取得 6 7 const apiUrl = `/users/${userId}/countries/${countryId}`; // APIのURL 8 const method = $(this).prop("checked") ? "POST" : "DELETE"; // APIのメソッド 9 10 fetch(apiUrl, { method }) 11 .then(res => { 12 if(res.ok) { 13 console.log(`${userName}さんの行ったことのある国が変更されました。`); 14 } 15 }); 16});

 

ざっと概要を示すと以上です。

それともう一点、この質問の主旨である「1つのカラムにデータを配列で入れるには?」から外れますが、補足を以下に書きます。

補足: has_many :through関連付けの利用

  • UserCountry は Many to Many の関係なので、users と countries のインターセクションテーブル(たとえば visits という名前とします。)を作成し、これを介して 以下のように、has_many アソシエーションを追加するのが自然かなと思います。

ruby

1class User < ActiveRecord::Base 2 has_many :countries, through: :visits 3end

ruby

1class Country < ActiveRecord::Base 2 has_many :users, through: :visits 3end

Rails が用意してくれているモデル操作の仕組みをなるべく使う(いわゆる、"Rails Wayに乗る")と、やりたいことが楽に実現できることが多いので、私がこのRailsアプリを作るとしたら、上記のように has_many :through を使うことによって、「ユーザーが行ったことのある国」を表すことを考えると思います。

 

has_many :through関連付けの利用については以下をご参照ください。

以上参考になれば幸いです。

投稿2018/09/09 14:12

編集2018/09/10 22:12
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gr.

2018/09/09 23:15

jun68yktさん 素晴らしい回答をありがとうございます! 読みやすく、また具体的でとても参考になります。 「has_many :throughで関連付けする」とか、「国名データを ISO 3166-1 の表などからスクレイピングする」とかそういった知識やアイデアもなかったため、知りたかったこと以上の知識が得られました。 本当にありがとうございました!
jun68ykt

2018/09/09 23:26

Gr.さん お役にたてたようで、よかったです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問