2016-08-26 3 views
0

Я использую API Rails 5 для создания приложения для извлечения данных. Я хочу использовать несколько параметров GET для извлечения данных.Управление несколькими параметрами GET в Rails 5 API

Пример GET Формат запроса

/users?company=Samsung&position=Engineer 

Controller Код для одного параметра: -

def index 
client = User.where("company = ?", params[:company]) 
render json: client 
end 

Controller Код для нескольких параметров: -

def index 
client = User.where("company = ?", params[:company]).where("position = ?", params[:position]) 
render json: client 
end 

Также есть много параметров, которые могут/не могут быть включены в запросе GET.

То, что я хочу

Если пользователь не указал какого-либо параметра, он должен показать всем пользователям. Если указано только несколько параметров, необходимо искать только эти параметры.

Что происходит

Если пользователь указывает только параметр положения в запросе GET, Rails не может справиться с этим & показывает пустой JSON, поскольку нет никакого правила, указанный для него.

Обратите внимание, что существует множество параметров, и невозможно создать правило для каждой комбинации параметров.

ответ

2

Основная проблема с вашим решением заключается в том, что он заставляет каждого из них выполнять в свою очередь. Это означает, что если параметр компании равен nil, вы получаете пустое отношение, и все операторы where после этого возвращают пустое отношение. Вы должны условно фильтровать только при условии предоставления параметров.

То, что вы пытаетесь сделать, лучше всего сделать внутри объекта запроса/поиска или фильтрации (запрос принимает параметры и возвращает набор результатов, фильтр принимает уже сгенерированный набор и отфильтровывает его). Мне нравится определять их в app/services/, хотя некоторые люди помещают их в app/queries.

Существуют некоторые несоответствия в вашем методе, однако конечная точка индекса должна возвращать список объектов. Даже если вы надеетесь вернуть один вариант, вы должны ожидать, что его может быть несколько. Предположим, мы исправим конечную точку вашего индекса и используем объект фильтра.

# app/controllers/users_controller.rb 
def index 
    users = User.where(1=1) 
    users = Users::Filter.call(users, params) 
    render json: users 
end 

Вы заметите, я использую User.where(1=1), это потому, что я использовать для работы с рельсами 3, который возвращает массив вместо отношения, если вы используете User.all.

# /app/services/users/filter.rb 
class Users::Filter 
    def self.call(resources, options) 
    new(users, options).filter 
    end 

    private 

    attr_reader :resources, :options 

    def initialize(resources, options) 
    @resources = resources 
    @options = options 
    end 

    def filter 
    if options[:company] 
     @resources = resources.where(company: options[:company]) 
    end 

    if options[:position] 
     @resources = resources.where(position: options[:position]) 
    end 

    resources 
    end 
end 

Причина я использую call, который затем вызывает частный initialize и filter метод так, что этот класс не используется неправильно. Он имеет единственную точку входа и возвращает результат. Это также позволяет мне разбить свои функции фильтрации на небольшие кусочки размера укуса, которые легко изменить.

Для этого примера я выполнил всю фильтрацию в filter, но вы можете разбить их на методы и даже использовать какое-то умное мета-программирование для вызова имени фильтра, если объект отвечает на него.

EDIT:

Вы можете также рассмотреть вопрос найти драгоценный камень решения, как рыскать [1], который позволяет передавать параметры непосредственно к объекту и искать его. Там есть много разных типов поиска/фильтрации драгоценных камней, чтобы удовлетворить ваши потребности.

[1] https://github.com/activerecord-hackery/ransack

Смежные вопросы