GithubHelp home page GithubHelp logo

sortifiable's Introduction

Sortifiable

Build Status Dependency Status

This gem provides an acts_as_list compatible capability for sorting and reordering a number of objects in a list. The class that has this specified needs to have a +position+ column defined as an integer on the mapped database table.

This gem requires ActiveRecord 3.0 as it has been refactored to use the scope methods and query interface introduced with Ruby on Rails 3.0

Example

class TodoList < ActiveRecord::Base
  has_many :todo_items, :order => "position"
end

class TodoItem < ActiveRecord::Base
  belongs_to :todo_list
  acts_as_list :scope => :todo_list
end

todo_list.first.move_to_bottom
todo_list.last.move_higher

Contributions

Bug fixes and new feature patches are welcome. Please provide tests and documentation wherever possible - without them it is unlikely your patch will be accepted. If you're fixing a bug then a failing test for the bug is essential. Once you have completed your patch please open a GitHub pull request and I will review it and respond as quickly as possible.

Thanks to the following people for their contributions:

  • Manuel Meurer
  • Reinier de Lange

Copyright (c) 2011 Andrew White, released under the MIT license

sortifiable's People

Contributors

manuelmeurer avatar pixeltrix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

sortifiable's Issues

Weird problem with join model and dependent: :destroy

Hi,
I'm using sortifiable on Rails 3.2.1.

My model setup is like this:

class MediaFile < ActiveRecord::Base
  has_many :playlist_media_files, dependent: :destroy
  has_many :playlists, through: :playlist_media_files

# playlist_id, media_file_id, position
class PlaylistMediaFile < ActiveRecord::Base
  # WARNING: this will not delete this model record in case the MediaFile gets destroyed
  # and position attribute is not blank, but instead tries only to decrement this model position field.
  # As result  *_destroy callbacks for this model never runs, record will persist and
  # playlists.updated_at does not get touched, nor the counter cache decremented
  # (see belongs_to declaration below)
  acts_as_list scope: :playlist_id

  belongs_to :playlist, touch: true, counter_cache: true
  belongs_to :media_file

playlist_media_files has a column position.

When I try to destroy a MediaFile instance, the dependent: :destroy should wipe also the related PlaylistMediaFile, however if position is not blank acts_as_list's before_destroy kicks in, but the PlaylistMediaFile instance won't continue its way to get destroyed, instead I see this:

(8.2ms)  SELECT id FROM `playlist_media_files` WHERE `playlist_media_files`.`playlist_id` = 7 AND (`position` IS NOT NULL) ORDER BY position FOR UPDATE
SQL (0.4ms)  UPDATE `playlist_media_files` SET `position` = `position` - 1 WHERE `playlist_media_files`.`playlist_id` = 7 AND (`position` IS NOT NULL) AND (`position` > 2292) ORDER BY position
# should delete the playlist_media_files record here, but it's not happening
SQL (0.4ms)  DELETE FROM `media_files` WHERE `media_files`.`type` IN ('AudioFile') AND `media_files`.`id` = 594341

Moving an existing item "into the scope" should add it to the bottom.

Example:

class List < AR::Base
  has_many :items
end

class Item < AR::Base
  belongs_to :list

  acts_as_list, :scope => :list
end

# Existing lists:
# #<List id: 1>
# #<List id: 2>

# Existing items:
# #<Item id: 1, list_id: 1, position: 1>
# #<Item id: 2, list_id: 1, position: 2>
# #<Item id: 3, list_id: 2, position: 1>

item = Item.find(3)
item.list = List.find(1)
item.save!

I would expect:

#<Item id: 1, list_id: 1, position: 1>
#<Item id: 2, list_id: 1, position: 2>
#<Item id: 3, list_id: 1, position: 3>

Instead:

#<Item id: 1, list_id: 1, position: 1>
#<Item id: 2, list_id: 1, position: 2>
#<Item id: 3, list_id: 1, position: 1>

Same with moving an item out of the list, I would expect the lower items to "close the gap".
Do you agree?
If yes, and if you would accept a pull request, I would be willing to work on that.

Bug in insert_at when moving down

The list order becomes inconsistent when an item is moved within the list from a position x to a position less then x.

If we have a list of a few items like this, ordered by 'position'

a = <Item postion: 1>
b = <Item postion: 2>
c = <Item postion: 3>
d = <Item postion: 4>
e = <Item postion: 5>

And we want to move b in between d and e, i would do b.insert_at e.postion
This should decrement c.position and d.position and make b.postion 4. However it results in this:

a = <Item postion: 1>
c = <Item postion: 2>
d = <Item postion: 3>
b = <Item postion: 5>
e = <Item postion: 5>

I'd say something like this should work:

176: new_position = position < current_position ? position : position - 1
and 
178: WHEN #{quoted_position_column} = #{current_position} THEN #{new_position}

update_position using wrong scope

Currently this method uses list_class to perform the update.

We are using a paranoid delete solution that defined a default scope: where(:deleted_at => nil).

This means update_position should use base_scope instead because otherwise deleted nodes will not be updated.

We want deleted nodes to be included in the list because we want to be able to restore them to their original position.

Can you change this? It seems like a bug to me.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.