Rails 4:如何找到某个属性等于某个值的所有行并更改该值?

Rails 4: how to find all rows where a certain attribute equals a certain value and change that value?

在我们的Rails4 app中,有四种模式:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
end

class Post < ActiveRecord::Base
    belongs_to :calendar
end

以下是相应的迁移:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :first_name
      t.string :last_name
      t.string :email
      t.integer :total_calendar_count
      t.integer :owned_calendar_count

      t.timestamps null: false
    end
  end
end

class CreateAdministrations < ActiveRecord::Migration
  def change
    create_table :administrations do |t|
      t.references :user, index: true, foreign_key: true
      t.references :calendar, index: true, foreign_key: true
      t.string :role

      t.timestamps null: false
    end
  end
end

class CreateCalendars < ActiveRecord::Migration
  def change
    create_table :calendars do |t|
      t.string :name

      t.timestamps null: false
    end
  end
end

class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
        t.references :calendar, index: true, foreign_key: true
        t.date :date
        t.time :time
        t.string :focus
        t.string :format
        t.string :blog_title
        t.text :long_copy
        t.text :short_copy
        t.string :link
        t.string :hashtag
        t.string :media
        t.float :promotion
        t.string :target
        t.integer :approval
        t.text :comment

      t.timestamps null: false
    end
  end
end

在该应用程序中,我们为用户提供了退出他们所属日历的机会,为此,我们 destroy 连接 table 连接中的管理行给定用户到给定的日历。

发生这种情况时,我们想做几件事:

我们相信这会发生在四个部分:

  1. Adminstration table 中,找到所有 @administration 个实例,其中 calendar_id 等于 calendar.id 并将所有提取的行存储到 变量,例如 @administrations
  2. 检查@administrations是否为真
  3. 如果@administrations为零,销毁@administration.calendar
  4. 如果 @administrations 为真,为 @administrations
  5. 中的每个 @administration 实例更改 @administration.role

我们知道如何使用简单的运算符执行 2,使用我们已有的 calendars#destroy 操作执行 3,使用块执行 4,但我们不知道如何编写代码 1。

有什么想法吗?

使用此查询:

@administration = Administration.joins(:calendar)

您可以在 Administration 模型中的 after_destroy 回调中执行此操作。

class Administration
  # existing relationships / methods

  # new code
  after_destroy :your_stuff

  private

  def your_stuff # pick a more suitable method name
    cal = self.calendar
    other_admins = cal.administrators.where("id != ?", self.id)

    if other_admins.exists?
      new_role_value = "Something"
      other_admins.update_all(role: new_role_value)
      # ^ or iterate through all admins in case logic is more complicated
    elsif Calendar.exists?(id: cal.id)
      cal.destroy 
    end
  end
end

我希望代码是不言自明的。

我已经添加了一些预防措施来避免无限循环。