Rails API-如何构建查询以过滤字符串数组?

问题描述 投票:0回答:1

我需要制作一个简单的API并添加以下功能:

GET /tools?tag=node (EXAMPLE)

工具模型包含以下列:*标题(字符串)*说明(文本)*链接(字符串)*标签(字符串数组)

我需要能够从本地主机搜索其中带有某些标记的所有工具。我尝试使用Rack Reducer,但此方法仅适用于字符串或文本类型。

我知道这应该很简单,但是我是Rails的新手。

感谢您的帮助。

schema.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
ruby-on-rails postgresql api ruby-on-rails-5
1个回答
0
投票

如果您首先正确地正确设置数据库,那么除了Rails之外,这是一件非常琐碎的任务。

您想创建一个标准化标签表和一个链接工具和标签的联接表:

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

class Tag
  validates_uniqueness_of :name
  has_many :taggings
  has_many :tools, through: :taggings
end

class Tagging
  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(: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
© www.soinside.com 2019 - 2024. All rights reserved.