簡體   English   中英

Rails API - 如何構建查詢來過濾字符串數組?

[英]Rails API - How to build a query to filter an array of strings?

我需要制作一個簡單的 API 並添加以下功能:

GET /tools?tag=node (EXAMPLE)

工具模型具有以下列:
* 標題(字符串)
* 描述(文本)
* 鏈接(字符串)
* 標簽(字符串數組)

我需要能夠從 localhost 搜索所有帶有標簽的工具。 我嘗試使用Rack Reducer,但此方法僅適用於字符串或文本類型。

我知道這應該很簡單,但我是 Rails 新手。

謝謝你的幫助。

架構.rb:

ActiveRecord::Schema.define(version: 2019_11_29_170156) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "tools", force: :cascade do |t|
    t.string "title"
    t.string "link"
    t.text "description"
    t.text "tags", default: [], array: true
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

tools_controller.rb

class ToolsController < ApplicationController

  ToolReducer = Rack::Reducer.new(
    Tool.all,
    # ->(tags:) { select { |item| item[:tags].match(/#{tags}/i) } }
    ->(tags:) { where("tags @> ?", "%#{tags}%") }
  )

  def index
    # @tools = Tool.where(query_params)
    @tools = ToolReducer.apply(params)
    # @tools = Tool.all
    render json: @tools
  end

  def new
    @tool = Tool.new
  end

  def show
    @tool = Tool.find(params[:id])
    render json: @tool
  end

  def create
    @tool = Tool.new(tool_params)
    if @tool.save
      render json: @tool
      redirect_to @tool
    end
  end

  def destroy
    @tool = Tool.find(params[:id])
    @tool.destroy
  end

  private

    def tool_params
      params.require(:tool).permit(:title, :link, :description, :tags)
    end
end

pg_search gem 非常適合在 Postgres 數據庫中進行搜索。

但是,就您而言,我認為您的應用程序設計不佳。

不是在“工具”模型的字段中存儲標簽,您應該創建一個名為“標簽”的新模型,並在標簽模型和工具模型之間創建 has_and_belongs_to_many 關系。

查找和刪除標簽會容易得多。

(此外,任何與機架相關的內容都會深入到您的應用程序中,它是中間件。我不知道 Rack::reducer,但我確定您不需要它)

如果您首先正確地設置了數據庫,那么除了 Rails 之外,無需任何其他東西即可完成這項任務。

您想創建一個規范化的標簽表和一個鏈接工具和標簽的連接表:

class Tool < ApplicationRecord
  has_many :taggings
  has_many :tags, through: :taggings
end

# rails g model tag name:string:uniq
class Tag < ApplicationRecord
  validates_uniqueness_of :name
  has_many :taggings
  has_many :tools, through: :taggings
end

# rails g model tagging tool:belongs_to tag:belongs_to
class Tagging < ApplicationRecord
  belongs_to :tool
  belongs_to :tag
end

這使您可以通過加入標簽模型來過濾工具:

# has at least one of the tags
Tool.joins(:tags)
    .where(tags: { name: ["foo", "bar", "baz"] })

# has all the tags
Tool.joins(:tags)
    .where(tags: { name: ["foo", "bar", "baz"] })
    .group('tools.id')
    .having('count(*) = 3')

您可以通過以[]結束參數名稱來在 Rack 中傳遞數組:

Started GET "/tools?tags[]=foo&tags[]=bar" for ::1 at 2019-12-02 23:49:37 +0100
   (0.4ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by ToolsController#index as HTML
  Parameters: {"tags"=>["foo", "bar"]}

這是當您創建選擇和復選框時 Rails 表單助手如何完成的。 您還可以使用逗號分隔列表之類的內容並手動拆分參數。

def index
  @tools = Tool.all
  if params[:tags].any?
    @tools = @tools.joins(:tags).where(tags: { name: params[:tags] })
  end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM