I want to search Rails for columns in related tables.

Asked 2 years ago, Updated 2 years ago, 38 views

I'd like to create a search function on Rails, but I'm into it, so I'd like you to teach me.
I would like to create a search form where Rails has models called Article and Item, and there is a URL column in the item, and I can search for partial matches based on that URL.
Currently, @items=Item.where("url like%#{params[:search]}") .uniq allows you to search by like based on the parameters (:search) entered in the form.
It's done so far, but I'd like to pull the record of the article tied to the item from here, but I can't think of a way.The article and item are linked to the item with the article_id associated with the article id.

ruby-on-rails ruby

2022-09-30 16:20

3 Answers

You can use joins to search for related tables.

However, embedding parameters directly into a string can cause SQL injection, which is very dangerous.
Try binding using ? as follows:

articles=Article.joins(:items).where("items.url LIKE?", "%#{params[:search]}").uniq

Learn more about SQL injection here.

Rails Security Guide|Rails Guide

P.S.

By the way, if you understand what SQL injection is, you will be able to understand the fun of the following four-frame manga.

xkcd:Exploits of a Mom

Enter a description of the image here

translation

Add

For Rails 4.2, you can use the method sanitize_sql_like.
This is how to use it.

class Article <ActiveRecord::Base
  has_many —Items
  scope:keyword_search, ->(keyword){
    joins(:items).where("items.url LIKE?", "%" + sanitize_sql_like(keyword))
  }
end

# controller
articles=Article.keyword_search (params[:search])

In LIKE searches, '%' or '_' have a special meaning.
You can use sanitize_sql_like to escape these strings.

Example: SQL

When the keyword '100%' is entered
SELECT...WHERE(items.url LIKE '%100\%')


2022-09-30 16:20

First,

where("url like%#{params[:search]}")

There are many bad things about , so I'll fix it.First of all, the search string is not literal at the root, so the original code must be

where("url like'%#{params[:search]}'")

I guess so. So this is

  • SQL injection available
  • Treats as a wildcard for LIKE when there are % or _ in the search key

There is a pretty serious problem, so I'll rewrite it using Arel.

search_key="%"+params[:search].gsub(/[%_]/, "\\0")
Item.where(Item.arel_table[:url].matches(search_key, "\\"))

This will eliminate the above problem.However, if Rails are out of date, #matches may not support the second argument.In that case,

Item.where(%q!"items.url"LIKE?ESCAPE'\\'!,search_key)

muddy the tea in .You should modify the column name table because duplicate column names can result in errors if you use joins.

Then, which one do you want to search for?

Add the belongs_to:article relationship to the item.

@item=Item.where(...)
@items[0].article

See the article in

Add the has_many:items relationship to the Article.

Article.joins(:items).where(...).uniq

The original code #uniq didn't make much sense, but if you don't add #uniq, article will overlap if there are multiple items with the same article_id.


2022-09-30 16:20

Assume that has_many:items is defined in the model as follows

class Article <ActiveRecord::Base
  has_many —Items
end

class Item<ActiveRecord::Base
end

Then you can do it by using joins

articles=Article.joins(:items).where("items.url like'%#{params[:search]}}').uniq


2022-09-30 16:20

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.