On Monday, October 7, 2013 9:07:07 AM UTC-7, Dave Bradford wrote:

> Given the following models:
>
> class Plan < Sequel::Model
>   one_to_many :user_plans
> end
>
> class User < Sequel::Model
>   one_to_many :plans, class: "UserPlan"
> end
>
> class UserPlan < Sequel::Model
>   many_to_one :user
>   many_to_one :plan
> end
>
>
>
> I'd like to have "chainable" filters on UserPlan that filter on fields 
> from Plan. For example:
>
> class UserPlan < Sequel::Model
>   dataset_module do
>     def visible
>       inner_join(:plans, id: :plan_id).where(plans__type: "hidden")
>     end
>
>     def for_sku(sku)
>       inner_join(:plans, id: :plan_id).where(plans__sku: sku)
>     end
> end
>
>
>
> However, attempting to chain the filters together joins "plans" twice 
> resulting in DB error (using Postgres). Example chained filters: 
>  
>
> UserPlan.visible.for_sku("123")
>
>
>
> What would be best-practice for creating chainable filters for joined 
> tables?
>

What I would probably do in my own code is be more explicit about the 
joining, with an API like:

  UserPlan.join_plans.visible.for_sku("123")

Basically, require join_plans be called before visible for for_sku.

However, if you want to keep it implicit, you can use introspection on 
opts[:join] to see if the table has already been joined, and not do the 
join in that case. You can also do something simpler, just recording 
whether the table has already been joined:

  class UserPlan < Sequel::Model
    dataset_module do
      def join_plans
        opts[:join_plans] ? clone : inner_join(:plans, id: 
:plan_id).clone(:join_plans=>true)
      end
      def visible
        join_plans.where(plans__type: "hidden")
      end
      def for_sku(sku)
        join_plans.where(plans__sku: sku)
      end
    end
  end

Thanks,
Jeremy

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to