- B
- D
- I
- N
- P
- R
- S
- T
- U
实例公共方法
becomes(klass) Link
返回指定klass的一个实例,并具有当前记录的属性。这在与单表继承(STI)结构结合使用时非常有用,当你希望一个子类表现得像父类一样。这可以与Action Pack中的记录识别一起使用,例如,允许Client < Company执行类似render partial: @client.becomes(Company)的操作,以便使用companies/company的部分而不是clients/client来渲染该实例。
注意:新实例将共享与原始类相同的属性链接。因此,STI列值将保持不变。对任一实例上的属性所做的任何更改都将影响两个实例。这包括新实例执行的任何属性初始化。
如果你也想更改STI列,请改用becomes!。
# File activerecord/lib/active_record/persistence.rb, line 487 def becomes(klass) became = klass.allocate became.send(:initialize) do |becoming| @attributes.reverse_merge!(becoming.instance_variable_get(:@attributes)) becoming.instance_variable_set(:@attributes, @attributes) becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil) becoming.instance_variable_set(:@new_record, new_record?) becoming.instance_variable_set(:@previously_new_record, previously_new_record?) becoming.instance_variable_set(:@destroyed, destroyed?) becoming.errors.copy!(errors) end became end
becomes!(klass) Link
becomes的包装器,它还会更改实例的STI列值。这在你希望将更改的类持久化到数据库时特别有用。
注意:旧实例的STI列值也会被更改,因为这两个对象共享相同的属性集。
decrement(attribute, by = 1) Link
如果attribute为nil,则将其初始化为零,然后减去传递的by值(默认为1)。递减操作直接在底层属性上执行,不调用setter。仅对数字型属性有意义。返回self。
decrement!(attribute, by = 1, touch: nil) Link
decrement的包装器,它将更新写入数据库。仅更新attribute;记录本身未保存。这意味着任何其他修改过的属性仍然是脏的。Validations和回调将被跳过。支持update_counters中的touch选项,请参见该方法了解更多。返回self。
delete() Link
在数据库中删除记录,并冻结该实例,以表明不应再进行任何更改(因为它们无法持久化)。返回冻结的实例。
该行将仅通过对记录主键执行SQL DELETE语句来删除,不会执行任何回调。
请注意,这也会删除标记为#readonly?的记录。
要强制执行对象的before_destroy和after_destroy回调或任何:dependent关联选项,请使用destroy。
destroy() Link
在数据库中删除记录,并冻结该实例,以表明不应再进行任何更改(因为它们无法持久化)。
与destroy相关联的是一系列回调。如果before_destroy回调抛出:abort,则操作将被取消,destroy返回false。有关详细信息,请参阅ActiveRecord::Callbacks。
destroy!() Link
在数据库中删除记录,并冻结该实例,以表明不应再进行任何更改(因为它们无法持久化)。
与destroy!相关联的是一系列回调。如果before_destroy回调抛出:abort,则操作将被取消,destroy!将引发ActiveRecord::RecordNotDestroyed。有关详细信息,请参阅ActiveRecord::Callbacks。
destroyed?() Link
如果此对象已被销毁,则返回true,否则返回false。
increment(attribute, by = 1) Link
如果attribute为nil,则将其初始化为零,然后加上传递的by值(默认为1)。递增操作直接在底层属性上执行,不调用setter。仅对数字型属性有意义。返回self。
increment!(attribute, by = 1, touch: nil) Link
increment的包装器,它将更新写入数据库。仅更新attribute;记录本身未保存。这意味着任何其他修改过的属性仍然是脏的。Validations和回调将被跳过。支持update_counters中的touch选项,请参见该方法了解更多。
当调用新对象时,或者当至少一个属性被标记为只读时,此方法会引发ActiveRecord::ActiveRecordError。
返回 self。
# File activerecord/lib/active_record/persistence.rb, line 672 def increment!(attribute, by = 1, touch: nil) raise ActiveRecordError, "cannot update a new record" if new_record? raise ActiveRecordError, "cannot update a destroyed record" if destroyed? increment(attribute, by) change = public_send(attribute) - (public_send(:"#{attribute}_in_database") || 0) self.class.update_counters(id, attribute => change, touch: touch) public_send(:"clear_#{attribute}_change") self end
new_record?() Link
如果此对象尚未保存,则返回true——也就是说,数据库中尚不存在该对象的记录;否则,返回false。
persisted?() Link
如果记录已持久化,则返回true,即它不是新记录且未被销毁,否则返回false。
previously_new_record?() Link
如果此对象刚刚被创建,则返回true——也就是说,在上次更新或删除之前,该对象在数据库中不存在,并且new_record?会返回true。
previously_persisted?() Link
如果此对象先前已持久化但现在已被删除,则返回true。
reload(options = nil) Link
从数据库重新加载记录。
此方法通过主键(可以手动分配)查找记录,并就地修改接收者
account = Account.new # => #<Account id: nil, email: nil> account.id = 1 account.reload # Account Load (1.2ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1 [["id", 1]] # => #<Account id: 1, email: 'account@example.com'>
Attributes将从数据库重新加载,缓存将被清除,特别是关联缓存和QueryCache。
如果记录在数据库中不再存在,将引发ActiveRecord::RecordNotFound。否则,除了就地修改外,该方法还将返回self以方便使用。
可选的:lock标志选项允许您锁定重新加载的记录
reload(lock: true) # reload with pessimistic locking
重新加载通常在测试套件中用于测试某项内容是否实际写入数据库,或者当某个操作修改数据库中的相应行但未修改内存中的对象时使用。
assert account.deposit!(25) assert_equal 25, account.credit # check it is updated in memory assert_equal 25, account.reload.credit # check it is also persisted
另一个常见的用例是乐观锁定处理。
def with_optimistic_retry begin yield rescue ActiveRecord::StaleObjectError begin # Reload lock_version in particular. reload rescue ActiveRecord::RecordNotFound # If the record is gone there is nothing to do. else retry end end end
# File activerecord/lib/active_record/persistence.rb, line 773 def reload(options = nil) self.class.connection_pool.clear_query_cache fresh_object = if apply_scoping?(options) _find_record((options || {}).merge(all_queries: true)) else self.class.unscoped { _find_record(options) } end @association_cache = fresh_object.instance_variable_get(:@association_cache) @association_cache.each_value { |association| association.owner = self } @attributes = fresh_object.instance_variable_get(:@attributes) @new_record = false @previously_new_record = false self end
save(**options) Link
保存模型。
如果模型是新的,则会在数据库中创建一个记录,否则将更新现有记录。
默认情况下,save始终运行验证。如果任何验证失败,操作将被取消,save将返回false,并且记录将不会被保存。但是,如果您提供validate: false,则会完全绕过验证。有关更多信息,请参阅ActiveRecord::Validations。
默认情况下,save还将updated_at/updated_on属性设置为当前时间。但是,如果您提供touch: false,则不会更新这些时间戳。
与save相关联的是一系列回调。如果任何before_*回调抛出:abort,操作将被取消,save将返回false。有关详细信息,请参阅ActiveRecord::Callbacks。
Attributes标记为只读的,如果在更新记录时,它们将被静默忽略。
save!(**options) Link
保存模型。
如果模型是新的,则会在数据库中创建一个记录,否则将更新现有记录。
默认情况下,save!始终运行验证。如果任何验证失败,将引发ActiveRecord::RecordInvalid,并且记录将不会被保存。但是,如果您提供validate: false,则会完全绕过验证。有关更多信息,请参阅ActiveRecord::Validations。
默认情况下,save!还将updated_at/updated_on属性设置为当前时间。但是,如果您提供touch: false,则不会更新这些时间戳。
与save!相关联的是一系列回调。如果任何before_*回调抛出:abort,操作将被取消,save!将引发ActiveRecord::RecordNotSaved。有关详细信息,请参阅ActiveRecord::Callbacks。
Attributes标记为只读的,如果在更新记录时,它们将被静默忽略。
除非发生错误,否则返回true。
toggle(attribute) Link
将attribute设置为attribute?的布尔相反值。因此,如果谓词返回true,则属性将变为false。此方法直接切换底层值而不调用任何setter。返回self。
示例
user = User.first user.banned? # => false user.toggle(:banned) user.banned? # => true
toggle!(attribute) Link
toggle的包装器,它会保存记录。此方法与其非bang版本不同之处在于它通过了属性setter。保存不受验证检查。如果记录能够保存,则返回true。
touch(*names, time: nil) Link
保存记录,并将updated_at/on属性设置为当前时间或指定时间。请注意,不会执行任何验证,并且只执行after_touch、after_commit和after_rollback回调。
此方法可以传递属性名称和可选的时间参数。如果传递了属性名称,它们将与updated_at/on属性一起更新。如果未传递时间参数,则默认使用当前时间。
product.touch # updates updated_at/on with current time product.touch(time: Time.new(2015, 2, 16, 0, 0, 0)) # updates updated_at/on with specified time product.touch(:designed_at) # updates the designed_at attribute and updated_at/on product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
如果与belongs_to一起使用,则touch将调用关联对象的touch方法。
class Brake < ActiveRecord::Base belongs_to :car, touch: true end class Car < ActiveRecord::Base belongs_to :corporation, touch: true end # triggers @brake.car.touch and @brake.car.corporation.touch @brake.touch
请注意,touch必须在已持久化的对象上使用,否则将抛出ActiveRecordError。例如
ball = Ball.new ball.touch(:updated_at) # => raises ActiveRecordError
# File activerecord/lib/active_record/persistence.rb, line 824 def touch(*names, time: nil) _raise_record_not_touched_error unless persisted? _raise_readonly_record_error if readonly? attribute_names = timestamp_attributes_for_update_in_model attribute_names = (attribute_names | names).map! do |name| name = name.to_s name = self.class.attribute_aliases[name] || name verify_readonly_attribute(name) name end unless attribute_names.empty? affected_rows = _touch_row(attribute_names, time) @_trigger_update_callback = affected_rows == 1 else true end end
update(attributes) Link
使用传入的哈希更新模型的属性,并将记录保存起来,所有这些都包装在事务中。如果对象无效,保存将失败并返回false。
# File activerecord/lib/active_record/persistence.rb, line 564 def update(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do assign_attributes(attributes) save end end
update!(attributes) Link
# File activerecord/lib/active_record/persistence.rb, line 575 def update!(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do assign_attributes(attributes) save! end end
update_attribute(name, value) Link
更新单个属性并保存记录。这对于现有记录上的布尔标志特别有用。另请注意
-
验证将被跳过。
-
回调将被调用。
-
如果
updated_at/updated_on列可用,则会被更新。 -
更新此对象中所有被标记为脏的属性。
如果属性被标记为只读,此方法将引发ActiveRecord::ActiveRecordError。
另请参阅update_column。
update_attribute!(name, value) Link
更新单个属性并保存记录。这对于现有记录上的布尔标志特别有用。另请注意
-
验证将被跳过。
-
回调将被调用。
-
如果
updated_at/updated_on列可用,则会被更新。 -
更新此对象中所有被标记为脏的属性。
如果属性被标记为只读,此方法将引发ActiveRecord::ActiveRecordError。
如果任何before_*回调抛出:abort,操作将被取消,update_attribute!将引发ActiveRecord::RecordNotSaved。有关详细信息,请参阅ActiveRecord::Callbacks。
update_column(name, value, touch: nil) Link
等同于update_columns(name => value)。
update_columns(attributes) Link
直接在数据库中更新属性,执行UPDATE SQL语句,并将这些属性设置在接收者中。
user.update_columns(last_request_at: Time.current)
这是更新属性的最快方式,因为它直接操作数据库,但请注意,因此 regular update procedures will be completely bypassed. In particular
-
验证将被跳过。
-
回调将被跳过。
-
如果
touch选项设置为true,则会更新updated_at/updated_on。 -
但是,属性的序列化规则与
ActiveRecord::Relation#update_all相同。
当调用新对象时,或者当至少一个属性被标记为只读时,此方法会引发ActiveRecord::ActiveRecordError。
Parameters¶ ↑
-
:touch选项 - 更新时触碰时间戳列。 -
如果传递了属性名称,它们将与
updated_at/updated_on属性一起更新。
Examples¶ ↑
# Update a single attribute. user.update_columns(last_request_at: Time.current) # Update with touch option. user.update_columns(last_request_at: Time.current, touch: true)
# File activerecord/lib/active_record/persistence.rb, line 619 def update_columns(attributes) raise ActiveRecordError, "cannot update a new record" if new_record? raise ActiveRecordError, "cannot update a destroyed record" if destroyed? _raise_readonly_record_error if readonly? attributes = attributes.transform_keys do |key| name = key.to_s name = self.class.attribute_aliases[name] || name verify_readonly_attribute(name) || name end touch = attributes.delete("touch") if touch names = touch if touch != true names = Array.wrap(names) options = names.extract_options! touch_updates = self.class.touch_attributes_with_time(*names, **options) attributes.with_defaults!(touch_updates) unless touch_updates.empty? end update_constraints = _query_constraints_hash attributes = attributes.each_with_object({}) do |(k, v), h| h[k] = @attributes.write_cast_value(k, v) clear_attribute_change(k) end affected_rows = self.class._update_record( attributes, update_constraints ) affected_rows == 1 end