如何避免运行 ActiveRecord 回调?

发布于 2024-07-14 10:07:00 字数 405 浏览 7 评论 0 原文

我有一些具有 after_save 回调的模型。 通常这很好,但在某些情况下,例如创建开发数据时,我想在不运行回调的情况下保存模型。 有没有一种简单的方法可以做到这一点? 类似于...

Person#save( :run_callbacks => false )

或者

Person#save_without_callbacks

我查看了 Rails 文档但没有找到任何内容。 然而,根据我的经验,Rails 文档并不总是讲述整个故事。

更新

我发现

Foo.after_save.clear

我找不到记录该方法的位置,但它似乎有效。

I have some models that have after_save callbacks. Usually that's fine, but in some situations, like when creating development data, I want to save the models without having the callbacks run. Is there a simple way to do that? Something akin to...

Person#save( :run_callbacks => false )

or

Person#save_without_callbacks

I looked in the Rails docs and didn't find anything. However in my experience the Rails docs don't always tell the whole story.

UPDATE

I found a blog post that explains how you can remove callbacks from a model like this:

Foo.after_save.clear

I couldn't find where that method is documented but it seems to work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(29

剩一世无双 2024-07-21 10:07:01

对于自定义回调,请在回调中使用 attr_accessorunless

按如下方式定义模型:

class Person << ActiveRecord::Base

  attr_accessor :skip_after_save_callbacks

  after_save :do_something, unless: :skip_after_save_callbacks

end

然后,如果您需要在不调用您定义的 after_save 回调的情况下保存记录,请将 skip_after_save_callbacks 虚拟属性设置为 true

person.skip_after_save_callbacks #=> nil
person.save # By default, this *will* call `do_something` after saving.

person.skip_after_save_callbacks = true
person.save # This *will not* call `do_something` after saving.

person.skip_after_save_callbacks = nil # Always good to return this value back to its default so you don't accidentally skip callbacks.

For custom callbacks, use an attr_accessor and an unless in the callback.

Define your model as follows:

class Person << ActiveRecord::Base

  attr_accessor :skip_after_save_callbacks

  after_save :do_something, unless: :skip_after_save_callbacks

end

And then if you need to save the record without hitting the after_save callbacks you defined, set the skip_after_save_callbacks virtual attribute to true.

person.skip_after_save_callbacks #=> nil
person.save # By default, this *will* call `do_something` after saving.

person.skip_after_save_callbacks = true
person.save # This *will not* call `do_something` after saving.

person.skip_after_save_callbacks = nil # Always good to return this value back to its default so you don't accidentally skip callbacks.
冷夜 2024-07-21 10:07:01

为什么您希望能够在开发中做到这一点? 当然,这意味着您正在使用无效数据构建应用程序,因此它的行为会很奇怪,并且不符合您在生产中的预期。

如果您想用数据填充您的开发数据库,​​更好的方法是构建一个 rake 任务,该任务使用 faker gem 构建有效数据并将其导入数据库,根据需要创建尽可能多或更少的记录,但如果您是跟风我想 update_without_callbacks 和 create_without_callbacks 会工作得很好,但是当你试图按照你的意愿弯曲轨道时,问问自己你有一个很好的理由,并且你正在做的事情是否真的是一个好主意。

Why would you want to be able to do this in development? Surely this will mean you are building your application with invalid data and as such it will behave strangely and not as you expect in production.

If you want to populate your dev db with data a better approach would be to build a rake task that used the faker gem to build valid data and import it into the db creating as many or few records as you desire, but if you are heel bent on it and have a good reason I guess that update_without_callbacks and create_without_callbacks will work fine, but when you are trying to bend rails to your will, ask yourself you have a good reason and if what you are doing is really a good idea.

乜一 2024-07-21 10:07:01

一种选择是使用同一个表为此类操作建立一个单独的模型:(

class NoCallbacksModel < ActiveRecord::Base
  set_table_name 'table_name_of_model_that_has_callbacks'

  include CommonModelMethods # if there are
  :
  :

end

相同的方法可能会使绕过验证变得更容易)

Stephan

One option is to have a separate model for such manipulations, using the same table:

class NoCallbacksModel < ActiveRecord::Base
  set_table_name 'table_name_of_model_that_has_callbacks'

  include CommonModelMethods # if there are
  :
  :

end

(Same approach might make things easier for bypassing validations)

Stephan

墨洒年华 2024-07-21 10:07:01

另一种方法是使用验证挂钩而不是回调。 例如:

class Person < ActiveRecord::Base
  validate_on_create :do_something
  def do_something
    "something clever goes here"
  end
end

这样你就可以默认获得 do_something ,但你可以轻松地用以下方法覆盖它:

@person = Person.new
@person.save(false)

Another way would be to use validation hooks instead of callbacks. For example:

class Person < ActiveRecord::Base
  validate_on_create :do_something
  def do_something
    "something clever goes here"
  end
end

That way you can get the do_something by default, but you can easily override it with:

@person = Person.new
@person.save(false)
極樂鬼 2024-07-21 10:07:01

应该适用于所有版本的 ActiveRecord,而不依赖于可能存在或可能不存在的选项或 activerecord 方法。

module PlainModel
  def self.included(base)
    plainclass = Class.new(ActiveRecord::Base) do
      self.table_name = base.table_name
    end
    base.const_set(:Plain, plainclass)
  end
end


# usage
class User < ActiveRecord::Base
  include PlainModel

  validates_presence_of :email
end

User.create(email: "")        # fail due to validation
User::Plain.create(email: "") # success. no validation, no callbacks

user = User::Plain.find(1)
user.email = ""
user.save

TLDR:在同一个表上使用“不同的 activerecord 模型”

Something that should work with all versions of ActiveRecord without depending on options or activerecord methods that may or may not exist.

module PlainModel
  def self.included(base)
    plainclass = Class.new(ActiveRecord::Base) do
      self.table_name = base.table_name
    end
    base.const_set(:Plain, plainclass)
  end
end


# usage
class User < ActiveRecord::Base
  include PlainModel

  validates_presence_of :email
end

User.create(email: "")        # fail due to validation
User::Plain.create(email: "") # success. no validation, no callbacks

user = User::Plain.find(1)
user.email = ""
user.save

TLDR: use a "different activerecord model" over the same table

怼怹恏 2024-07-21 10:07:01

当我想运行 Rake 任务但没有为我保存的每条记录运行回调时,我遇到了同样的问题。
这对我有用(Rails 5),并且它必须适用于几乎所有版本的Rails:

class MyModel < ApplicationRecord
  attr_accessor :skip_callbacks
  before_create :callback1
  before_update :callback2
  before_destroy :callback3

  private
  def callback1
    return true if @skip_callbacks
    puts "Runs callback1"
    # Your code
  end
  def callback2
    return true if @skip_callbacks
    puts "Runs callback2"
    # Your code
  end
  # Same for callback3 and so on....
end

它的工作方式是它只在skip_callbacks为true的方法的第一行返回true,所以它不会运行其余部分方法中的代码。
要跳过回调,您只需在保存、创建、销毁之前将skip_callbacks设置为true:

rec = MyModel.new() # Or Mymodel.find()
rec.skip_callbacks = true
rec.save

I faced the same problem when I wanted to run a Rake Task but without running the callbacks for every record I was saving.
This worked for me (Rails 5), and it must work for almost every version of Rails:

class MyModel < ApplicationRecord
  attr_accessor :skip_callbacks
  before_create :callback1
  before_update :callback2
  before_destroy :callback3

  private
  def callback1
    return true if @skip_callbacks
    puts "Runs callback1"
    # Your code
  end
  def callback2
    return true if @skip_callbacks
    puts "Runs callback2"
    # Your code
  end
  # Same for callback3 and so on....
end

The way it works is that it just returns true in the first line of the method it skip_callbacks is true, so it doesn't run the rest of the code in the method.
To skip callbacks you just need to set skip_callbacks to true before saving, creating, destroying:

rec = MyModel.new() # Or Mymodel.find()
rec.skip_callbacks = true
rec.save
您的好友蓝忘机已上羡 2024-07-21 10:07:01

在 Rails 7 中,我们可以这样做来跳过所有回调 -

person.save!(callbacks: false)

In Rails 7, we can do something like this to skip all callbacks -

person.save!(callbacks: false)
葬シ愛 2024-07-21 10:07:01

这不是最简洁的方法,但您可以将回调代码包装在检查 Rails 环境的条件中。

if Rails.env == 'production'
  ...

Not the cleanest way, but you could wrap the callback code in a condition that checks the Rails environment.

if Rails.env == 'production'
  ...
策马西风 2024-07-21 10:07:00

使用 update_column (Rails >= v3.1) 或 update_columns (Rails >= 4.0) 跳过回调和验证。 同样使用这些方法,updated_at不会更新。

#Rails >= v3.1 only
@person.update_column(:some_attribute, 'value')
#Rails >= v4.0 only
@person.update_columns(attributes)

http://api.rubyonrails.org/classes/ActiveRecord/Persistence .html#method-i-update_column

#2:跳过创建对象时也有效的回调

class Person < ActiveRecord::Base
  attr_accessor :skip_some_callbacks

  before_validation :do_something
  after_validation :do_something_else

  skip_callback :validation, :before, :do_something, if: :skip_some_callbacks
  skip_callback :validation, :after, :do_something_else, if: :skip_some_callbacks
end

person = Person.new(person_params)
person.skip_some_callbacks = true
person.save

UPDATE (2020)

显然是 Rails 始终支持 :if:除非 options,所以上面的代码可以简化为:

class Person < ActiveRecord::Base
  attr_accessor :skip_some_callbacks

  before_validation :do_something, unless: :skip_some_callbacks
  after_validation :do_something_else, unless: :skip_some_callbacks
end

person = Person.new(person_params)
person.skip_some_callbacks = true
person.save

Use update_column (Rails >= v3.1) or update_columns (Rails >= 4.0) to skip callbacks and validations. Also with these methods, updated_at is not updated.

#Rails >= v3.1 only
@person.update_column(:some_attribute, 'value')
#Rails >= v4.0 only
@person.update_columns(attributes)

http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column

#2: Skipping callbacks that also works while creating an object

class Person < ActiveRecord::Base
  attr_accessor :skip_some_callbacks

  before_validation :do_something
  after_validation :do_something_else

  skip_callback :validation, :before, :do_something, if: :skip_some_callbacks
  skip_callback :validation, :after, :do_something_else, if: :skip_some_callbacks
end

person = Person.new(person_params)
person.skip_some_callbacks = true
person.save

UPDATE (2020)

Apparently Rails has always supported :if and :unless options, so above code can be simplified as:

class Person < ActiveRecord::Base
  attr_accessor :skip_some_callbacks

  before_validation :do_something, unless: :skip_some_callbacks
  after_validation :do_something_else, unless: :skip_some_callbacks
end

person = Person.new(person_params)
person.skip_some_callbacks = true
person.save
梦中的蝴蝶 2024-07-21 10:07:00

此解决方案仅适用于 Rails 2。

我刚刚调查了这个问题,我想我有一个解决方案。 您可以使用两个 ActiveRecord 私有方法:

update_without_callbacks
create_without_callbacks

您必须使用 send 来调用这些方法。 示例:

p = Person.new(:name => 'foo')
p.send(:create_without_callbacks)

p = Person.find(1)
p.send(:update_without_callbacks)

这绝对是您只想在控制台或进行一些随机测试时使用的东西。 希望这可以帮助!

This solution is Rails 2 only.

I just investigated this and I think I have a solution. There are two ActiveRecord private methods that you can use:

update_without_callbacks
create_without_callbacks

