On Saturday, December 2, 2017 at 8:10:06 PM UTC-8, Andrew Burleson wrote:
>
> I have an app where there are Writing Groups:
> - Each group can have many Users.
> - Users can have many books.
> - Users can submit a book to a group.
> - Books then proceed through several states, such as "pending review" -> 
> "in review" -> "accepted" | "rejected", etc.
>
> The Group <-> Books relation is very simple to set up using a table 
> `group_books` with the primary key (group_id, book_id).
>
> The basic associations are very easy to set up:
>
> class Group < Sequel::Model
>   one_to_many :group_books
>   many_to_many :books, join_table: :group_books
> end
>
> <3 Sequel!
>
> Now, using the group it would be helpful to filter books based on what 
> state they're in, eg. rather than show me all books, show me all books that 
> are pending review. In the database this means the group book's 
> `review_status` column has the value `pending_review.`
>
> It's possible to declare that association like so:
>
> many_to_many :books_pending_review, join_table: :group_books, class: :Book
> , right_key: :book_id do |ds|
>   ds.where(review_status: 'pending_review')
> end
>
> This works fine, but in practice I have some qualms with it:
>
> First, it duplicates knowledge. For instance, in the GroupBooks model I 
> would want to have the following:
>
> dataset_module do
>   def pending_review
>     where(review_status: 'pending_review')
>   end
> end
>
> Now, I can chain that association if I want to return the group book 
> records, e.g.: `group.group_books.pending_review`, but that returns the 
> join models, not the book models.
>
> I'd prefer that the enum values that define book states in the database be 
> limited to the GroupBook class and be referenced via methods from the 
> outside world.
>
> A secondary, less important concern, is that this ends up being very 
> verbose if you have a large number of filtered associations in a full-size 
> app.
>

Assuming that every association is basically the same other than the status 
filter:

many:to_many :books, join_table: :group_books, class: :Book, right_key: 
:book_id
%w'pending_review in_review accepted rejected'.each do |status|
  many_to_many :"books_#{status}", :clone=>:books do |ds|
    ds.where(review_status: status)
  end
end
 

> So, is there a cleaner or better way to do this, ideally defining the 
> filtered associations in one place (GroupBook) and simply referencing them 
> (or chaining them) elsewhere?
>

Instead of making a many_to_many association, make a one_to_many to the 
join model (GroupBook), and have that use the :eager/:eager_graph option to 
also get the Book.

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 https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.

Reply via email to