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

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

ただいまの
回答率

88.91%

検索フォームで、動的に変わるセレクトボックスを使いたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 197

pecchan

score 339

rails 5.2で検索画面を作ってるところです。

検索条件の入力項目として、「カテゴリ」>「サブカテゴリ」と連動するセレクトボックスを追加したいです。

以下を参考にセレクトボックスを追加してみましたが、応用できずにいます・・・。
Ajaxでセレクトボックスの中身が動的に変わるRailsアプリの作り方

    <%= form_with url: items_path, method: :get, local: true do |f| %>

      <% category_options = Category.order(:id).map { |c| [c.name, c.id, data: { children_path: category_sub_categories_path(c) }] } %>
      <%= f.label :category_id %> <%= label_tag(:category, "", class: 'optional_field') %>
      <%= select :search, :category_id, category_options, {include_blank: ""}, {class: 'select-parent'} %>

      <% sub_categories = @item.category.try(:sub_categories) || [] %>
      <% sub_category_options = sub_categories.map { |c| [c.name, c.id] } %>
      <%= select :search, :sub_category_id, sub_category_options, {include_blank: ""}, {class: 'select-children'} %>

      <%= f.submit "検索" , class: "btn btn-default" %>
    <% end %>

1つ目のselectである「カテゴリ」は、表示され検索も出来ました。

問題は、2つ目のselectを作る部分です。
参考先では、下のように@itemを使っています。

<% sub_categories = @item.category.try(:sub_categories) || [] %>

今回作りたいのは検索フォームなので、関連するオブジェクトは不要かと思います。
この部分をどう記述すれば良いのでしょうか?

f.category.
や
Item.category.


とすると、違うようで下のエラーになります。