You're going to have to use send to call these methods. examples:

p = Person.new(:name => 'foo')
p.send(:create_without_callbacks)

p = Person.find(1)
p.send(:update_without_callbacks)

This is definitely something that you'll only really want to use in the console or while doing some random tests. Hope this helps!

蛮可爱 2024-07-21 10:07:00

更新:

@Vikrant Chaudhary 的解决方案似乎更好:

#Rails >= v3.1 only
@person.update_column(:some_attribute, 'value')
#Rails >= v4.0 only
@person.update_columns(attributes)

我原来的答案:

请参阅此链接:如何跳过 ActiveRecord 回调?

在 Rails3 中,

假设我们有一个类定义:

class User < ActiveRecord::Base
  after_save :generate_nick_name
end 

Approach1:

User.send(:create_without_callbacks)
User.send(:update_without_callbacks)

Approach2:
当您想在 rspec 文件或其他文件中跳过它们时,请尝试以下操作:

User.skip_callback(:save, :after, :generate_nick_name)
User.create!()

注意:完成此操作后,如果您不在 rspec 环境中,则应该重置回调:

User.set_callback(:save, :after, :generate_nick_name)

在 Rails 3.0.5 上对我来说效果很好


Updated:

@Vikrant Chaudhary's solution seems better:

#Rails >= v3.1 only
@person.update_column(:some_attribute, 'value')
#Rails >= v4.0 only
@person.update_columns(attributes)

My original answer :

see this link: How to skip ActiveRecord callbacks?

in Rails3,

assume we have a class definition:

class User < ActiveRecord::Base
  after_save :generate_nick_name
end 

Approach1:

User.send(:create_without_callbacks)
User.send(:update_without_callbacks)

Approach2:
When you want to skip them in your rspec files or whatever, try this:

User.skip_callback(:save, :after, :generate_nick_name)
User.create!()

NOTE: once this is done, if you are not in rspec environment, you should reset the callbacks:

User.set_callback(:save, :after, :generate_nick_name)

works fine for me on rails 3.0.5

幸福丶如此 2024-07-21 10:07:00

如果目标是简单地插入一条记录而不需要回调或验证,并且您希望在不诉诸额外的 gem、添加条件检查、使用 RAW SQL 或以任何方式修改现有代码的情况下完成此操作,请考虑使用“影子” object”指向您现有的数据库表。 就像这样:

class ImportedPerson < ActiveRecord::Base
  self.table_name = 'people'
end

这适用于 Rails 的每个版本,是线程安全的,并且完全消除了所有验证和回调,无需修改现有代码。 您可以在实际导入之前扔掉该类声明,然后就可以开始了。 只需记住使用新类来插入对象,例如:

ImportedPerson.new( person_attributes )

If the goal is to simply insert a record without callbacks or validations, and you would like to do it without resorting to additional gems, adding conditional checks, using RAW SQL, or futzing with your exiting code in any way, consider using a "shadow object" pointing to your existing db table. Like so:

class ImportedPerson < ActiveRecord::Base
  self.table_name = 'people'
end

This works with every version of Rails, is threadsafe, and completely eliminates all validations and callbacks with no modifications to your existing code. You can just toss that class declaration in right before your actual import, and you should be good to go. Just remember to use your new class to insert the object, like:

ImportedPerson.new( person_attributes )
猫弦 2024-07-21 10:07:00

轨道 3:

MyModel.send("_#{symbol}_callbacks") # list  
MyModel.reset_callbacks symbol # reset

rails 3:

MyModel.send("_#{symbol}_callbacks") # list  
MyModel.reset_callbacks symbol # reset
居里长安 2024-07-21 10:07:00

您可以在您的 Person 模型中尝试类似的操作:

after_save :something_cool, :unless => :skip_callbacks

def skip_callbacks
  ENV[RAILS_ENV] == 'development' # or something more complicated
end

编辑: after_save 不是一个符号,但这至少是我第 1000 次尝试将其设为符号。

You could try something like this in your Person model:

