activeadmin-orderable-table 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +61 -0
- data/activeadmin-orderable-table.gemspec +24 -0
- data/app/assets/javascripts/activeadmin-orderable-table.js +97 -0
- data/app/assets/stylesheets/activeadmin-orderable-table.css +1 -0
- data/lib/active_admin/orderable_table.rb +42 -0
- data/lib/active_record/acts_as.rb +7 -0
- data/lib/active_record/acts_as/orderable_table.rb +93 -0
- data/lib/activeadmin-orderable-table.rb +7 -0
- data/lib/activeadmin-orderable-table/version.rb +5 -0
- data/spec/db_helper.rb +14 -0
- data/spec/lib/active_record/acts_as/orderable_table_spec.rb +181 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/utilities.rb +4 -0
- metadata +158 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 1d219b5422a68bd3eb67ef48836e3b9792d00515
         | 
| 4 | 
            +
              data.tar.gz: 1442df0bc372616af4422f4210c82542b9203082
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 94f61daf00fbf7d6753012f2bb783ac5e59b42128bd26e5ecfc9f76f2cb26d74c2650922d2c0eabed71ca90d6b65abe5cf94e9d68cc5e19691fb1c97b05d2d5e
         | 
| 7 | 
            +
              data.tar.gz: fb6d9c701d956a26ef8807b6131a9c6f814810d93de07d4cd405874b4eefdd355a56b40624af89b41519f70b87e7b306b677c28a52973669b76d4881e7cc0dff
         | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            Copyright (c) 2016 Max Hordiichuk
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            MIT License
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 6 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 7 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 8 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 9 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 10 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 11 | 
            +
            the following conditions:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 14 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 17 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 18 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 19 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 20 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 21 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 22 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,61 @@ | |
| 1 | 
            +
            # Active Admin Orderable Table
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            This gem extends ActiveAdmin so that your index page's table rows can be 
         | 
| 4 | 
            +
            orderable without page reloading via a drag-and-drop interface.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            ## Usage
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ### Add gem to your Gemfile
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            ```ruby
         | 
| 11 | 
            +
            gem 'sortable-rails'
         | 
| 12 | 
            +
            gem 'activeadmin-orderable-table'
         | 
| 13 | 
            +
            ```
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            ### Include the JavaScript in active_admin.js
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ```javascript
         | 
| 18 | 
            +
            //= require sortable-rails
         | 
| 19 | 
            +
            //= require activeadmin-orderable-table
         | 
| 20 | 
            +
            ```
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            ### Include the Stylesheet in active_admin.css
         | 
| 23 | 
            +
            ```css
         | 
| 24 | 
            +
            //= require activeadmin-orderable-table
         | 
| 25 | 
            +
            ```
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            ### Configure your ActiveRecord model
         | 
| 28 | 
            +
            You need to add an ordinal column to desired table:
         | 
| 29 | 
            +
            ```bash
         | 
| 30 | 
            +
            rails g migration AddOrdinalToPage ordinal:integer
         | 
| 31 | 
            +
            rake db:migrate
         | 
| 32 | 
            +
            ```
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            Then add following line to model that suppose to be orderable:
         | 
| 35 | 
            +
            ```ruby
         | 
| 36 | 
            +
            acts_as_orderable_table
         | 
| 37 | 
            +
            ```
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            ### Configure your ActiveAdmin Resource
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            ```ruby
         | 
| 42 | 
            +
            ActiveAdmin.register Page do
         | 
| 43 | 
            +
              config.sort_order = 'ordinal_asc'
         | 
| 44 | 
            +
              config.paginate = false # optional; drag-and-drop across pages is not supported
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              orderable # creates the controller action which handles the ordering
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              index do
         | 
| 49 | 
            +
                orderable_handle_column # inserts a drag handle
         | 
| 50 | 
            +
                # other columns...
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
            end
         | 
| 53 | 
            +
            ```
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            ## Contributing
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            1. Fork it
         | 
| 58 | 
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         | 
| 59 | 
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         | 
| 60 | 
            +
            4. Push to the branch (`git push origin my-new-feature`)
         | 
| 61 | 
            +
            5. Create new Pull Request
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
            require File.expand_path('../lib/activeadmin-orderable-table/version', __FILE__)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            Gem::Specification.new do |s|
         | 
| 5 | 
            +
              s.name = 'activeadmin-orderable-table'
         | 
| 6 | 
            +
              s.version = Activeadmin::OrderableTable::VERSION
         | 
| 7 | 
            +
              s.date = Time.new.strftime('%Y-%m-%d')
         | 
| 8 | 
            +
              s.summary = 'Order ActiveAdmin tables'
         | 
| 9 | 
            +
              s.description = 'Drag and drop order interface for ActiveAdmin tables'
         | 
| 10 | 
            +
              s.authors = ['Max Hordiichuk']
         | 
| 11 | 
            +
              s.email = 'hordijchuk.m.i@gmail.com'
         | 
| 12 | 
            +
              s.files = `git ls-files`.split("\n")
         | 
| 13 | 
            +
              s.homepage = 'https://github.com/MaximHordijchuk/activeadmin-orderable-table'
         | 
| 14 | 
            +
              s.license = 'MIT'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              s.add_development_dependency 'bundler', '~> 1.10'
         | 
| 17 | 
            +
              s.add_development_dependency 'rspec-rails', '~> 3.5'
         | 
| 18 | 
            +
              s.add_development_dependency 'test-unit', '~> 3.0'
         | 
| 19 | 
            +
              s.add_development_dependency 'sqlite3', '~> 1.3'
         | 
| 20 | 
            +
              s.add_development_dependency 'sass-rails'
         | 
