[RUBY] [Rails] Implemented a pull-down search function for Active Hash data


I will summarize how to implement the pull-down search function in ActiveHash data. I used a gem called ransack to implement the function.

ransack is a gem that allows for complex searches. This function is a simple search, so you may be able to do it without using ransack. This will be an issue for the future.


--ActiveHash's GitHub page
https://github.com/zilkey/active_hash -[Rails] Let's make a pseudo model using active_hash

--ransack's GitHub page
https://github.com/activerecord-hackery/ransack --73 recipes to easily create a search form with Ransack

Complete image

This time, I will explain how to display a list of photos in that category after selecting a category using the photo posting app as the subject.

Image from Gyazo

Development environment

Implementation flow

  1. Install gem ransack
  2. Set up routing
  3. Set the action on the controller
  4. Create a search box
  5. Create a search result view

This code

The code is omitted except for the necessary parts (CSS, etc.). The method of creating a pseudo model using ActiveHash is also omitted. We will proceed on the assumption that the pseudo model has been created. Please see the reference page etc. for the creation method.

1. Install gem ransack


#Added at the bottom of the file
gem 'ransack'


% bundle install

2. Set up routing


get '/photo/category', to: "photos#category"

Set the category action on the photos controller. Causes the category search results page to be displayed when the category action is executed.

3. Set the action on the controller


 before_action :search_category_photo, only: [:index, :category, :hashtag, :search]



  def search_category_photo
    @q = Photo.ransack(params[:q])

Create a search_category_photo method in the private method. Doing this will create a search object called @ q = Photo.ransack (params [: q]).

This time, I stored the search result box in the header. As a result, the search result box is displayed not only on the category search result screen (: category) but also on the top screen (: index), hashtag search result screen (: hashtag), and caption search result screen (: search). I will. Therefore, make sure that before_action executes the search_category_photo method when each screen is loaded. Without this I got an error. I had a hard time solving this ...


  def category
    @photos = @q.result
    category_id = params[:q][:category_id_eq]
    @category = Category.find_by(id: category_id)

Enter @ photos = @ q.result in the category method to get the search results.

Search parameters are stored in params [: q].

For example, when the category of id: 5 of ActiveHash pseudo model was selected from the pull-down menu, the following items were stored in params [: q].


[1] pry(#<PhotosController>)> params[:q]
=> <ActionController::Parameters {"category_id_eq"=>"5"} permitted: false>

In order to display the category name selected in the search result view, I got the category_id ("5" in this example) in params [: q] as category_id = params [: q]: category_id_eq]. Using that category_id, I got the selected category name as @category = Category.find_by (id: category_id).

4. Create a search box

The following is the ActiveHash pseudo model of the category created this time.


class Category < ActiveHash::Base
  self.data = [
    { id: 0, name: '--' },
    { id: 1, name: 'dog' },
    { id: 2, name: 'Cat' },
    { id: 3, name: 'bird' },
    { id: 4, name: 'fish' },
    { id: 5, name: 'reptiles' },
    { id: 6, name: 'Amphibians' },
    { id: 7, name: 'insect' },
    { id: 8, name: 'Other' }
  include ActiveHash::Associations
  has_many :photos


<%= search_form_for @q, url: photo_category_path do |f| %>
    <%= f.collection_select :category_id_eq, Category.where.not(id: 0), :id, :name, include_blank: "Category search" %>
    <%= f.submit 'Search' %>
<% end %>

Create a search form with the helper method search_form_for method of ransack. The search object @ q is passed as an argument (see:" 3. Set the action on the controller "). The pathname of the url is the pathname of the category action (checked in rails routes). Create a pull-down category selection box with the helper method collection_select method.

** Note) You may not have a good understanding of the .collection_select method. Below, I would like you to point out any mistakes. ** **

<% = f.collection_select ①: category_id_eq, ②Category.where.not (id: 0), ③: id, ④: name, ⑤include_blank:" Category search "%>

① Column name + ransack search method

The column name is : category_id to search by: category_id in the photos table, and the search method is -eq to get the photos with the same id as the selected category. -eq is a method that searches according to the conditions (equal image).

(2) Array data used in the pull-down list

Since the data of the Category model of ActiveHash is used, the model name Category is used as an argument. In .where.not (id: 0), id: 0 is not displayed. Instead, in ⑤, include_blank:" category search " is set, and when not selected, the word "category search" is displayed in the search box. I tried to be done.

③ Column name used for search

Since the value of the id column of the Category model is used for the search, it is set to : id.

④ Column name displayed in the pull-down menu

I chose : name because I want to display the value of: name instead of : id of the Category model in the pull-down menu.

5. Create a search result view

Describe the contents of the category search result page in category.html.erb.


#Only the parts necessary for implementation are described.
<h2>Category<%= @category.name %></h2>
    <% @photos.each do |photo| %>
          <%= image_tag photo.image if photo.image.attached? %>
    <% end %>

@category and @photos are the instance variables set by the category method of the photos controller above (see "3. Set the action on the controller").

With @ category.name, I got the category name selected from the pull-down list and displayed it in the search result view.

Since the photos of the category selected from the pull-down list are stored in @ photos, I took them out one by one with the .each method and displayed them in the view.

in conclusion

It was difficult to input the arguments of the .collection_select method, and I came up with the correct answer through many trials and errors. I hope you found this article helpful.

Since this is a beginner, please point out any mistakes or improvements.

Recommended Posts

[Rails] Implemented a pull-down search function for Active Hash data
[For Rails beginners] Implemented multiple search function without Gem
Add a search function in Rails.
Implement a refined search function for multiple models without Rails5 gem.
Let's make a search function with Rails (ransack)
[Rails] About active hash
[Rails] Implement search function
[Rails] Introducing Active Hash
[Rails] Implemented hashtag function
Rails search function implementation
Implemented pull-down in the original app with Active Hash
[Rails 6.0] I implemented a tag search function (a function to narrow down by tags) [no gem]
Search function using [rails] ransack
[Rails 6] Implementation of search function
[Rails] Creating a search box
[Rails] (Supplement) Implemented follow function
I made a reply function for the Rails Tutorial extension (Part 1)
I made a reply function for the Rails Tutorial extension (Part 5):
Implemented mail sending function with rails
I made a reply function for Rails Tutorial extension (Part 2): Change model
[Ruby on Rails] Search function (not selected)
[Rails withdrawal] Create a simple withdrawal function with rails
[Rails] Manage data for each seed file
[Rails] Get standard input for multi-line data
Rails [For beginners] Implementation of comment function
Make a login function with Rails anyway
Implemented follow function in Rails (Ajax communication)
[Rails] Method summary for conversion / verification / search
[Rails 6] Asynchronous (Ajax) follow function is implemented
[Rails] Set validation for the search function using Rakuten API (from the implementation of Rakuten API)