【问题标题】:Method to change resource attribute based on nested resource attributes基于嵌套资源属性改变资源属性的方法
【发布时间】:2014-04-28 22:23:51
【问题描述】:

我有一个 Rails 4 应用程序。相当简单的问题;我写了一个方法,但是我不知道它应该去哪里以及如何调用它。

我有一个资源Goals 和一个嵌套资源Tasks(即每个目标都有任务)。所有这部分工作正常。

我想要做的是设置它,以便一旦goal 的每个taskstatus 为真,则该goalstatus 变为真。

我想使用的方法的内容是:

completed = true
@goal.tasks.each do |t|
  if !t.status?
    completed = false
  end
end
if completed?
  @goal.status = true
end

检查goal 的所有任务是否具有status:true,如果是,则将goalstatus 也更改为true。

我的想法是将该方法放在Goal 模型中,但这是我能猜到的。

  • 方法去哪儿了? (是不是像我想的那样在模型中?)
  • 我如何(/我需要)调用该方法?

(我知道该方法可能有一些小的语法错误,但一旦我可以实际使用它,我就可以对其进行测试和调整!)

感谢任何人花时间看一看。

【问题讨论】:

    标签: ruby-on-rails model nested-attributes


    【解决方案1】:

    您可以按如下方式简化您的功能:

    @goal.status = @goals.tasks.map(&:complete).all?
    

    假设您想尽快知道您的goal 是否完整,您需要将此功能放入您的Task 模型中。你可以这样做:

    def Task < ActiveRecord::Base
      belongs_to :goal
    
      after_save :goal_completed
    
      def goal_completed
        if self.goal.tasks.map(&:completed).all?
          self.goal.update_attribute(:completed, true)
        end
      end
    end
    

    如您所见,如果您有很多 tasks 与一个 goal,这可能会很快变得昂贵,因为每次@ 987654329@ 已保存。因此,对于更大的数据库,我建议为每个目标保留已完成任务的计数。 (这实际上与我在我的一个项目中实现的非常相似。)

    首先,您需要在goals 中为tasks_count 添加一个计数器缓存列(如果您还没有),然后在goals 中添加一个名为completed_tasks_count 的列,或类似的那。确保它们都默认为零。

    def Goal < ActiveRecord::Base
      has_many :tasks, inverse_of: :goal, counter_cache: true
    end
    
    def Task < ActiveRecord::Base
      belongs_to :goal, inverse_of: :tasks
    
      after_initial :set_completed_tasks_count, on: new
      around_save :goal_complete
    
      def set_completed_tasks_count
        self.completed = false if self.new_record? && self.completed.nil?
      end
    
      def goal_complete
        yield
        if self.completed? && !self.completed_was
          self.review.increment!(:completed_tasks_count)
        elsif (!self.completed? && self.completed_was) || self.marked_for_destruction?
          self.review.decrement!(:completed_tasks_count)
        end
      end
    end
    

    希望这会有所帮助。编码愉快!

    【讨论】:

    • 谢谢,这是一个比我想象的更全面的解决方案!