Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ordering of children when there are two possible parent models. #172

Closed
vietqhoang opened this issue Oct 1, 2015 · 1 comment
Closed

Comments

@vietqhoang
Copy link

Environment: Rails 3.2.22, acts_as_list 0.7.2

The scenario is the following:

Models: Book, Magazine, Page

Associations:
Book, Magazine have_many Pages
Page belongs_to Book OR Magazine

acts_as_list Implementation:
The following is added to the Page model

acts_as_list scope: :book
acts_as_list scope: :magazine

What happens:
When adding a Page to either Book or Magazine, it shifts all pages within the same parent association above it by two positions instead of the expected one. In other words there is a gap of one space between the newly added Page and the next page in the order. In addition this also shifts the position of all Pages in the related parent model, but not associated to the parent. The Pages that are shifted match the position and above the position selected for the original Page.

How I expect it to work:
When adding a new Page it should only shift the positions of the pages with the same parent association. It should not affect Pages which are not in the same parent scope. It should also only shift the position of any pages above it by one.

@fabn
Copy link
Contributor

fabn commented Dec 16, 2015

If I understand the situation you are using acts_as_list twice for the same model, is that correct?

I think this is because they uses the same position column. This is not supported by this gem because aal callbacks does not have a scope dependent name, thus the behavior is unpredictable in current codebase.

I'd say that you could try by using different named position columns (e.g. book_position and magazine_position) but it will likely won't work because last acts_as_list call will override previous callbacks.

The solution you can use is to define an intermediate model to manage positions something like

class Ordering < ActiveRecord::Base
  belongs_to :sortable, polymorphic: true
  belongs_to :page

  # Every record is sorted scoped to its page and its sortable type
  acts_as_list scope: [:page_id, :sortable_type]

end

class Page < ActiveRecord::Base
  has_many :orderings, -> { order :position }, dependent: :destroy
  has_many :book_orderings, -> { where(sortable_type: Book).order(:position) }, class_name: Ordering
  has_many :magazine_orderings, -> { where(sortable_type: Magazine).order(:position) }, class_name: Ordering
  has_many :books, through: :orderings, source: :sortable, source_type: Book
  has_many :magazines, through: :orderings, source: :sortable, source_type: Magazine

end

I'm going to close this because I don't think this feature can be implemented easily and a workaround exist.

@fabn fabn closed this as completed Dec 16, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants