Sorry about the Docker setup, thought it might be easier. I'll remember for 
next time.

I see what you're saying about adding the :order. Doing that on the 
association is cleaner than the proc.

I turned on debug to look at the queries, and it looks like doing it that 
way creates N+1 queries, i.e.:

INFO -- : (0.000408s) SELECT * FROM `vendors` WHERE (`user_id` = 1)
INFO -- : (0.000509s) SELECT * FROM `vendor_revisions` WHERE 
(`vendor_revisions`.`vendor_id` = 1) ORDER BY `created_at` DESC LIMIT 1
INFO -- : (0.000356s) SELECT * FROM `vendor_revisions` WHERE 
(`vendor_revisions`.`vendor_id` = 2) ORDER BY `created_at` DESC LIMIT 1

Isn't that less efficient than doing it all in one query and sorting it out?

Thanks,
greg

On Thursday, December 29, 2016 at 2:14:00 AM UTC-5, Jeremy Evans wrote:
>
> On Wednesday, December 28, 2016 at 10:03:55 PM UTC-8, Greg Gilbert wrote:
>>
>> Hey,
>>
>> I put together a proof of concept using Docker: 
>> https://github.com/greggilbert/sequel-association-test
>>
>> If you look at doit.rb, you'll see two queries. The first one doesn't 
>> work (i.e. returns nil) but the second one does. I guess there's 
>> something about the eager_limit that's not right? And if you leave out 
>> the .eager line altogether, you get the first VendorRevision for each, 
>> not the last.
>>
>> Let me know if there's anything else I can clarify.
>>
>
> In the future, please do not submit examples that use docker, or split 
> code between multiple files.  Please combine all code in a single post to 
> this list.  This saves me time as I wouldn't have to go through 4 separate 
> files to piece together a working example just to provide support.  Below 
> is a self contained example I made from your repo that is runnable with 
> bin/sequel (e.g. ruby bin/sequel -E sqlite:/ filename.rb).
>
> In any case, :eager_limit should not be used for one_to_one associations, 
> and it doesn't make sense to use it as the limit should always be 1 anyway 
> (it can make sense for *_to_many associations).  Using :eager_limit for 
> one_to_one associations is undefined behavior, so the fact that it breaks 
> something is not a bug.
>
> You'll notice in the code below that I commented out the :order option to 
> the last_edit association.  From looking at your example, I would guess 
> that you would want to specify that option, and then you'll be able to use 
> the last block in the example, which doesn't use an eager callback.  This 
> is best as it produces the most optimized query.  It seems to me unlikely 
> that you'd ever want to use the last_edit association without a reverse 
> chronological order.
>
> Thanks,
> Jeremy
>
> DB.instance_exec do
>     create_table(:users) do
>       primary_key :id
>       String :email, null: false
>       String :password_hash, null: false
>       DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
>       DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
>     end
>
>     create_table(:vendors) do
>       primary_key :id
>       foreign_key :user_id, :users
>       Boolean :is_verified, default: false
>     end
>
>     create_table(:vendor_revisions) do
>       primary_key :id
>       foreign_key :vendor_id, :vendors, null: false, index: true
>       String :name, null: false, index: true
>       DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP
>       DateTime :updated_at, default: Sequel::CURRENT_TIMESTAMP
>     end
>
>     alter_table(:vendors) do
>       add_foreign_key :latest_revision, :vendor_revisions, null: true
>     end
> end
>
> class User < Sequel::Model
>   one_to_many :vendors
> end
>
> class VendorRevision < Sequel::Model
>   many_to_one :vendor
> end
>
> VendorRevision.plugin :timestamps, update_on_create: true
>
> class Vendor < Sequel::Model
>   one_to_many :vendor_revisions, class: VendorRevision
>   many_to_one :user
> end
>
> Vendor.one_to_one :last_edit, :class => :VendorRevision#, 
> :order=>Sequel.desc(:created_at)
>
> u1 = User.create(:email => '[email protected] <javascript:>', 
> password_hash: 'foo')
> u2 = User.create(:email => '[email protected] <javascript:>', 
> password_hash: 'foo')
> v1 = Vendor.create(:user_id => u1.id)
> v2 = Vendor.create(:user_id => u1.id)
> v3 = Vendor.create(:user_id => u2.id)
> vr1 = VendorRevision.create(:vendor_id => v1.id, :name => 'Test one')
> vr3 = VendorRevision.create(:vendor_id => v2.id, :name => 'Test three')
> vr2 = VendorRevision.create(:vendor_id => v1.id, :name => 'Test two')
> vr4 = VendorRevision.create(:vendor_id => v2.id, :name => 'Test four')
>
> vendors = Vendor
>             .where(:user_id => 1)
>             .eager(:last_edit => proc {|ds| 
> ds.reverse_order(:created_at).clone(:eager_limit => 1) })
>             .all
>
> vendors.each do |v|
>   p v.last_edit
>   p '-'*50
> end
>
> vendors = Vendor
>              .where(:user_id => 1)
>              .eager(:last_edit => proc {|ds| ds.reverse_order(:created_at) 
> })
>              .all
>
> vendors.each do |v|
>   p v.last_edit
>   p '-'*50
> end
>
> vendors = Vendor
>              .where(:user_id => 1)
>              .eager(:last_edit)
>              .all
>
> vendors.each do |v|
>   p v.last_edit
>   p '-'*50
> end
>

-- 
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