window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster już istnieje') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Proste filtry w Rails API - The Codest
The Codest
  • O nas
  • Nasze Usługi
    • Software Development
      • Frontend Development
      • Backend Development
    • Zespoły IT
      • Programiści frontendowi
      • Backend Dev
      • Inżynierowie danych
      • Inżynierowie rozwiązań chmurowych
      • Inżynierowie QA
      • Inne
    • Konsultacje IT
      • Audyt i doradztwo
  • Branże
    • Fintech i bankowość
    • E-commerce
    • Adtech
    • Healthtech
    • Produkcja
    • Logistyka
    • Motoryzacja
    • IOT
  • Wartość dla
    • CEO
    • CTO
    • Delivery Managera
  • Nasz zespół
  • Case Studies
  • Nasze Know How
    • Blog
    • Meetups
    • Webinary
    • Raporty
Kariera Skontaktuj się z nami
  • O nas
  • Nasze Usługi
    • Software Development
      • Frontend Development
      • Backend Development
    • Zespoły IT
      • Programiści frontendowi
      • Backend Dev
      • Inżynierowie danych
      • Inżynierowie rozwiązań chmurowych
      • Inżynierowie QA
      • Inne
    • Konsultacje IT
      • Audyt i doradztwo
  • Wartość dla
    • CEO
    • CTO
    • Delivery Managera
  • Nasz zespół
  • Case Studies
  • Nasze Know How
    • Blog
    • Meetups
    • Webinary
    • Raporty
Kariera Skontaktuj się z nami
Strzałka w tył WSTECZ
2022-02-23
Software Development

Proste filtry w Rails API

The Codest

Krzysztof Buszewicz

Senior Software Engineer

Czy jesteś zły za każdym razem, gdy widzisz mutowanie zmiennych instancji w kontrolerze rails w celu filtrowania danych? Ten artykuł jest dla Ciebie 🙂

Filtry

Prawdopodobnie widziałeś to już wcześniej:

# app/controllers/api/v1/things_controller.rb

moduł API
  moduł V1
    class ThingsController < BaseController
      def index
        @things = Thing.all
        @things = @things.where(size: params[:size]) if params[:size]
        @things = @things.where('name ILIKE ?', "%#{params[:name_contains]}%") if params[:name_contains]

        render json: @things
      end
    end
  end
koniec

Dlaczego uważam to za złe kod? Ponieważ po prostu sprawia, że nasz kontroler jest gruby.
IMHO powinniśmy wyodrębnić jak najwięcej logiki z kontrolerów i użyć powiązanego z celem
narzędzi lub usług. W tym przypadku zaimplementujemy ogólny filtr, który będziemy w stanie
do wykorzystania na wielu kontrolerach.

Ale poczekajmy, najpierw przeanalizujmy obecny kod. Może być zły, ale działa.
Mamy pewien początkowy zakres (Thing.all), a następnie ograniczają go, jeśli użytkownik przeszedł
powiązany parametr. Dla każdego filtra sprawdzamy, czy parametr został przekazany, a jeśli tak, to czy został przekazany,
stosujemy filtr. Drugą rzeczą jest to, że nie musimy używać ivar, możemy użyć
zwykłe stare zmienne lokalne.

Ok, w takim razie. Czy nie moglibyśmy użyć jakiegoś obiektu usługi do zmutowania początkowego zakresu?
Wykonanie może wyglądać następująco:

# app/controllers/api/v1/things_controller.rb

moduł API
  moduł V1
    class ThingsController < BaseController
      def index
        scope = Thing.all
        things = Things::IndexFilter.new.call(scope, params)

        renderowanie json: things
      end
    end
  end
koniec

Teraz wygląda to znacznie lepiej, ale oczywiście musimy jeszcze zaimplementować filtr.
Należy pamiętać, że sygnatura wywołania będzie taka sama dla wszystkich zasobów, więc możemy mieć
jakąś ogólną klasę do tego zadania.

# app/services/generic/index_filter.rb

moduł Generic
  class IndexFilter
    EMPTY_HASH = {}.freeze

    def self.filters
      EMPTY_HASH
    end

    def call(scope, params)
      apply_filters!(self.class.filters.keys, scope, params)
    end

    private

    def apply_filters!(filter_keys, scope, params)
      filter_keys.inject(scope.dup) do |current_scope, filter_key|
        apply_filter!(filter_key, current_scope, params)
      end
    end

    def apply_filter!(filter_key, scope, params)
      filter = fetch_filter(filter_key)
      return scope unless apply_filter?(filter, params)

      filter[:apply].call(scope, params)
    end

    def apply_filter?(filter, params)
      filter[:apply?].call(params)
    end

    def fetch_filter(filter_key)
      self.class.filters.fetch(filter_key) { raise ArgumentError, 'nieznany filtr' }
    end
  end
end

