2016-08-26 1 views
0

Ich verwende Rails 5 API, um eine App zum Abrufen von Daten zu erstellen. Ich möchte mehrere GET-Parameter verwenden, um Daten zu extrahieren.Verwalten mehrerer GET-Parameter in Rails 5 API

Beispiel GET Anfrage Format

/users?company=Samsung&position=Engineer 

-Controller-Code für einzelne Parameter: -

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

-Controller-Code für mehrere Parameter: -

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

Ebenso gibt es viele Parameter, die kann/darf nicht in der GET-Anfrage enthalten sein.

Was ich

möchten Wenn ein Benutzer einen beliebigen Parameter nicht angegeben hat, sollte er alle Benutzer angezeigt. Wenn nur wenige Parameter angegeben wurden, sollten nur diese Parameter durchsucht werden.

Was

geschieht Wenn ein Benutzer nur Parameterposition gibt in der GET-Anfrage, Rails kann nicht damit umgehen & zeigt eine leere json, da es keine Regel dafür angegeben ist.

Bitte beachten Sie, dass es viele Parameter gibt und es nicht möglich ist, eine Regel für jede Kombination von Parametern zu schreiben.

Antwort

2

Das grundlegende Problem mit Ihrer Lösung ist, dass sie jede Ausführung nacheinander erzwingt. Das heißt, wenn der Firmenparameter nil ist, erhalten Sie eine leere Relation und alle where-Anweisungen danach werden eine leere Relation zurückgeben. Sie müssen nur bedingt filtern, wenn die Parameter bereitgestellt werden.

Was Sie zu tun versuchen, ist am besten innerhalb eines Abfrage-/Such- oder Filterobjekts erledigt (Abfrage übernimmt Parameter und gibt eine Ergebnismenge zurück, Filter nimmt ein bereits erzeugtes Set und filtert es herunter). Ich mag es, diese in app/services/ zu definieren, obwohl einige Leute sie in app/queries setzen.

In Ihrer Methode gibt es einige Inkonsistenzen. Ein Indexendpunkt sollte jedoch eine Liste von Objekten zurückgeben. Selbst wenn Sie hoffen, eine einzige Option zu bekommen, sollten Sie erwarten, dass es mehrere geben könnte. Nehmen wir an, wir reparieren Ihren Indexendpunkt und verwenden ein Filterobjekt.

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

Sie werde ich User.where(1=1) verwenden bemerken, ist dies, weil ich den Einsatz für den Umgang mit Schienen 3, die anstelle einer Beziehung ein Array zurückgibt bin, wenn Sie User.all verwenden.

# /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 

Der Grund, warum ich call verwenden, die dann die private Methode initialize und filter ruft ist so, dass diese Klasse nicht falsch verwendet wird. Es hat einen einzigen Eintrittspunkt und gibt die Ergebnismenge zurück. Dies ermöglicht mir auch, meine Filterfunktionen in kleine, leicht zu wechselnde Stücke zu verwandeln.

Für dieses Beispiel habe ich die Filterung in filter durchgeführt, aber Sie könnten diese in Methoden ausbrechen und sogar eine clevere Meta-Programmierung verwenden, um den Filternamen aufzurufen, wenn das Objekt darauf reagiert.

EDIT:

Sie auch ein Juwel Lösung zu finden, wie ransack betrachten kann [1], die Sie Parameter direkt auf das Objekt passieren lässt und suchen sie. Es gibt viele verschiedene Arten von Such-/Filter-Edelsteinen, um Ihre Bedürfnisse zu erfüllen.

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