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 连接中的管理行给定用户到给定的日历。
发生这种情况时,我们想做几件事:
- 检查是否有其他用户属于这个日历
- 如果有的话,我们要
update
把它们的值administration.role
- 如果没有,我们想要
destroy
整个 calendar
我们相信这会发生在四个部分:
- 在
Adminstration
table 中,找到所有 @administration
个实例,其中
calendar_id
等于 calendar.id
并将所有提取的行存储到
变量,例如 @administrations
- 检查
@administrations
是否为真
- 如果
@administrations
为零,销毁@administration.calendar
- 如果
@administrations
为真,为 @administrations
中的每个 @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
我希望代码是不言自明的。
我已经添加了一些预防措施来避免无限循环。
在我们的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 连接中的管理行给定用户到给定的日历。
发生这种情况时,我们想做几件事:
- 检查是否有其他用户属于这个日历
- 如果有的话,我们要
update
把它们的值administration.role
- 如果没有,我们想要
destroy
整个calendar
我们相信这会发生在四个部分:
- 在
Adminstration
table 中,找到所有@administration
个实例,其中calendar_id
等于calendar.id
并将所有提取的行存储到 变量,例如@administrations
- 检查
@administrations
是否为真 - 如果
@administrations
为零,销毁@administration.calendar
- 如果
@administrations
为真,为@administrations
中的每个
@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
我希望代码是不言自明的。
我已经添加了一些预防措施来避免无限循环。