Wydaje się skomplikowane? Nie do końca - cała magia dzieje się w #apply_filters!.
Bierzemy duplikat początkowego zakresu i stosujemy do niego każdy filtr.

Kiedy stosujemy zakres, oznacza to, że mutujemy duplikat naszego początkowego zakresu.
Oczekujemy, że filtry zostaną zaimplementowane jako hash w self.filters metoda
klasy dziecka. Zróbmy to.

# app/services/things/index_filter.rb

moduł Things
  class IndexFilter (params) {
          params[:size].is_a?(String)
        },
        apply: ->(scope, params) {
          scope.where(size: params[:size])
        }
      }.freeze,
      name_contains_filter: {
        apply?: ->(params) {
          params[:name_contains].is_a?(String)
        },
        apply: ->(scope, params) {
          scope.where('name ILIKE ?', "%#{params[:name_contains]}%")
        }
      }.freeze
    }.freeze

    def self.filters
      FILTRY
    end
  end
end

To wszystko! Napisaliśmy więcej kodu, ale proste filtry będą wyglądać tak samo
dla wszystkich zasobów. Wyczyściliśmy kontroler z kodu odpowiedzialnego
filtrowania i udostępnił w tym celu "wyspecjalizowaną" klasę, która jest bardzo
jasna konwencja.

Oferta dla programistów Ruby

Czytaj więcej:

Plusy i minusy tworzenia oprogramowania w Ruby

Szyny i inne środki transportu

Rails Development z TMUX, Vim, Fzf + Ripgrep

Powiązane artykuły

Software Development

Tworzenie przyszłościowych aplikacji internetowych: spostrzeżenia zespołu ekspertów The Codest

Odkryj, w jaki sposób The Codest wyróżnia się w tworzeniu skalowalnych, interaktywnych aplikacji internetowych przy użyciu najnowocześniejszych technologii, zapewniając płynne doświadczenia użytkowników na wszystkich platformach. Dowiedz się, w jaki sposób nasza wiedza napędza transformację cyfrową i biznes...

THEECODEST
Software Development

10 najlepszych firm tworzących oprogramowanie na Łotwie

Dowiedz się więcej o najlepszych łotewskich firmach programistycznych i ich innowacyjnych rozwiązaniach w naszym najnowszym artykule. Odkryj, w jaki sposób ci liderzy technologiczni mogą pomóc w rozwoju Twojej firmy.

thecodest
Rozwiązania dla przedsiębiorstw i scaleupów

Podstawy tworzenia oprogramowania Java: Przewodnik po skutecznym outsourcingu

Zapoznaj się z tym niezbędnym przewodnikiem na temat skutecznego tworzenia oprogramowania Java outsourcing, aby zwiększyć wydajność, uzyskać dostęp do wiedzy specjalistycznej i osiągnąć sukces projektu z The Codest.

thecodest
Software Development

Kompletny przewodnik po outsourcingu w Polsce

Wzrost liczby outsourcing w Polsce jest napędzany przez postęp gospodarczy, edukacyjny i technologiczny, sprzyjający rozwojowi IT i przyjazny klimat dla biznesu.

TheCodest
Rozwiązania dla przedsiębiorstw i scaleupów

Kompletny przewodnik po narzędziach i technikach audytu IT

Audyty IT zapewniają bezpieczne, wydajne i zgodne z przepisami systemy. Dowiedz się więcej o ich znaczeniu, czytając cały artykuł.

The Codest
Jakub Jakubowicz CTO & Współzałożyciel

Subskrybuj naszą bazę wiedzy i bądź na bieżąco!

    O nas

    The Codest - Międzynarodowa firma programistyczna z centrami technologicznymi w Polsce.

    Wielka Brytania - siedziba główna

    • Office 303B, 182-184 High Street North E6 2JA
      Londyn, Anglia

    Polska - lokalne centra technologiczne

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warszawa, Polska

      The Codest

    • Strona główna
    • O nas
    • Nasze Usługi
    • Case Studies
    • Nasze Know How
    • Kariera
    • Słownik

      Nasze Usługi

    • Konsultacje IT
    • Software Development
    • Backend Development
    • Frontend Development
    • Zespoły IT
    • Backend Dev
    • Inżynierowie rozwiązań chmurowych
    • Inżynierowie danych
    • Inne
    • Inżynierowie QA

      Raporty

    • Fakty i mity na temat współpracy z zewnętrznym partnerem programistycznym
    • Z USA do Europy: Dlaczego amerykańskie startupy decydują się na relokację do Europy?
    • Porównanie centrów rozwoju Tech Offshore: Tech Offshore Europa (Polska), ASEAN (Filipiny), Eurazja (Turcja)
    • Jakie są największe wyzwania CTO i CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Warunki korzystania z witryny

    Copyright © 2025 by The Codest. Wszelkie prawa zastrzeżone.

    pl_PLPolish
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek pl_PLPolish