Thanks, that is some useful code!
For this case though, it doesn't fulfill the need- the original models in
`a` are replaced with new references. For example, this situation would
need to pass:
x = T.new(name: 'A')
a = [x]
bulk_create_ala_jeremy(a)
assert x.id > 0
assert !x.new?
Admittedly, this does seem rather obscure- in this case, I have a series of
what are basically paired models; I want to do something like this:
model_a = []
model_b = []
(0..5).each do |i|
model_a << A.new
model_b << B.new
end
bulk_create(model_b)
model_a.zip(model_b).each { |a, b| a[:b_id] = b.id }
bulk_create(model_a)
My experience with Django's bulk_create tells me there are more (and less
exotic) cases; but I am not sure that's true in the general sense, it may
be more an artifact of the designs Django ORM pushes you down (or the bad
modeling of Django projects I've worked in, or both).
Thanks,
Rob
On Sun, Aug 29, 2021 at 10:28 PM Jeremy Evans <[email protected]>
wrote:
> On Sun, Aug 29, 2021 at 8:48 PM Rob Galanakis <[email protected]> wrote:
>
>> For now I went with something like this (my actual implementation isn't
>> quite so general):
>>
>> ```
>> module Bulk
>> class Ref
>> attr_accessor :instance
>> def initialize(instance)
>> @instance = instance
>> end
>> end
>> class Creator
>> def initialize(model_cls)
>> @model_cls = model_cls
>> @refs = []
>> end
>> def prepare(instance)
>> r = Ref.new(instance)
>> @refs << r
>> return r
>> end
>> def create_all
>> pks = @model_cls.multi_insert(@refs.map(&:instance), return:
>> :primary_key)
>> by_pk = @model_cls.where(id: pks).all.index_by(&:pk)
>> refs = @refs
>> @refs = []
>> refs.each_with_index do |ref, i|
>> inserted_pk = pks[i]
>> ref.instance = by_pk[inserted_pk]
>> end
>> return refs
>> end
>> end
>> end
>> ```
>>
>> I don't mind the additional caller complexity of having to use
>> `ref.instance` for now; I'm a bit hesitant to go the plugin route since it
>> will have to muck around with the guts of Model. But I'll keep it in mind
>> if I need it in the future (for what it's worth, I have had to add a
>> Sequel-style multi_insert helper for every significant Django project I
>> work on; this is the first time I've needed a Django-style bulk_create
>> helper in 7 years of Sequel).
>>
>
> For what you want, assuming you have an array of model instances, you can
> use this approach (should work on PostgreSQL and SQLite):
>
> DB.create_table(:ts) do
> primary_key :id
> String :name
> end
>
> class T < Sequel::Model
> end
>
> a = [T.new(name: 'A'), T.new(name: 'B')]
> columns = a.first.keys
> a = T.dataset.
> returning.
> with_sql(:insert_sql, columns, DB.values(a.map{|x|
> x.values.values_at(*columns)})).
> all
>
> Thanks,
> Jeremy
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "sequel-talk" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/sequel-talk/w8pWnUWHaC4/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sequel-talk/CADGZSSdFWYYgFOLB2wAaSu2fQbTXSuGqPpECmeEV4SXAxpAO7A%40mail.gmail.com
> <https://groups.google.com/d/msgid/sequel-talk/CADGZSSdFWYYgFOLB2wAaSu2fQbTXSuGqPpECmeEV4SXAxpAO7A%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
--
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 view this discussion on the web visit
https://groups.google.com/d/msgid/sequel-talk/CAMXo6RddKD2t8KLw-Yn%3DizuAxqo05tdo4s%3DnubAiMzWQ%3DMgW8Q%40mail.gmail.com.