Question

I have a simple Rails 3 app where a Goal has many Objectives. In my views, I allow the user to-reorder the Objectives for any given Goal, and I am using the acts_as_list gem to achieve some of this functionality.

Goal model:

class Goal < ActiveRecord::Base
  attr_accessible :name, :description

  has_many :objectives, :order => :position, :dependent => :destroy
end

Objective model:

class Objective < ActiveRecord::Base
  attr_accessible :name, :description, :position

  belongs_to :goal

  acts_as_list :scope => :goal
end

I also want to allow the user to change the Goal that a particular Objective is associated with. I would have assumed that the acts_as_list gem would reset the position column whenever an Objective's Goal is changed (because I defined scope => :goal), but instead it just retains the current position.

For me, this is undesirable, because the position no longer makes sense in the context of a new Goal. I would rather that the position gets reset, and the Objective is moved to the bottom of the new Goal that it is associated with. So I wrote this method to occur on before_save in the Objective model:

  before_update :reset_position

  def reset_position
    if self.goal_id_changed?
      self.move_to_bottom #acts_as_list method
    end
  end

Unfortunately, this results in a stack level too deep error when I attempt to save. Any ideas for how I can fix this?

Was it helpful?

Solution

Okay, I ended up re-writing the reset_position to what is shown below, since acts_as_list clearly does not handle association changes.

before_update :reset_position

def reset_position
  if self.goal_id_changed?
    self.position = self.goal.objectives.count > 0 ? self.goal.objectives.last.position + 1 : 1
  end
end

Basically, it moves the Objective to the bottom of the Objective list when it is associated with a different Goal. Seems to work.

OTHER TIPS

I ld say this is due to move_to_bottom self trying to save the record. So writing your own version of this method would be the way to go in my opinion. Start from the current acts_as_list method and develop your own variation without the save.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top