| 21 | 
            +
              s.add_development_dependency 'activerecord'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              s.add_runtime_dependency 'sortable-rails', '~> 1.4'
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,97 @@ | |
| 1 | 
            +
            (function($) {
         | 
| 2 | 
            +
                $(document).ready(function() {
         | 
| 3 | 
            +
                    var $handle = $('.activeadmin-orderable-handle');
         | 
| 4 | 
            +
                    if ($handle.length > 0) {
         | 
| 5 | 
            +
                        $handle.closest('tbody').activeAdminOrderableTable();
         | 
| 6 | 
            +
                    }
         | 
| 7 | 
            +
                });
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                $.fn.activeAdminOrderableTable = function() {
         | 
| 10 | 
            +
                    var $container = this;
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    // Returns all sibling elements between $firstElement and $lastElement
         | 
| 13 | 
            +
                    // including these elements
         | 
| 14 | 
            +
                    var findElements = function ($container, $firstElement, $lastElement) {
         | 
| 15 | 
            +
                        var $elements = $firstElement.nextUntil($lastElement);
         | 
| 16 | 
            +
                        var elements = [$firstElement[0]];
         | 
| 17 | 
            +
                        for (var i = 0; i < $elements.length; i++) {
         | 
| 18 | 
            +
                            elements.push($elements[i]);
         | 
| 19 | 
            +
                        }
         | 
| 20 | 
            +
                        elements.push($lastElement[0]);
         | 
| 21 | 
            +
                        return elements;
         | 
| 22 | 
            +
                    };
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    // [1, 2, 3, 4, 5] -> [2, 3, 4, 5, 1]
         | 
| 25 | 
            +
                    // Reverse: [1, 2, 3, 4, 5] -> [5, 1, 2, 3, 4]
         | 
| 26 | 
            +
                    var rotateArray = function (elements, reverse) {
         | 
| 27 | 
            +
                        var result = [], i;
         | 
| 28 | 
            +
                        if (reverse) {
         | 
| 29 | 
            +
                            result.push(elements[elements.length - 1]);
         | 
| 30 | 
            +
                            for (i = 0; i < elements.length - 1; i++) {
         | 
| 31 | 
            +
                                result.push(elements[i]);
         | 
| 32 | 
            +
                            }
         | 
| 33 | 
            +
                        } else {
         | 
| 34 | 
            +
                            for (i = 1; i < elements.length; i++) {
         | 
| 35 | 
            +
                                result.push(elements[i]);
         | 
| 36 | 
            +
                            }
         | 
| 37 | 
            +
                            result.push(elements[0]);
         | 
| 38 | 
            +
                        }
         | 
| 39 | 
            +
                        return result;
         | 
| 40 | 
            +
                    };
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    // Returns array of elements' ordinal values
         | 
| 43 | 
            +
                    var getOrdinals = function (elements) {
         | 
| 44 | 
            +
                        var ordinals = [];
         | 
| 45 | 
            +
                        for (var i = 0; i < elements.length; i++) {
         | 
| 46 | 
            +
                            ordinals.push($(elements[i]).find('[data-ordinal]').data('ordinal'));
         | 
| 47 | 
            +
                        }
         | 
| 48 | 
            +
                        return ordinals;
         | 
| 49 | 
            +
                    };
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    var setOrdinals = function (elements, ordinals) {
         | 
| 52 | 
            +
                        for (var i = 0; i < elements.length; i++) {
         | 
| 53 | 
            +
                            $(elements[i]).find('[data-ordinal]').data('ordinal', ordinals[i]);
         | 
| 54 | 
            +
                        }
         | 
| 55 | 
            +
                    };
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    var sendReorderRequest = function ($element, ordinals) {
         | 
| 58 | 
            +
                        var url = $element.find('[data-reorder-url]').data('reorder-url');
         | 
| 59 | 
            +
                        $.ajax({
         | 
| 60 | 
            +
                            url: url,
         | 
| 61 | 
            +
                            type: 'post',
         | 
| 62 | 
            +
                            data: { position: $element.find('[data-ordinal]').data('ordinal'),
         | 
| 63 | 
            +
                                    ordinals: ordinals },
         | 
| 64 | 
            +
                            error: function(error) { console.log('Reordering failed:', error) }
         | 
| 65 | 
            +
                        });
         | 
| 66 | 
            +
                    };
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    var logOrdinals = function (elements) {
         | 
| 69 | 
            +
                        for (var i = 0; i < elements.length; i++) {
         | 
| 70 | 
            +
                            console.log($(elements[i]).find('[data-ordinal]').data('ordinal'));
         | 
| 71 | 
            +
                        }
         | 
| 72 | 
            +
                    };
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    Sortable.create($container[0], {
         | 
| 75 | 
            +
                        animation: 150,
         | 
| 76 | 
            +
                        draggable: 'tr',
         | 
| 77 | 
            +
                        onEnd: function (event) {
         | 
| 78 | 
            +
                            if (event.oldIndex != event.newIndex) {
         | 
| 79 | 
            +
                                var $firstElement, $lastElement, $movedElement, elements, ordinals;
         | 
| 80 | 
            +
                                if (event.oldIndex < event.newIndex) { // from left to right
         | 
| 81 | 
            +
                                    $firstElement = $container.find('tr').eq(event.oldIndex);
         | 
| 82 | 
            +
                                    $lastElement = $container.find('tr').eq(event.newIndex);
         | 
| 83 | 
            +
                                    $movedElement = $lastElement
         | 
| 84 | 
            +
                                } else { // from right to left
         | 
| 85 | 
            +
                                    $firstElement = $container.find('tr').eq(event.newIndex);
         | 
| 86 | 
            +
                                    $lastElement = $container.find('tr').eq(event.oldIndex);
         | 
| 87 | 
            +
                                    $movedElement = $firstElement
         | 
| 88 | 
            +
                                }
         | 
| 89 | 
            +
                                elements = findElements($container, $firstElement, $lastElement);
         | 
| 90 | 
            +
                                ordinals = rotateArray(getOrdinals(elements), event.oldIndex < event.newIndex);
         | 
| 91 | 
            +
                                setOrdinals(elements, ordinals);
         | 
| 92 | 
            +
                                sendReorderRequest($movedElement, ordinals);
         | 
| 93 | 
            +
                            }
         | 
| 94 | 
            +
                        }
         | 
| 95 | 
            +
                    });
         | 
| 96 | 
            +
                }
         | 
| 97 | 
            +
            })(jQuery);
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            .activeadmin-orderable-column .activeadmin-orderable-handle { cursor: ns-resize; }
         | 
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            if defined?(ActiveAdmin)
         | 
| 2 | 
            +
              module ActiveAdmin
         | 
| 3 | 
            +
                module OrderableTable
         | 
| 4 | 
            +
                  module ControllerActions
         | 
| 5 | 
            +
                    def orderable
         | 
| 6 | 
            +
                      member_action :reorder, method: :post do
         | 
| 7 | 
            +
                        position = params[:position].to_i
         | 
| 8 | 
            +
                        if params[:ordinals]
         | 
| 9 | 
            +
                          ordinals_scope = params[:ordinals].map { |ordinal| ordinal.to_i }
         | 
| 10 | 
            +
                          resource.insert_at position, ordinals_scope
         | 
| 11 | 
            +
                        else
         | 
| 12 | 
            +
                          resource.insert_at position
         | 
| 13 | 
            +
                        end
         | 
| 14 | 
            +
                        head 200
         | 
| 15 | 
            +
                      end
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  module TableMethods
         | 
| 20 | 
            +
                    HANDLE = '↕'.html_safe
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    def orderable_handle_column
         | 
| 23 | 
            +
                      column_name = resource_class.ordinal_field
         | 
| 24 | 
            +
                      return if params[:order] != "#{column_name}_asc" && params[:order] != "#{column_name}_desc"
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      column '', class: 'activeadmin-orderable-column' do |resource|
         | 
| 27 | 
            +
                        reorder_path = resource_path(resource) + '/reorder'
         | 
| 28 | 
            +
                        content_tag :span, HANDLE, class: 'activeadmin-orderable-handle', 'data-reorder-url': reorder_path,
         | 
| 29 | 
            +
                                    'data-ordinal': resource.acts_ordinal_value
         | 
| 30 | 
            +
                      end
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  ::ActiveAdmin::ResourceDSL.send(:include, ControllerActions)
         | 
| 35 | 
            +
                  ::ActiveAdmin::Views::TableFor.send(:include, TableMethods)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  class Engine < ::Rails::Engine
         | 
| 38 | 
            +
                    # Including an Engine tells Rails that this gem contains assets
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
| @@ -0,0 +1,93 @@ | |
| 1 | 
            +
            module ActiveRecord
         | 
| 2 | 
            +
              module ActsAs
         | 
| 3 | 
            +
                module OrderableTable
         | 
| 4 | 
            +
                  def self.included(base)
         | 
| 5 | 
            +
                    base.extend(ClassMethods)
         | 
| 6 | 
            +
                  end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  module ClassMethods
         | 
| 9 | 
            +
                    attr_reader :ordinal_field, :starts_from
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def acts_as_orderable_table(options = {})
         | 
| 12 | 
            +
                      @ordinal_field = options[:ordinal_field] || :ordinal
         | 
| 13 | 
            +
                      @starts_from = options[:starts_from] || 0
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      validates @ordinal_field, presence: true
         | 
| 16 | 
            +
                      validate :check_ordinal_uniqueness
         | 
| 17 | 
            +
                      before_validation :set_defaults
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      class_eval do
         | 
| 20 | 
            +
                        include ActiveRecord::ActsAs::OrderableTable::InstanceMethods
         | 
| 21 | 
            +
                      end
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  module InstanceMethods
         | 
| 26 | 
            +
                    def insert_at(position, ordinals_scope = nil)
         | 
| 27 | 
            +
                      return if position == acts_ordinal_value # if ordinal haven't changed
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      # if new position is not occupied just take this ordinal
         | 
| 30 | 
            +
                      unless self.class.where("#{acts_ordinal_field}": position).first
         | 
| 31 | 
            +
                        update_attributes("#{acts_ordinal_field}": position)
         | 
| 32 | 
            +
                        return
         | 
| 33 | 
            +
                      end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                      items = items_scoped(position, ordinals_scope)
         | 
| 36 | 
            +
                      current_positions = items.map { |item| item.send(acts_ordinal_field) }
         | 
| 37 | 
            +
                      reordered_positions = reorder_positions(position, current_positions)
         | 
| 38 | 
            +
                      update_ordinals(items, reordered_positions)
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def acts_ordinal_field
         | 
| 42 | 
            +
                      self.class.ordinal_field
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    def acts_ordinal_value
         | 
| 46 | 
            +
                      self.send(acts_ordinal_field)
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    def starts_from
         | 
| 50 | 
            +
                      self.class.starts_from
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    private
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    def ordinal_range(position)
         | 
| 56 | 
            +
                      position > acts_ordinal_value ? (acts_ordinal_value + 1)..position : position...acts_ordinal_value
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                    def items_scoped(position, ordinals_scope)
         | 
| 60 | 
            +
                      actual_ordinals_scope = *ordinal_range(position)
         | 
| 61 | 
            +
                      actual_ordinals_scope &= ordinals_scope if ordinals_scope
         | 
| 62 | 
            +
                      self.class.where("#{acts_ordinal_field}": actual_ordinals_scope).order(acts_ordinal_field).to_a.push(self)
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    def reorder_positions(position, positions)
         | 
| 66 | 
            +
                      position > acts_ordinal_value ? positions.rotate(-1) : positions.rotate
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    def update_ordinals(items, positions)
         | 
| 70 | 
            +
                      items.each_with_index do |item, index|
         | 
| 71 | 
            +
                        item.assign_attributes("#{acts_ordinal_field}": positions[index])
         | 
| 72 | 
            +
                        item.save!(validate: false)
         | 
| 73 | 
            +
                      end
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                    def check_ordinal_uniqueness
         | 
| 77 | 
            +
                      if acts_ordinal_value.present? &&
         | 
| 78 | 
            +
                         self.class.where("#{acts_ordinal_field}": acts_ordinal_value).reject { |record| record == self }.first
         | 
| 79 | 
            +
                        self.errors[acts_ordinal_field] << 'must be unique'
         | 
| 80 | 
            +
                      end
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    def set_defaults
         | 
| 84 | 
            +
                      if acts_ordinal_value.blank?
         | 
| 85 | 
            +
                        ordinal_value_prev = self.class.maximum(acts_ordinal_field)
         | 
| 86 | 
            +
                        ordinal_value_next = (ordinal_value_prev ? ordinal_value_prev + 1 : starts_from)
         | 
| 87 | 
            +
                        assign_attributes("#{acts_ordinal_field}": ordinal_value_next)
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
            end
         | 
    
        data/spec/db_helper.rb
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            require 'sqlite3'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ActiveRecord::Schema.define(:version => 1) do
         | 
| 6 | 
            +
              create_table "entities", :force => true do |t|
         | 
| 7 | 
            +
                t.integer  "ordinal", null: false
         | 
| 8 | 
            +
                t.integer  "field"
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
            end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            class Entity < ActiveRecord::Base
         | 
| 13 | 
            +
              acts_as_orderable_table
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,181 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RANDOM_ORDINAL_MAX = 100
         | 
| 4 | 
            +
            # should be > 2 and <= RANDOM_ORDINAL_MAX
         | 
| 5 | 
            +
            TEST_ENTITIES_COUNT = 10
         | 
| 6 | 
            +
            # should be > 1 and <= TEST_ENTITIES_COUNT
         | 
| 7 | 
            +
            TEST_ENTITIES_SCOPE_COUNT = 6
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            RSpec.describe ActiveRecord::ActsAs::OrderableTable do
         | 
| 10 | 
            +
              describe 'without options' do
         | 
| 11 | 
            +
                let(:random_ordinal) { Random.new.rand(RANDOM_ORDINAL_MAX) }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                after { Entity.destroy_all }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                describe 'set default values' do
         | 
| 16 | 
            +
                  it 'should create entity with custom ordinal value' do
         | 
| 17 | 
            +
                    entity = Entity.create!(ordinal: random_ordinal)
         | 
| 18 | 
            +
                    expect(entity.ordinal).to eq random_ordinal
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  it 'should set default ordinal value to zero with empty entities table' do
         | 
| 22 | 
            +
                    entity = Entity.create!
         | 
| 23 | 
            +
                    expect(entity.ordinal).to eq 0
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  it 'should set default ordinal value to incremented max existing ordinal' do
         | 
| 27 | 
            +
                    entities_with_random_ordinal(TEST_ENTITIES_COUNT, RANDOM_ORDINAL_MAX).each(&:save!)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    entities = [Entity.new(ordinal: RANDOM_ORDINAL_MAX + random_ordinal)]
         | 
| 30 | 
            +
                    (TEST_ENTITIES_COUNT).times { entities << Entity.new }
         | 
| 31 | 
            +
                    entities.each(&:save!)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    1.upto(entities.size - 1) { |i| expect(entities[i].ordinal).to eq entities[i - 1].ordinal + 1 }
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                it 'should validate ordinal uniqueness' do
         | 
| 38 | 
            +
                  Entity.create!(ordinal: random_ordinal)
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  entity_with_different_ordinal = Entity.new(ordinal: random_ordinal + 1)
         | 
| 41 | 
            +
                  expect(entity_with_different_ordinal).to be_truthy
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  entity_with_same_ordinal = Entity.new(ordinal: random_ordinal)
         | 
| 44 | 
            +
                  expect(entity_with_same_ordinal.valid?).to be_falsey
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                describe 'reordering' do
         | 
| 48 | 
            +
                  context 'without scope' do
         | 
| 49 | 
            +
                    let(:entities) do
         | 
| 50 | 
            +
                      entities = entities_with_random_ordinal(TEST_ENTITIES_COUNT, RANDOM_ORDINAL_MAX)
         | 
