-
-
Notifications
You must be signed in to change notification settings - Fork 357
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
Issue when reordering within scopes #131
Comments
I'm investigating this issue and I found out that the issue is triggered by check_scope method. I've changed the method in this way to debug the problem def check_scope
if scope_changed?
position = send(position_column)
db_position = self.class.where(id: id).select(position_column).first[position_column]
warn "For record #{id} db_position is different #{position} != #{db_position}" if db_position != position
# self[position_column] = db_position
swap_changed_attributes
send('decrement_positions_on_lower_items') if lower_item
swap_changed_attributes
send("add_to_list_#{add_new_at}")
end
end and in the current codebase the warning is triggered more than once, so there must be something wrong in method implementation. If I enable the I'll try to create a test case for this particolar issue, @swanandp is a problem if I add ancestry gem in Gemfile to reproduce the issue? |
Hi @swanandp could you please send me a feedback on this issue (and related PR). Thanks. |
I can confirm this issue exists. I've applied @fabn 's fix as a temp monkey patch and can confirm it resolves the issue. Waiting for PR to be resolved. |
Hi @fabn, you're still working on this one by the looks? |
@brendon I'm not working on this in this moment. I rebased my original pr couple of weeks ago but currently it's not mergeable anymore. |
Ok, let's leave it open. I use ancestry too. I haven't noticed problems but I actually override the following to disable the scope detection, then have a few methods to move items around instead: acts_as_tree :cache_depth => true
# MySQL sorts NULL's first anyway, so we override ancestry's scopes
scope :ordered_by_ancestry, lambda { reorder("#{table_name}.#{ancestry_column}") }
scope :ordered_by_ancestry_and, lambda { |order| reorder("#{table_name}.#{ancestry_column}, #{order}") }
acts_as_list
# There is a bug (as of acts_as_list 0.7.2) that causes some reordering issues when moving tree nodes.
# Setting the scope manually, and setting scope_changed? to false avoids the scope changing logic, and
# avoids the bug. We handle moving nodes around the tree via the `move` method.
def scope_condition
{ :ancestry => read_attribute(:ancestry) }
end
def scope_changed?
false
end Let me know if you want to see those methods. |
Hi @fabn, I'd be interested to see if the work on @scope_changed fixed this bug. Could you let me know? |
@brendon rebased again the PR and the fix introduced in 1cf515d9fccc473409fc729ae394493aebe1ba86 is still necessary. Without that commit tests will fail. |
Hi @fabn, given that the Rails 5 compatible attribute swapper is now in master, let's try to close this one off with a solution around that existing code. I think there's also no PR for this yet. Can you open one and that'll give us a working point. :) |
Hi @fabn, just reviewing my code, I've been able to remove my scope overrides and am now about to just do this:
This is my # Expects an array of sibling_ids (strings), and a parent component_instance
# This method relies on scope_changed? in acts_as_list to do the magic of positioning
def move(parent, sibling_ids = [], scope = parent.children.current)
self.parent = parent
if sibling_ids.present?
raise ArgumentError.new('self.id must exist in sibling_ids') unless sibling_ids.include?(id.to_s)
if sibling_ids.size == 1
self.position = 1
elsif sibling_ids.size > 1
position_among_siblings = sibling_ids.index(id.to_s)
reference = scope.offset(position_among_siblings).first
self.position = reference.position if reference
end
end
save
end |
Hi all, I am also expecting similar issue with acts_as_paranoid and acts_as_list. |
I have just experienced this issue using I have no experience of the internals of either of these gems, but, getting this bug fixed is pretty important to me. If I take a copy of the PR and try to fix the merge conflicts would someone be available to review? (not sure that I'll be up to it, but I can try!) Alternatively, @brendon I didn't quite follow in your comment above are you saying that you are able to use Thanks for the great gems! |
Hi @patrickdavey, I'm happy for you to have a go at getting the patch working with master. Correct, in that I get by with just the code mentioned above. I had a look and I also use this: # MySQL sorts NULL's first anyway, so we override ancestry's scopes
scope :ordered_by_ancestry, -> { reorder("component_instances.ancestry") }
scope :ordered_by_ancestry_and, -> (order) { reorder("component_instances.ancestry, #{order}") } That might help you too, but it's not got much to do with the main problem. Keep me posted on your progress :) |
@brendon I have had a play with this, but, I haven't got very far. We then went with If I get some more time I'll try and fix it. |
All good @patrickdavey. I remember looking at |
Well @brendon I ran into a nasty bug which brought production to, while not a halt, a bad place ;) So.. now I'm thinking I shouldn't have cheated on |
Lol! Come back home man! |
Having the same issue as OP with acts_as_list + ancestry. Taking the def scope_changed?
return false unless ancestry_changed?
return true unless ancestry_change.all? # return true if either new or old value is nil
# 'scope' is the immediate parent (the last position of the ancestry key),
# so let's compare the previous value to see if it has changed
ancestry_change[0].split('/')[-1] != ancestry_change[1].split('/')[-1]
end |
Hi @cipater, can you come up with a failing test for |
@fabn, not sure what to do with this one. Should we close it for now? |
Closing this for now. |
I'm using this gem in conjunction with ancestry gem in the following model:
However I found an edge case with this usage (suggested by ancestry wiki)
Given that every list is scoped to the ancestry column (i.e. siblings nodes are in the same list), when I move a node with children, children list is reordered in a wrong way. Here is a sample tree
When I move Category 6 to root level their children assumes a wrong position
As you can see both 6 and 7 have position set to 1 after the transaction
Here is another example with two errors after transaction (only the final tree)
Here node 11 and 12 have the same position and node 10 (the node I moved) has position set to 3.
I think this behavior is due to the fact that ancestry gem triggers updates for the ancestry column for all children nodes and when they execute acts_as_list callbacks, but since their position is not changed they fail to update lists.
Query log
Spec code is (more or less) the following:
and here is the most relevant and commented output (full output is here):
Demo app
I've uploaded a demo app to reproduce the problem, you can find it here: https://github.com/fabn/category.
You can execute specs with a couple of env variables to control output and size of the generated tree, for instance
will generate the latest tree in the example above.
The text was updated successfully, but these errors were encountered: