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.