super-appy / itsumono_obento

今ある材料で作れるレシピを提案するAIレシピとお弁当カレンダー機能で、お弁当作りをサポートするアプリ
6 stars 0 forks source link

レシピ一覧での検索機能 #27

Closed super-appy closed 10 months ago

super-appy commented 11 months ago

ransackにて検索機能を実装 デフォルトは新着順ですべて表示

プルダウンにて入力

並べ替えは以下の通り

super-appy commented 10 months ago

食材での検索について 食材のプルダウンで指定した食材のidが「taste_tag_time」に含まれているか tagは0埋めした6桁の数字の組み合わせ

難しく考えなくてもtag_idsの配列にその食材のidが含まれているかで判断でいける

super-appy commented 10 months ago

改めて保存されているタグを見てみると、手動で登録の場合に想定している挙動になっていない模様。 編集時にも変更できるように修正し、APIの方も0埋めされるように修正。

super-appy commented 10 months ago

ストロングパラメーター受け取ったあとに加工したかったのでassign_attributesを使った!

  def update
    @recipe = current_user.recipes.find(params[:id])
    @recipe.assign_attributes(recipe_params)
    @recipe.taste_tag_time = make_taste_tag_time(@recipe, @recipe.tag_ids)
    if @recipe.save
      redirect_to recipe_path(@recipe), success: 'レシピ編集できた!'
    else
      render :edit, status: :unprocessable_entity
    end
  end
super-appy commented 10 months ago

以下で希望通りの見た目にはなるけど検索が機能しない

index.html.erb

      <% @tags_by_category.each do |category, tags| %>
        <div class="p-2 w-full md:w-1/3 px-2">
          <div class="relative">
            <%= f.label :tag_ids_eq, category.to_s.humanize, class: "leading-7 text-sm text-gray-600" %>
            <%= f.select :tag_ids_eq, tags.map { |tag| [tag.name, tag.id] }, { include_blank: true }, { multiple: true, class: "w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none py-2 px-3 leading-6 transition-colors duration-200 ease-in-out" } %>
          </div>
        </div>
      <% end %>

recipes_controller

  def index
    @tags_by_category = Tag.all.group_by(&:category)
    @q = Recipe.ransack(params[:q])
    @recipes = @q.result(distinct: true)
  end
super-appy commented 10 months ago

検索ボタンが押せてない!

super-appy commented 10 months ago

<%= f.submit %>を以下に変えたらできた!!...なぜ?

        <%= f.button type: 'submit', class: "inline-block text-white bg-gray-400 border-0 py-2 px-5 focus:outline-none hover:bg-blue-400 rounded-full text-lg mx-2" do %>
          <i class="fa-solid fa-magnifying-glass"> 登録</i>
        <% end %>
super-appy commented 10 months ago

カテゴリ別にするとOR検索になるので、カテゴリを分けないことにしてみる。 ただ、探しにくいので以下の対策を検討

  1. カテゴリ選択→食材名選択
  2. カテゴリ別で縦一列になっている表を出してその中からタグを選択してもらう

本リリースまでに実装したい。 以下、は1の場合のGPTの回答。参考までに


選択されたカテゴリに応じてTagname一覧を表示するプルダウンを作成するには、JavaScript(またはAjax)を使用して動的にセカンドプルダウンを更新する必要があります。ここでは、RailsとJavaScriptを使用した基本的な実装方法を説明します。

まず、カテゴリを選択するプルダウンを作成します。次に、JavaScriptを使用して、カテゴリが変更されたときにタグの一覧を更新する機能を追加します。

ステップ1: カテゴリ選択のプルダウンを作成

<%= search_form_for @q do |f| %>
  <div class="p-2 w-full md:w-1/3 px-2">
    <div class="relative">
      <%= f.label :category_id_eq, 'カテゴリ', class: "leading-7 text-sm text-gray-600" %>
      <%= f.collection_select :category_id_eq, Category.all, :id, :name, { include_blank: true }, { class: "w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none py-2 px-3 leading-6 transition-colors duration-200 ease-in-out", id: "category-select" } %>
    </div>
  </div>

  <!-- タグのプルダウン(初期状態では空) -->
  <div class="p-2 w-full md:w-1/3 px-2" id="tags-container">
  </div>

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

ステップ2: JavaScriptで動的にタグの一覧を更新

JavaScriptを使って、カテゴリが変更されたときにタグのプルダウンを更新します。これにはAjaxを使い、サーバーからタグのデータを取得する方法が一般的です。

document.addEventListener('DOMContentLoaded', function () {
  const categorySelect = document.getElementById('category-select');
  const tagsContainer = document.getElementById('tags-container');

  categorySelect.addEventListener('change', function () {
    const categoryId = this.value;

    // Ajaxリクエストを送信して、カテゴリに応じたタグを取得
    fetch(`/tags_for_category/${categoryId}`)
      .then(response => response.json())
      .then(data => {
        // タグのプルダウンを更新
        let optionsHtml = data.tags.map(tag => 
          `<option value="${tag.id}">${tag.name}</option>`
        ).join('');

        tagsContainer.innerHTML = `
          <select name="q[tags_id_in]" class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none py-2 px-3 leading-6 transition-colors duration-200 ease-in-out">
            <option value="">タグを選択</option>
            ${optionsHtml}
          </select>
        `;
      })
      .catch(error => console.error('Error:', error));
  });
});

ステップ3: サーバーサイドでタグのデータを提供

サーバーサイドでは、指定されたカテゴリに応じたタグのデータをJSON形式で返すアクションを作成します。

# routes.rb
get '/tags_for_category/:category_id', to: 'tags#tags_for_category'

# tags_controller.rb
def tags_for_category
  category = Category.find(params[:category_id])
  tags = category.tags
  render json: { tags: tags.map { |tag| { id: tag.id, name: tag.name } } }
end

この実装では、カテゴリが変更されると、選択されたカテゴリに基づいてタグの一覧がプルダウンに表示されます。ただし、実際のアプリケーションの構造に応じて、コードの詳細を調整する必

要があります。また、セキュリティの観点からAjaxリクエストを適切に処理することも重要です。