after_save :something_cool, :unless => :skip_callbacks

def skip_callbacks
  ENV[RAILS_ENV] == 'development' # or something more complicated
end

EDIT: after_save is not a symbol, but that's at least the 1,000th time I've tried to make it one.

逐鹿 2024-07-21 10:07:00

您可以使用update_columns

User.first.update_columns({:name => "sebastian", :age => 25})

更新对象的给定属性,而不调用保存,因此跳过验证和回调。

You can use update_columns:

User.first.update_columns({:name => "sebastian", :age => 25})

Updates the given attributes of an object, without calling save, hence skipping validations and callbacks.

别再吹冷风 2024-07-21 10:07:00

阻止所有 after_save 回调的唯一方法是让第一个回调返回 false。

也许你可以尝试类似的东西(未经测试):

class MyModel < ActiveRecord::Base
  attr_accessor :skip_after_save

  def after_save
    return false if @skip_after_save
    ... blah blah ...
  end
end

...

m = MyModel.new # ... etc etc
m.skip_after_save = true
m.save

The only way to prevent all after_save callbacks is to have the first one return false.

Perhaps you could try something like (untested):

class MyModel < ActiveRecord::Base
  attr_accessor :skip_after_save

  def after_save
    return false if @skip_after_save
    ... blah blah ...
  end
end

...

m = MyModel.new # ... etc etc
m.skip_after_save = true
m.save
潦草背影 2024-07-21 10:07:00

看起来在 Rails 2.3 中处理这个问题的一种方法(因为 update_without_callbacks 消失了,等等)是使用 update_all,这是根据 Rails 验证和回调指南第 12 节

另外,请注意,如果您在 after_ 回调中执行某些操作,则基于许多关联进行计算(即 has_many 关联,您还执行accepts_nested_attributes_for),您将需要重新加载关联,以防作为保存的一部分,其中一名成员被删除。

Looks like one way to handle this in Rails 2.3 (since update_without_callbacks is gone, etc.), would be to use update_all, which is one of the methods that skips callbacks as per section 12 of the Rails Guide to validations and callbacks.

Also, note that if you are doing something in your after_ callback, that does a calculation based on many association (i.e. a has_many assoc, where you also do accepts_nested_attributes_for), you will need to reload the association, in case as part of the save, one of its members was deleted.

把人绕傻吧 2024-07-21 10:07:00

在某些情况下,投票最多的答案可能看起来令人困惑。

您可以仅使用简单的 if 检查是否要跳过回调,如下所示:

after_save :set_title, if: -> { !new_record? && self.name_changed? }

The most up-voted answer might seem confusing in some cases.

You can use just a simple if check if you would like to skip a callback, like this:

after_save :set_title, if: -> { !new_record? && self.name_changed? }
坐在坟头思考人生 2024-07-21 10:07:00

在 Rails 6 中,您现在可以使用 插入方法

来自文档:

通过单个 SQL INSERT 将多条记录插入数据库
陈述。 它不会实例化任何模型,也不会触发
Active Record 回调或验证。 尽管传递的值消失了
通过 Active Record 的类型转换和序列化。

with Rails 6 you can now use the insert methods

from the documentation:

Inserts multiple records into the database in a single SQL INSERT
statement. It does not instantiate any models nor does it trigger
Active Record callbacks or validations. Though passed values go
through Active Record's type casting and serialization.

淡紫姑娘! 2024-07-21 10:07:00

https://gist.github.com/576546

只需将此猴子补丁转储到 config/initializers/skip_callbacks 中.rb

然后

<代码>
Project.skip_callbacks { @project.save }

或类似的。

一切归功于作者

https://gist.github.com/576546

just dump this monkey-patch into config/initializers/skip_callbacks.rb

then


Project.skip_callbacks { @project.save }

or the like.

all credit to the author

沙沙粒小 2024-07-21 10:07:00

无需使用 gem 或插件即可在所有版本的 Rails 上工作的解决方案就是直接发出更新语句。 例如,