| 51 | 
            +
                      entities.each(&:save!)
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    let(:entity) { entities.first }
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    it "shouldn't change position if ordinal haven't changed" do
         | 
| 57 | 
            +
                      expect { entity.insert_at(entity.ordinal) }.not_to change { entities.map(&:ordinal) }
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    context 'new position is now occupied' do
         | 
| 61 | 
            +
                      let(:position_new) { RANDOM_ORDINAL_MAX + random_ordinal }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                      it 'should not change other entities if new position is now occupied' do
         | 
| 64 | 
            +
                        expect { entity.insert_at(position_new) }.not_to change { entities.drop(1).map(&:ordinal) }
         | 
| 65 | 
            +
                      end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                      it 'should set new position if new position is now occupied' do
         | 
| 68 | 
            +
                        entity.insert_at(position_new)
         | 
| 69 | 
            +
                        expect(entity.ordinal).to eq position_new
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    context 'when new position is occupied' do
         | 
| 74 | 
            +
                      let(:sorted_scope) { entities.sort_by { |entity| entity.ordinal } }
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                      it 'should correctly reorder close entities when entity moved down' do
         | 
| 77 | 
            +
                        scope = sorted_scope.take(2)
         | 
| 78 | 
            +
                        reordered_ids = scope.map(&:id).reverse! + sorted_scope.drop(2).map(&:id)
         | 
| 79 | 
            +
                        scope.first.insert_at(scope.second.ordinal)
         | 
| 80 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 81 | 
            +
                      end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                      it 'should correctly reorder close entities when entity moved up' do
         | 
| 84 | 
            +
                        scope = sorted_scope.take(2)
         | 
| 85 | 
            +
                        reordered_ids = scope.map(&:id).reverse! + sorted_scope.drop(2).map(&:id)
         | 
| 86 | 
            +
                        scope.second.insert_at(scope.first.ordinal)
         | 
| 87 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                      it 'should correctly reorder entities when entity moved down' do
         | 
| 91 | 
            +
                        scope = sorted_scope.take(TEST_ENTITIES_SCOPE_COUNT)
         | 
| 92 | 
            +
                        # [1, 2, 3, 4, 5].rotate => [2, 3, 4, 5, 1]
         | 
| 93 | 
            +
                        reordered_ids =  scope.map(&:id).rotate + sorted_scope.drop(TEST_ENTITIES_SCOPE_COUNT).map(&:id)
         | 
| 94 | 
            +
                        scope.first.insert_at(scope.last.ordinal)
         | 
| 95 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 96 | 
            +
                      end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                      it 'should correctly reorder entities when entity moved up' do
         | 
| 99 | 
            +
                        scope = sorted_scope.take(TEST_ENTITIES_SCOPE_COUNT)
         | 
| 100 | 
            +
                        # [1, 2, 3, 4, 5].rotate(-1) => [5, 1, 2, 3, 4]
         | 
| 101 | 
            +
                        reordered_ids =  scope.map(&:id).rotate(-1) + sorted_scope.drop(TEST_ENTITIES_SCOPE_COUNT).map(&:id)
         | 
| 102 | 
            +
                        scope.last.insert_at(scope.first.ordinal)
         | 
| 103 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  context 'with scope' do
         | 
| 109 | 
            +
                    let(:entities) do
         | 
| 110 | 
            +
                      entities = entities_with_random_ordinal(TEST_ENTITIES_COUNT, RANDOM_ORDINAL_MAX)
         | 
| 111 | 
            +
                      entities.each(&:save!)
         | 
| 112 | 
            +
                    end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    let(:entity) { entities.first }
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    it "shouldn't change position if ordinal haven't changed" do
         | 
| 117 | 
            +
                      expect { entity.insert_at(entity.ordinal, [entity.ordinal]) }
         | 
| 118 | 
            +
                        .not_to change { entities.map(&:ordinal) }
         | 
| 119 | 
            +
                    end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                    context 'new position is now occupied' do
         | 
| 122 | 
            +
                      let(:position_new) { RANDOM_ORDINAL_MAX + random_ordinal }
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                      it 'should not change other entities if new position is now occupied' do
         | 
| 125 | 
            +
                        expect { entity.insert_at(position_new, entity.ordinal) }
         | 
| 126 | 
            +
                          .not_to change { entities.drop(1).map(&:ordinal) }
         | 
| 127 | 
            +
                      end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                      it 'should set new position if new position is now occupied' do
         | 
