6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

rails options_from_collection_for_select

Posted at

#初めに
collection_check_boxesと似た感じで使えるのに

options_from_collectoin_for_selectというヘルパーメソッドがありました。

これは名前からわかるようにselectタグを使うときのメソッドで

例えば既存のタグの名前からセレクトタグを自動的に生成するやつです。

#使い方

まずrails guidesにはoptions_from_collection_for_selectは

collectionを列挙した結果をoptionタグ化した文字列を返し、呼び出しの結果をvalue_methodにオプション値として割り当て、text_methodにオプションテキストとして割り当てます。

このように書いてありました。

例のごとく一回読んだだけでは理解できません.....

またこんなことも

返されるのはoptionだけです。従って、出力結果の外側を適切なHTML selectタグで囲む必要があります。

要は

<%= options_from_collection_for_select(:tag_ids, Tag.all, :id, :name) do |tag| %>
.....
<% end %>

みたいな使い方をするわけではなくこのoptions_from_collection_for_selectの外側にselectを使うなら

<%= select_tag :tag_id ..... %>

みたいにしなくちゃいけない

実際の使い方としては

<%= select_tag :tag_id,
           options_from_collection_for_select(Tag.all, :id, :name, params[:tag_id]),
           {
                       prompt: 'タグで絞り込み',
                       class: 'form-control select_css_tag',
           }
%>

みたいな感じ

#実際に使ってみる

rails g model article title
rails g model tag name
rails g model article_tags article:references tag:references
rails db:migrate
rails g controller articles

routesの設定はresourcesを使用

modelの設定は基本的な多対多の設定をする

controllerは

articles_controller.rb

class ArticlesController < ApplicationController
  def index
    @articles = Article.all 
  end

  def new 
    @article = Article.new 
  end 

  def create 
    article = Article.new(article_params)
    tag = Tag.find(params[:tag_id])
    if article.save 
      article.tags << tag
      redirect_to articles_path 
    else 
      render :new 
    end 
  end 

  private 

  def article_params 
    params.require(:article).permit(:title,:tag_id)
  end   
end

まずcreateではarticleを保存してそのあと

article.tags << tag

でarticle_tagsを作成しています。

viewは

<%= form_with model: @article, local: true do |f| %>
    <%= f.label :title %>
    <%= f.text_field :title %>

    <%= select_tag :tag_id,
         options_from_collection_for_select(Tag.all, :id, :name, params[:tag_id]), 
            {
                prompt: 'タグを選択',
            }
    %>
    <%= f.submit %>
<% end %>

こんな感じ

ちなみに複数の値を保存できるようにしたい場合はこんな感じにmultiple: trueを指定してあげればよいです


<%= form_with model: @article, local: true do |f| %>
    <%= f.label :title %>
    <%= f.text_field :title %>

    <%= select_tag :tag_id,
         options_from_collection_for_select(Tag.all, :id, :name, params[:tag_id]), 
            {
                prompt: 'タグを選択',
                multiple: true
            }
    %>
    <%= f.submit %>
<% end %>

これで複数保存できるようになります。

#発見

これを作ってるときに気づいたんですけど

select_tagでmultipleがtrueのときはparams[:tag_id]が配列で来るんですけど

controllerのcreateアクションが


def create 
    @article = Article.new(article_params)
    @tag = Tag.find(params[:tag_id])
    if @article.save 
      @article.tags << @tag
      redirect_to articles_path 
    else 
      render :new 
    end 
  end 

このままでも複数個を保存することができました。

binding.pryで調べてみたところ

Tag.find(params[:tag_id])

のところでtag_idが["1", "2"]となっているときに

    10: def create
    11:   @article = Article.new(article_params)
    12:   @tag = Tag.find(params[:tag_id])
    13:   binding.pry
 => 14:   if @article.save
    15:     @article.tags << @tag
    16:     redirect_to articles_path
    17:   else
    18:     render :new
    19:   end
    20: end

[1] pry(#<ArticlesController>)> @tag
=> [#<Tag:0x00007f36182a6d90
  id: 1,
  name: "Ruby",
  created_at: Mon, 11 Feb 2019 06:35:46 UTC +00:00,
  updated_at: Mon, 11 Feb 2019 06:35:46 UTC +00:00,
  article_id: nil>,
 #<Tag:0x00007f36182a6c50
  id: 2,
  name: "Ruby on Rails",
  created_at: Mon, 11 Feb 2019 06:35:58 UTC +00:00,
  updated_at: Mon, 11 Feb 2019 06:35:58 UTC +00:00,
  article_id: nil>]
[2] pry(#<ArticlesController>)>

こんな感じでちゃんとすべて取れてるんですよね。

Model.findって一個しか取ってこれないと思っていたので大発見でした。

またこれは基本的なことなのかもしてないですが@tagが配列の時

@article.tags << @tag

も問題なく動いてくれるんですね

普通ならループ作って

@tag.each do |tag|
  @article.tags << tag 
end 

としてしまいます。

おわり:sunny:

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?