ActionView::Template::Error (undefined method `category' for #<ActionView::Helpers::FormBuilder:0x00007f88584ff8e8>):

それともここは、検索フォームですがコントローラから、

def index
  @item = Item.new
end


して
@itemを渡してあげるべきなのでしょうか?

初心者につき的外れの質問しているかもしれませんが、どうかアドバイス宜しくお願いします。


ご指摘により
以下から不足情報を追加


カテゴリモデル

class Category < ApplicationRecord
  has_many :sub_categories
  has_many :items
  default_scope -> { order(:order_number) }
end


サブカテゴリモデル

class SubCategory < ApplicationRecord
  belongs_to :category
  has_many :items
  default_scope -> { order(:order_number) }
end

アイテムモデル※検索したい対象

class Item < ApplicationRecord

  belongs_to :category
  belongs_to :sub_category


  scope :search, ->(search_params) do
    return if search_params.blank?

    keyword_like(search_params[:keyword])
    .category_id_is(search_params[:category_id])
    .sub_category_id_is(search_params[:sub_category_id])
  end
  scope :keyword_like, -> (keyword) { where('description LIKE ? or title LIKE ?', "%#{keyword}%","%#{keyword}%") if keyword.present? }
  scope :category_id_is, -> (category_id) { where(category_id: category_id) if category_id.present? }
  scope :sub_category_id_is, -> (sub_category_id) { where(sub_category_id: sub_category_id) if sub_category_id.present? }



end

不足情報を追加


コントローラ

class SubCategoriesController < ApplicationController
  def index

    @sub_categories = SubCategory.where(category_id: params[:category_id])    

    respond_to do |format|
      format.html do
      end

      format.js do
        render json: @sub_categories.select(:id, :name)
      end
    end

  end
end

coffeescript

$(document).on 'turbolinks:load', ->
    replaceSelectOptions = ($select, results) ->
      $select.html $('<option>')
      $.each results, ->
        option = $('<option>').val(this.id).text(this.name)
        $select.append(option)

    replaceChildrenOptions = ->
      childrenPath = $(@).find('option:selected').data().childrenPath
      $selectChildren = $(@).closest('form').find('.select-children')
      if childrenPath?
        $.ajax
          url: childrenPath
          dataType: "json"
          success: (results) ->
            replaceSelectOptions($selectChildren, results)
          error: (XMLHttpRequest, textStatus, errorThrown) ->
            console.error("Error occurred in replaceChildrenOptions")
            console.log("XMLHttpRequest: #{XMLHttpRequest.status}")
            console.log("textStatus: #{textStatus}")
            console.log("errorThrown: #{errorThrown}")
      else
        replaceSelectOptions($selectChildren, [])

    $('.select-parent').on
      'change': replaceChildrenOptions

分かった所までを追加


その後分かった所までを追記致します。

エラーログはブラウザ、サーバともに出てませんでした。

ただ、正常な流れは、
親(Category)のセレクトボックスを変更で
スクリプトのreplaceChildrenOptions = ->に飛ぶのに対し、
今回のこの画面は、
replaceChildrenOptions = ->に飛びません。
replaceChildrenOptions = ->の真下にalertで確認しました。

ここからまったく分かりません・・・。


htmlを追加


出力されてるhtmlを追記致します

<select class="select-parent" name="search[category_id]" id="search_category_id">
    <option value=""></option>
    <option data-children-path="/categories/1/sub_categories" value="1">野菜</option>
    <option data-children-path="/categories/2/sub_categories" value="2">果物</option>
    <option data-children-path="/categories/3/sub_categories" value="3">お肉</option>
    <option data-children-path="/categories/4/sub_categories" value="4">魚介</option>
</select>

<select class="select-children" name="search[sub_category_id]" id="search_sub_category_id">
    <option value=""></option>
    <option value="1">キャベツ</option>
    <option value="2">人参</option>
    <option value="3">玉ねぎ</option>
    <option value="4">ブロッコリー</option>
    <option value="5">もやし</option>
    <option value="6">レタス</option>
    <option value="7">トマト</option>
</select>

以下は登録画面のhtmlです。
こちらでも同じセレクトボックス連動を使用しており、こちらは正常に動作済みです。

<select class="select-parent" name="item[category_id]" id="item_category_id">
    <option value="">選択して下さい</option>
    <option data-children-path="/categories/1/sub_categories" value="1">野菜</option>
    <option data-children-path="/categories/2/sub_categories" value="2">果物</option>
    <option data-children-path="/categories/3/sub_categories" value="3">お肉</option>
    <option data-children-path="/categories/4/sub_categories" value="4">魚介</option>
</select>

<select class="select-children" name="item[sub_category_id]" id="item_sub_category_id">
    <option value="">選択して下さい</option>
</select>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • winterboum

    2020/07/05 13:18

    カテゴリーとサブカテゴリの関係がわかる様にしてください
    同じモデルなのか違うモデルなのかもわからないし

    キャンセル

  • pecchan

    2020/07/05 13:20

    記載不足すみません、失礼しました。
    追記致します。

    キャンセル

回答 1

checkベストアンサー

+1

sub_categories = @item.category.try(:sub_categories) || []


sub_categories = Category.first.sub_categories || []


にしてみたら、どうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/07 13:25

    元々ご提示いただいた、
    sub_categories = Category.first.sub_categories || []
    で紐づくデータは表示できてますので解決とさせていただきます。

    モーダルウインドウになると駄目な件は、未解決ですが新たに質問を立てさせていただこうと思います。

    この度はお付き合いいただき有難う御座いました。

    キャンセル

  • 2020/07/07 15:42

    そうでしたか。

    参考までに、、、
    スクリプトがDOMの読み込みができるのは、HTMLに表現されているもののみです。
    pecchanさんのおっしゃってることが、正しいとすれば、
    チェンジイベントを登録しているタイミングでは、まだモーダルのDOMができていないかもしれません。
    デバッグして確かめてみるといいと思います。

    CSSフレームワークを利用しているのであれば、フレームワーク側にそういった場合の回避方法がある可能性があるので、確認してみるといいかもしれません。

    キャンセル

  • 2020/07/07 16:22

    有難う御座います。

    「検証」で確認できたので、DOM生成済みと認識してました。

    CSSフレームワークはbootstrapを使用してます。

    キャンセル

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

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る