[Rails]다계층 카테고리에서 상품을 검색·일람 표시하는 기능

13990 단어 ancestry루비Rails

개요



아래 이미지와 같이 선택한 카테고리에 속하는 상품을 나열하는 기능입니다.
카테고리는 다층으로 되어 있어, 아래의 계층에 갈수록 좁은 검색을 할 수 있게 됩니다.
카테고리는 gem의 ancestry를 사용하여 작성하고 있습니다.


전제



· ancestry를 사용하여 카테고리 테이블을 작성하고 있습니다.
· 카테고리 : 상품 = 1 : 많은 관계가 있습니다.
・상품 모델의 category_id에는, 최하층의 카테고리 id가 등록되어 있다.

이 기사의 앱은 3 계층 범주를 사용합니다.
또, 이 기사내에서는 맨 위의 카테고리를 「부모 카테고리」, 그 아래의 계층을 「아이 카테고리」,
그 또한 아래를 "손자 카테고리"라고 표현하고 있습니다.

참고 기사



ancestry의 도입 방법에 대해서는 이하의 기사가 참고가 됩니다.
htps : // m / tq_17 / ms / 120256209993fb05
htps : // m / pdm21 / ms / f0055b3190 a f790f1c0

구현



카테고리 목록 페이지



시작하기 전에 모든 카테고리를 표시하는 목록 페이지를 만듭니다.
categories 컨트롤러의 index 액션을 사용합니다.


index 액션 정의



app/controllers/categories_controller.rb
def index
  @parents = Category.where(ancestry: nil)
end

상위 카테고리의 ancestry 열은 nil이므로 위의 설명에서 상위 카테고리를 얻을 수 있습니다.

뷰 생성



app/views/categories/index.html.haml
%h1 カテゴリー一覧
%ul.categories
  - @parents.each do |parent|
    %li.parents= link_to "#{parent.name}", category_path(parent)

    %ul.categories__children
      - parent.children.each do |child|
        %li.childern= link_to "#{child.name}", category_path(child)

        %ul.categories__grandchildren
          - child.children.each do |grandchild|
            %li= link_to "#{grandchild.name}", category_path(grandchild)

이제 모든 카테고리를 나열 할 수 있습니다.
각각의 카테고리명은, 후술하는 카테고리별 상품 일람 페이지에 링크하고 있습니다.

카테고리별 상품 일람 페이지



그런 다음 선택한 카테고리에 속한 제품을 나열하는 페이지를 만듭니다.
categories 컨트롤러의 show 액션을 사용합니다.

show 액션 정의



app/controllers/categories_controller.rb
before_action :set_category, only: :show

def show
  @items = @category.set_items
  @items = @items.where(buyer_id: nil).order("created_at DESC").page(params[:page]).per(9)
end

private
def set_category
  @category = Category.find(params[:id])
end

후술하는 모델 메소드 set_items 에 의해, 카테고리내의 상품을 취득합니다.

모델 메소드 정의



app/models/category.rb
has_many :items
has_ancestry

def set_items
  # 親カテゴリーの場合
  if self.root?
    start_id = self.indirects.first.id
    end_id = self.indirects.last.id
    items = Item.where(category_id: start_id..end_id)
    return items

    # 子カテゴリーの場合
  elsif self.has_children?
    start_id = self.children.first.id
    end_id = self.children.last.id
    items = Item.where(category_id: start_id..end_id)
    return items

    # 孫カテゴリーの場合
  else
    return self.items
  end
end

상품의 category_id에는 손자 카테고리의 id가 등록되어 있습니다.
따라서 단순히 @items = @category.items 라고 기술하는 것만으로는 @category 가 손자인 경우 밖에 상품 정보를 취득할 수 없습니다.
따라서 위와 같이 카테고리가 부모 or 자식 or 손자 중 어느 것에 해당하는지에 조건 분기합니다.
카테고리가 부모 or 아이의 경우는, 자신이 가지는 손자 카테고리의 id 범위를 지정해 상품을 취득하고 있습니다.

root?나 indirects 등, ancestry 독자적인 메소드를 사용할 때는 이하의 기사가 참고가 됩니다.
h tps:// 퀵했다. 소 m/루비 st_소타/있어 MS/49383 아 7f60C42141871

뷰 생성



app/views/categories/show.html.haml
.products-container
  .products-index
    .title
      = "#{@category.name}の商品一覧"
      .title__border
    - if @items
      %ul.lists
        = render "items/item", items: @items
    = paginate @items

모든 상품 일람 페이지에서 사용하고 있는 부분 템플릿을 공유.
@items 의 값에 따라 표시 내용을 변경합니다.

다른 카테고리에 대한 링크 만들기



마지막으로 다음과 같이 다른 카테고리에 대한 링크를 추가하여 제품을 더 쉽게 찾을 수 있습니다.

표시 카테고리가 상위 or 아이의 경우, 1 계층하의 카테고리에의 링크를,
손자의 경우 동일한 하위 범주에 속한 손자 범주에 대한 링크를 표시합니다.

app/controllers/categories_controller.rb
def set_category
  @category = Category.find(params[:id])
  # 追記---------------------------------
  if @category.has_children?
    @category_links = @category.children
  else
    @category_links = @category.siblings
  end
  # -------------------------------------
end

app/views/categories/show.html.haml

// 追記--------------------------------------------------
.category_wrapper
  .category_links
    - @category_links.each do |category|
      = link_to category.name, category_path(category)
// -----------------------------------------------------
.products-container
  .products-index
    .title
      = "#{@category.name}の商品一覧"
      .title__border
    - if @items
      %ul.lists
        = render "items/item", items: @items
    = paginate @items

그리고는 적절히 CSS를 정돈하면 완성됩니다.

마지막으로



이상으로 다계층 카테고리에서 상품을 검색하는 기능은 완성입니다.
여기까지 읽어 주셔서 감사합니다.

좋은 웹페이지 즐겨찾기