Techioz Blog

チェーンレール。いずれかが当てはまる場合に選択する場所

概要

Rails アプリケーションで作成した条件付きクエリに問題があります。現在、特定の場所(location_north、location_southなど)がtrueである場合、および特定のタイプ(type_ Dining、type_uniqueなど)がtrueである場合に店舗がクエリされていますが、代わりに、それらのすべてではなく、いずれかが2つである場合にクエリを実行したいと考えています。それらは真実です。

たとえば、リードの location_north と location_east が true に設定されている場合、location_north または location_east を使用してすべてのストアにクエリを実行したい場合、ストアでは両方を true に設定する必要はありません。

タイプについても同様です。リードのstore_type_uniqueがtrueで、store_type_ Diningがtrueの場合、type_uniqueまたはtype_ Diningがtrueであるすべての店舗をクエリしたいのですが、店舗では両方をtrueに設定する必要はありません。

データベースの構成方法に問題があることはわかっていますが、現在のビルドでこれを設定する方法はありますか?ご指導ありがとうございます。感謝いたします。

    def build_filters_obj
        filters = []
        filters.push 'location_north' if @lead.location_north
        filters.push 'location_east' if @lead.location_east
        filters.push 'location_south' if @lead.location_south
        filters.push 'location_west' if @lead.location_west
        filters.push 'location_other' if @lead.location_other
        
        return filters
    end

    def perform(lead_id)
        @lead = Lead.find(lead_id)

        lead_email = ValidEmail2::Address.new(@lead.email)
        UserNotifierMailer.send_signup_email(@lead).deliver if lead_email.valid?

        @stores = Store.all
        @stores = @stores.where.not(email: [nil, ''])

        n = @lead.guests_total.to_i
        @stores = @stores.where("capacity_min <= ? AND capacity_max >= ?", n, n)
        
        @stores = @stores.where(:type_unique => true) if @lead.store_type_unique
        @stores = @stores.where(:type_dining => true) if @lead.store_type_dining
        @stores = @stores.where(:type_hotel => true) if @lead.store_type_hotel
        
        filters = build_filters_obj
        filters.each do |filter|
            @stores = @stores.where(filter.to_sym => true)
        end

        @stores = @stores.or(Store.where(:receive_all => true))

        @stores.each do |store|
            store_email = ValidEmail2::Address.new(store.email)
            UserNotifierMailer.send_lead_email(store, @lead).deliver if store_email.valid?
        end
    end

解決策

非常に簡単な変更は、次の各行を書き換えることです。

@stores = @stores.where(:type_unique => true) if @lead.store_type_unique

これに:

@stores = @stores.or(Store.where(:type_unique => true)) if @lead.store_type_unique

フィルターループ内の行も同様です。

そこから、テストを作成して、正しいロジックが得られていることを確認します。最後に、コードをリファクタリングして DRY アップできます。