В итоге я сделал патч обезьяны, который переопределяет классовые методы Mongoid embeds_many
и embeds_one
, чтобы также определить метод экземпляра для очистки несохраненных документов для этого отношения. Мне показалось, что это самый простой способ, потому что это очень мало кода, и это означает, что мне не нужно помнить, чтобы включать его местами.
# config/initializers/patches/dirty_tracking_embedded.rb
module DirtyTrackingEmbedded
# override the embedding methods to also make dirty-tracking
def embeds_many(name, options= {}, &block)
define_method "clear_unsaved_#{name}" do
new_list = send(name).select(&:persisted?)
send(name.to_s + "=", new_list)
end
super
end
def embeds_one(name, options={}, &block)
define_method "clear_unsaved_#{name}" do
send(name.to_s + "=", nil) unless send(name).persisted?
end
super
end
end
module Mongoid
module Association
module Macros
module ClassMethods
prepend DirtyTrackingEmbedded
end
end
end
end
Затем в моем контроллере я использовал after_action
:
# app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
after_action :clear_unsaved, only: [:new]
def new
@relationship = current_user.relationships.new(friend_id: params[:fid])
@relationship.validate
end
private
def clear_unsaved
current_user.clear_unsaved_relationships
end
end
Вы можете патчить обезьяну [ 115] методы в Mongoid::Association::Embedded::EmbedsMany
и Mongoid::Association::Embedded::EmbedsOne
, чтобы включить настройку метода экземпляра для очистки несохраненных. Вы можете найти пример того, как монгоиды делают подобные вещи, посмотрев на Mongoid::Association::Accessors#self.define_ids_setter!
. Я бы порекомендовал сделать ваше исправление с помощью prepend
, как в решении, которое я использовал, чтобы вы могли наследовать остальную часть метода.
Mongoid выбирает, какой класс использовать для создания ассоциации из константы с именем MACRO_MAPPING
в Mongoid::Association
, так что вы можете создавать классы, которые наследуются от EmbedsMany
и EmbedsOne
просто переопределяют setup_instance_methods!
, чтобы добавить необходимый метод экземпляра, тогда вам нужно будет только обезьяна заплатить MACRO_MAPPING
для сопоставления с вашими новыми классами.
Если вы исправляете ошибки от обезьян, вы можете использовать код из моего модуля DirtyTrackingEmbedded
, чтобы создать ActiveSupport::Concern
, который делает то же самое. Вы захотите поместить переопределенные методы в блок class_methods
, а затем просто убедитесь, что вы включили этот модуль после включения Mongoid::Document
в любой класс модели, в котором вы хотите его использовать.
(Вероятно, это немного поздно для OP, но все же может быть полезно для других)
К сожалению, Java не поддерживает массивы с более чем 2 31 < / sup> -1 элементов. Максимальное потребление составляет 2 ГБ пространства для массива byte[]
или 16 ГБ пространства для массива long[]
.
Хотя это, вероятно, неприменимо в этом случае, если массив будет разреженным , вы можете избежать использования ассоциативной структуры данных, такой как Map
, чтобы сопоставить каждое использованное смещение с соответствующим значением. Кроме того, Trove обеспечивает более эффективную реализацию памяти для хранения примитивных значений, чем стандартные коллекции Java.
Если массив не разреженный и вам действительно нужен весь блоб в памяти, вам, вероятно, придется использовать двумерную структуру, например, с Map
совпадающими смещениями по модулю 1024 в соответствующий 1024-байтовый массив. Этот подход может быть более эффективным с точки зрения памяти даже для разреженных массивов, поскольку смежные заполненные ячейки могут использовать одну и ту же запись Map
.
Это не из немедленной помощи, но создание массивов с большими размерами (через longs) является предлагаемым изменением языка для Java 7. Ознакомьтесь с предложениями Project Coin для получения дополнительной информации
Байт []
с размером максимального 32-битного целого числа со знаком потребует 2 ГБ непрерывного адресного пространства. Не стоит пытаться создать такой массив. В противном случае, если размер на самом деле не такой большой (а это просто больший тип), вы можете безопасно преобразовать его в int
и использовать его для создания массива.
Вам, вероятно, следует использовать поток для чтения ваших данных, а другой - для их записи вне. Если вам понадобится доступ к данным позже в файле, сохраните их. Если вам нужен доступ к чему-то, с чем вы еще не сталкивались, вам нужна двухпроходная система, в которой вы проходите один раз и сохраняете «материал, который вам понадобится для второго прохода, а затем проходите снова».
Компиляторы работайте таким образом.
Единственный случай одновременной загрузки всего массива - это многократный случайный доступ ко многим местам в массиве. В этом случае я предлагаю вам загрузить его в несколько байтовых массивов, все из которых хранятся в одном классе-контейнере.
Класс-контейнер будет иметь массив байтовых массивов, но извне все обращения кажутся смежными. Вы просто запросите байт 49874329128714391837, и ваш класс разделит ваш Long на размер каждого байтового массива, чтобы вычислить, к какому массиву получить доступ, затем используйте остаток для определения байта.
Он также может иметь методы для хранения и извлечения «фрагментов», которые могут охватывать границы байтового массива, что потребует создания временной копии, но затраты на создание нескольких временных массивов будут быть более чем компенсированным тем фактом, что у вас нет выделенного заблокированного 2 ГБ пространства, что, как я думаю, может просто испортить вашу производительность.
Edit: ps. Если вам действительно нужен произвольный доступ и вы не можете использовать потоки, тогда реализация содержащего класса является очень хорошей идеей. Это позволит вам на лету менять реализацию с однобайтового массива на группу байтовых массивов на файловую систему без каких-либо изменений в остальной части вашего кода.
который мог бы охватывать границы байтового массива, что потребовало бы создания временной копии, но затраты на создание нескольких временных массивов были бы более чем компенсированы тем фактом, что у вас нет выделенного заблокированного 2 ГБ пространства, которое, как я думаю, могло бы просто разрушьте вашу производительность.Edit: ps. Если вам действительно нужен произвольный доступ и вы не можете использовать потоки, тогда реализация содержащего класса является очень хорошей идеей. Это позволит вам на лету менять реализацию с однобайтового массива на группу байтовых массивов на файловую систему без каких-либо изменений в остальной части вашего кода.
который мог бы охватывать границы байтового массива, что потребовало бы создания временной копии, но затраты на создание нескольких временных массивов были бы более чем компенсированы тем фактом, что у вас нет выделенного заблокированного 2 ГБ пространства, которое, как я думаю, могло бы просто разрушьте вашу производительность.Edit: ps. Если вам действительно нужен произвольный доступ и вы не можете использовать потоки, тогда реализация содержащего класса является очень хорошей идеей. Это позволит вам на лету менять реализацию с однобайтового массива на группу байтовых массивов на файловую систему без каких-либо изменений в остальной части вашего кода.
Если вам действительно нужен произвольный доступ и вы не можете использовать потоки, тогда реализация содержащего класса является очень хорошей идеей. Это позволит вам на лету менять реализацию с однобайтового массива на группу байтовых массивов на файловую систему без каких-либо изменений в остальной части вашего кода. Если вам действительно нужен произвольный доступ и вы не можете использовать потоки, тогда реализация содержащего класса является очень хорошей идеей. Это позволит вам на лету менять реализацию с однобайтового массива на группу байтовых массивов на файловую систему без каких-либо изменений в остальной части вашего кода.Один из способов «сохранить» массив - это записать его в файл и затем получить к нему доступ (если вам нужен доступ к нему как к массиву) с помощью RandomAccessFile. API для этого файла использует long как индекс в файле вместо int. Это будет медленнее, но с меньшей нагрузкой на память.
Это когда вы не можете извлечь то, что вам нужно во время начального сканирования ввода.