| 130 | 
            +
                        entity.insert_at(position_new, entity.ordinal)
         | 
| 131 | 
            +
                        expect(entity.ordinal).to eq position_new
         | 
| 132 | 
            +
                      end
         | 
| 133 | 
            +
                    end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                    context 'when new position is occupied' do
         | 
| 136 | 
            +
                      let(:sorted_scope) { entities.sort_by { |entity| entity.ordinal } }
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                      it 'should correctly reorder close entities when entity moved down' do
         | 
| 139 | 
            +
                        scope = sorted_scope.take(2)
         | 
| 140 | 
            +
                        reordered_ids = scope.map(&:id).reverse! + sorted_scope.drop(2).map(&:id)
         | 
| 141 | 
            +
                        scope.first.insert_at(scope.second.ordinal, scope.map(&:ordinal))
         | 
| 142 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 143 | 
            +
                      end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                      it 'should correctly reorder close entities when entity moved up' do
         | 
| 146 | 
            +
                        scope = sorted_scope.take(2)
         | 
| 147 | 
            +
                        reordered_ids = scope.map(&:id).reverse! + sorted_scope.drop(2).map(&:id)
         | 
| 148 | 
            +
                        scope.second.insert_at(scope.first.ordinal, scope.map(&:ordinal))
         | 
| 149 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 150 | 
            +
                      end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                      it 'should correctly reorder entities when entity moved down' do
         | 
| 153 | 
            +
                        scope = sorted_scope.take(TEST_ENTITIES_SCOPE_COUNT)
         | 
| 154 | 
            +
                        # [1, 2, 3, 4, 5].rotate => [2, 3, 4, 5, 1]
         | 
| 155 | 
            +
                        reordered_ids =  scope.map(&:id).rotate + sorted_scope.drop(TEST_ENTITIES_SCOPE_COUNT).map(&:id)
         | 
| 156 | 
            +
                        scope.first.insert_at(scope.last.ordinal, scope.map(&:ordinal))
         | 
| 157 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 158 | 
            +
                      end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                      it 'should correctly reorder entities when entity moved up' do
         | 
| 161 | 
            +
                        scope = sorted_scope.take(TEST_ENTITIES_SCOPE_COUNT)
         | 
| 162 | 
            +
                        # [1, 2, 3, 4, 5].rotate(-1) => [5, 1, 2, 3, 4]
         | 
| 163 | 
            +
                        reordered_ids =  scope.map(&:id).rotate(-1) + sorted_scope.drop(TEST_ENTITIES_SCOPE_COUNT).map(&:id)
         | 
| 164 | 
            +
                        scope.last.insert_at(scope.first.ordinal, scope.map(&:ordinal))
         | 