ActiveRecord::Base.connection.execute "update table set foo = bar where id = #{self.id}"

这可能是(也可能不是)一个选项,具体取决于您的更新的复杂程度。 这对于例如在 after_save 回调中更新记录上的标志(无需重新触发回调)非常有效。

A solution that should work across all versions of Rails without the use of a gem or plugin is simply to issue update statements directly. eg

ActiveRecord::Base.connection.execute "update table set foo = bar where id = #{self.id}"

This may (or may not) be an option depending on how complex your update is. This works well for eg updating flags on a record from within an after_save callback (without retriggering the callback).

风向决定发型 2024-07-21 10:07:00

我需要 Rails 4 的解决方案,所以我想出了这个:

app/models/concerns/save_without_callbacks.rb

module SaveWithoutCallbacks

  def self.included(base)
    base.const_set(:WithoutCallbacks,
      Class.new(ActiveRecord::Base) do
        self.table_name = base.table_name
      end
      )
  end

  def save_without_callbacks
    new_record? ? create_without_callbacks : update_without_callbacks
  end

  def create_without_callbacks
    plain_model = self.class.const_get(:WithoutCallbacks)
    plain_record = plain_model.create(self.attributes)
    self.id = plain_record.id
    self.created_at = Time.zone.now
    self.updated_at = Time.zone.now
    @new_record = false
    true
  end

  def update_without_callbacks
    update_attributes = attributes.except(self.class.primary_key)
    update_attributes['created_at'] = Time.zone.now
    update_attributes['updated_at'] = Time.zone.now
    update_columns update_attributes
  end

end

在任何模型中:

include SaveWithoutCallbacks

然后你可以:

record.save_without_callbacks

Model::WithoutCallbacks.create(attributes)

I needed a solution for Rails 4, so I came up with this:

app/models/concerns/save_without_callbacks.rb

module SaveWithoutCallbacks

  def self.included(base)
    base.const_set(:WithoutCallbacks,
      Class.new(ActiveRecord::Base) do
        self.table_name = base.table_name
      end
      )
  end

  def save_without_callbacks
    new_record? ? create_without_callbacks : update_without_callbacks
  end

  def create_without_callbacks
    plain_model = self.class.const_get(:WithoutCallbacks)
    plain_record = plain_model.create(self.attributes)
    self.id = plain_record.id
    self.created_at = Time.zone.now
    self.updated_at = Time.zone.now
    @new_record = false
    true
  end

  def update_without_callbacks
    update_attributes = attributes.except(self.class.primary_key)
    update_attributes['created_at'] = Time.zone.now
    update_attributes['updated_at'] = Time.zone.now
    update_columns update_attributes
  end

end

in any model:

include SaveWithoutCallbacks

then you can:

record.save_without_callbacks

or

Model::WithoutCallbacks.create(attributes)
手长情犹 2024-07-21 10:07:00

当我需要完全控制回调时,我创建另一个用作开关的属性。 简单有效:

型号:

class MyModel < ActiveRecord::Base
  before_save :do_stuff, unless: :skip_do_stuff_callback
  attr_accessor :skip_do_stuff_callback

  def do_stuff
    puts 'do stuff callback'
  end
end

测试:

m = MyModel.new()

# Fire callbacks
m.save

# Without firing callbacks
m.skip_do_stuff_callback = true
m.save

# Fire callbacks again
m.skip_do_stuff_callback = false
m.save

When I need full control over the callback, I create another attribute that is used as a switch. Simple and effective:

Model:

class MyModel < ActiveRecord::Base
  before_save :do_stuff, unless: :skip_do_stuff_callback
  attr_accessor :skip_do_stuff_callback

  def do_stuff
    puts 'do stuff callback'
  end
end

Test:

m = MyModel.new()

# Fire callbacks
m.save

# Without firing callbacks
m.skip_do_stuff_callback = true
m.save

