<commit_before>module Forest
  module HasManyOrdered
    extend ActiveSupport::Concern

    class_methods do
      def has_many_ordered(association, options = {})
        through = options.delete(:through)
        through_options = options.delete(:through_options) || {}
        has_many_options = options.delete(:has_many_options) || {}
        order_by = options.delete(:order_by) || :position
        singular = association.to_s.singularize
        singular_id = (has_many_options.fetch(:source, nil).try(:to_s).try(:singularize) || singular).to_s + '_id'

        has_many through, -> { reorder(order_by) }, **options.reverse_merge(dependent: :destroy, **through_options)
        has_many association, -> { reorder("#{through}.#{order_by}") }, **options.merge(through: through, **has_many_options)
        accepts_nested_attributes_for through, allow_destroy: true

        define_method("#{singular}_ids=") do |ids|
          ids = ids.reject(&:blank?).collect(&:to_i)
          super(ids)
          send(through).each do |join_model|
            join_model.send("#{order_by}=", ids.index(join_model.send(singular_id)))
          end
        end
      end
    end
  end
end

ActiveRecord::Base.send(:include, Forest::HasManyOrdered)<commit_msg>Update has_many_ordered to remove non-unique ids<commit_after>module Forest
  module HasManyOrdered
    extend ActiveSupport::Concern

    class_methods do
      def has_many_ordered(association, options = {})
        through = options.delete(:through)
        through_options = options.delete(:through_options) || {}
        has_many_options = options.delete(:has_many_options) || {}
        order_by = options.delete(:order_by) || :position
        singular = association.to_s.singularize
        singular_id = (has_many_options.fetch(:source, nil).try(:to_s).try(:singularize) || singular).to_s + '_id'

        has_many through, -> { reorder(order_by) }, **options.reverse_merge(dependent: :destroy, **through_options)
        has_many association, -> { reorder("#{through}.#{order_by}") }, **options.merge(through: through, **has_many_options)
        accepts_nested_attributes_for through, allow_destroy: true

        define_method("#{singular}_ids=") do |ids|
          ids = ids.reject(&:blank?).collect(&:to_i).uniq
          super(ids)
          send(through).each do |join_model|
            join_model.send("#{order_by}=", ids.index(join_model.send(singular_id)))
          end
        end
      end
    end
  end
end

ActiveRecord::Base.send(:include, Forest::HasManyOrdered)
{'fraction_non_alphanumeric': 0.13238770685579196, 'fraction_numerical': 0.0, 'mean_word_length': 3.51779359430605, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5825123', 'n_tokens_mistral': 760, 'n_tokens_neox': 750, 'n_words': 128}