| 165 | 
            +
                        expect(Entity.order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 166 | 
            +
                      end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                      it 'should reorder entities only from scope when entity moved down' do
         | 
| 169 | 
            +
                        entities.shuffle!
         | 
| 170 | 
            +
                        scope = entities.take(TEST_ENTITIES_SCOPE_COUNT).sort_by { |entity| entity.ordinal }
         | 
| 171 | 
            +
                        # [1, 2, 3, 4, 5].rotate => [2, 3, 4, 5, 1]
         | 
| 172 | 
            +
                        reordered_ids =  scope.map(&:id).rotate
         | 
| 173 | 
            +
                        expect { scope.first.insert_at(scope.last.ordinal, scope.map(&:ordinal)) }
         | 
| 174 | 
            +
                          .not_to change { entities.drop(TEST_ENTITIES_SCOPE_COUNT).map(&:ordinal) }
         | 
| 175 | 
            +
                        expect(Entity.where(id: reordered_ids).order(:ordinal).map(&:id)).to eq reordered_ids
         | 
| 176 | 
            +
                      end
         | 
| 177 | 
            +
                    end
         | 
| 178 | 
            +
                  end
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
              end
         | 
| 181 | 
            +
            end
         | 
    
        data/spec/spec_helper.rb
    ADDED
    
    
    
        metadata
    ADDED
    
    | @@ -0,0 +1,158 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: activeadmin-orderable-table
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Max Hordiichuk
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: bin
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2017-03-15 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: bundler
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '1.10'
         | 
| 20 | 
            +
              type: :development
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '1.10'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rspec-rails
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '3.5'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '3.5'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: test-unit
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - "~>"
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '3.0'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - "~>"
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '3.0'
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: sqlite3
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - "~>"
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '1.3'
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - "~>"
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: '1.3'
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: sass-rails
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - ">="
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: '0'
         | 
| 76 | 
            +
              type: :development
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - ">="
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: '0'
         | 
| 83 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 84 | 
            +
              name: activerecord
         | 
| 85 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 | 
            +
                requirements:
         | 
| 87 | 
            +
                - - ">="
         | 
| 88 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 89 | 
            +
                    version: '0'
         | 
| 90 | 
            +
              type: :development
         | 
| 91 | 
            +
              prerelease: false
         | 
| 92 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 | 
            +
                requirements:
         | 
| 94 | 
            +
                - - ">="
         | 
| 95 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            +
                    version: '0'
         | 
| 97 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 98 | 
            +
              name: sortable-rails
         | 
| 99 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 | 
            +
                requirements:
         | 
| 101 | 
            +
                - - "~>"
         | 
| 102 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            +
                    version: '1.4'
         | 
| 104 | 
            +
              type: :runtime
         | 
| 105 | 
            +
              prerelease: false
         | 
| 106 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 | 
            +
                requirements:
         | 
| 108 | 
            +
                - - "~>"
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            +
                    version: '1.4'
         | 
| 111 | 
            +
            description: Drag and drop order interface for ActiveAdmin tables
         | 
| 112 | 
            +
            email: hordijchuk.m.i@gmail.com
         | 
| 113 | 
            +
            executables: []
         | 
| 114 | 
            +
            extensions: []
         | 
| 115 | 
            +
            extra_rdoc_files: []
         | 
| 116 | 
            +
            files:
         | 
| 117 | 
            +
            - ".gitignore"
         | 
| 118 | 
            +
            - ".rspec"
         | 
| 119 | 
            +
            - Gemfile
         | 
| 120 | 
            +
            - LICENSE.txt
         | 
| 121 | 
            +
            - README.md
         | 
| 122 | 
            +
            - activeadmin-orderable-table.gemspec
         | 
| 123 | 
            +
            - app/assets/javascripts/activeadmin-orderable-table.js
         | 
| 124 | 
            +
            - app/assets/stylesheets/activeadmin-orderable-table.css
         | 
| 125 | 
            +
            - lib/active_admin/orderable_table.rb
         | 
| 126 | 
            +
            - lib/active_record/acts_as.rb
         | 
| 127 | 
            +
            - lib/active_record/acts_as/orderable_table.rb
         | 
| 128 | 
            +
            - lib/activeadmin-orderable-table.rb
         | 
| 129 | 
            +
            - lib/activeadmin-orderable-table/version.rb
         | 
| 130 | 
            +
            - spec/db_helper.rb
         | 
| 131 | 
            +
            - spec/lib/active_record/acts_as/orderable_table_spec.rb
         | 
| 132 | 
            +
            - spec/spec_helper.rb
         | 
| 133 | 
            +
            - spec/support/utilities.rb
         | 
| 134 | 
            +
            homepage: https://github.com/MaximHordijchuk/activeadmin-orderable-table
         | 
| 135 | 
            +
            licenses:
         | 
| 136 | 
            +
            - MIT
         | 
| 137 | 
            +
            metadata: {}
         | 
| 138 | 
            +
            post_install_message: 
         | 
| 139 | 
            +
            rdoc_options: []
         | 
| 140 | 
            +
            require_paths:
         | 
| 141 | 
            +
            - lib
         | 
| 142 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 143 | 
            +
              requirements:
         | 
| 144 | 
            +
              - - ">="
         | 
| 145 | 
            +
                - !ruby/object:Gem::Version
         | 
| 146 | 
            +
                  version: '0'
         | 
| 147 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 148 | 
            +
              requirements:
         | 
| 149 | 
            +
              - - ">="
         | 
| 150 | 
            +
                - !ruby/object:Gem::Version
         | 
| 151 | 
            +
                  version: '0'
         | 
| 152 | 
            +
            requirements: []
         | 
| 153 | 
            +
            rubyforge_project: 
         | 
| 154 | 
            +
            rubygems_version: 2.6.10
         | 
| 155 | 
            +
            signing_key: 
         | 
| 156 | 
            +
            specification_version: 4
         | 
| 157 | 
            +
            summary: Order ActiveAdmin tables
         | 
| 158 | 
            +
            test_files: []
         |