# Fire callbacks again
m.skip_do_stuff_callback = false
m.save
难忘№最初的完美 2024-07-21 10:07:00
# for rails 3
  if !ActiveRecord::Base.private_method_defined? :update_without_callbacks
    def update_without_callbacks
      attributes_with_values = arel_attributes_values(false, false, attribute_names)
      return false if attributes_with_values.empty?
      self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.update(attributes_with_values)
    end
  end
# for rails 3
  if !ActiveRecord::Base.private_method_defined? :update_without_callbacks
    def update_without_callbacks
      attributes_with_values = arel_attributes_values(false, false, attribute_names)
      return false if attributes_with_values.empty?
      self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.update(attributes_with_values)
    end
  end
葬﹪忆之殇 2024-07-21 10:07:00

这些都没有指向 without_callbacks 插件,它只做你需要的事情......

class MyModel < ActiveRecord::Base
  before_save :do_something_before_save

  def after_save
    raise RuntimeError, "after_save called"
  end

  def do_something_before_save
    raise RuntimeError, "do_something_before_save called"
  end
end

o = MyModel.new
MyModel.without_callbacks(:before_save, :after_save) do
  o.save # no exceptions raised
end

http:// github.com/cjbottaro/without_callbacks 适用于 Rails 2.x

None of these points to without_callbacks plugin that just does what you need ...

class MyModel < ActiveRecord::Base
  before_save :do_something_before_save

  def after_save
    raise RuntimeError, "after_save called"
  end

  def do_something_before_save
    raise RuntimeError, "do_something_before_save called"
  end
end

o = MyModel.new
MyModel.without_callbacks(:before_save, :after_save) do
  o.save # no exceptions raised
end

http://github.com/cjbottaro/without_callbacks works with Rails 2.x

少跟Wǒ拽 2024-07-21 10:07:00

我编写了一个在 Rails 3 中实现 update_without_callbacks 的插件:

http://github.com/dball/skip_activerecord_callbacks

我认为正确的解决方案是重写模型以避免回调,但如果这在短期内不切实际,这个插件可能会有所帮助。

I wrote a plugin that implements update_without_callbacks in Rails 3:

http://github.com/dball/skip_activerecord_callbacks

The right solution, I think, is to rewrite your models to avoid callbacks in the first place, but if that's impractical in the near term, this plugin may help.

顾铮苏瑾 2024-07-21 10:07:00

如果您使用的是 Rails 2。您可以使用 SQL 查询来更新列,而无需运行回调和验证。

YourModel.connection.execute("UPDATE your_models SET your_models.column_name=#{value} WHERE your_models.id=#{ym.id}")

我认为它应该适用于任何 Rails 版本。

If you are using Rails 2. You could use SQL query for updating your column without running callbacks and validations.

YourModel.connection.execute("UPDATE your_models SET your_models.column_name=#{value} WHERE your_models.id=#{ym.id}")

I think it should work in any rails versions.

李白 2024-07-21 10:07:00

要在 Rails 中创建测试数据,您可以使用以下 hack:

record = Something.new(attrs)
ActiveRecord::Persistence.instance_method(:create_record).bind(record).call

https://coderwall.com/p/y3yp2q/edit< /a>

For creating test data in Rails you use this hack:

record = Something.new(attrs)
ActiveRecord::Persistence.instance_method(:create_record).bind(record).call

https://coderwall.com/p/y3yp2q/edit

等往事风中吹 2024-07-21 10:07:00

您可以使用sneaky-save gem:https://rubygems.org/gems/sneaky-save

请注意,这无法帮助在没有验证的情况下保存关联。 它会抛出错误“created_at 不能为 null”,因为它与模型不同,直接插入 sql 查询。 为了实现这一点,我们需要更新数据库的所有自动生成的列。

You can use sneaky-save gem: https://rubygems.org/gems/sneaky-save.

Note this cannot help in saving associations along without validations. It throws error 'created_at cannot be null' as it directly inserts the sql query unlike a model. To implement this, we need to update all auto generated columns of db.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文