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

时间:2015-07-09 04:59:53

标签: ruby-on-rails ruby-on-rails-4 model-view-controller relational-database rails-activerecord

在我们的Rails 4应用程序中,有四种模式:

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联接表中的管理行将给定用户绑定到给定日历。< / p>

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

  • 检查是否有其他用户属于此日历
  • 如果有,我们希望update administration.role
  • 的价值
  • 如果没有,我们希望destroy整个calendar

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

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

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

    有什么想法吗?

2 个答案:

答案 0 :(得分:1)

使用此查询:

@administration = Administration.joins(:calendar)

答案 1 :(得分:1)

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

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

我希望代码不言自明。

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