2017-10-20 15:20:28 -04:00
|
|
|
module FactoryBot
|
2012-04-13 14:20:19 -04:00
|
|
|
module Strategy
|
|
|
|
class Stub
|
2009-04-28 10:39:32 -04:00
|
|
|
@@next_id = 1000
|
|
|
|
|
Stub strategy disables all persistence instance methods
Previously, instances created with the Stub strategy disabled a number of
methods defined by ActiveRecord::Persistence, to ensure that stubbed instances
did not read or write to the database. However, this blacklist was incomplete,
allowing some methods (e.g. #save!) to be called on stub instances.
This expands the blacklist to disable all methods defined by
ActiveRecord::Persistence that are not explicitly defined on stub instances
(currently #new_record?, #persisted?), or do not talk to the database at all
(#becomes, #becomes!).
The blacklist is correct as of current Rails master (the pre-release for Rails
5.0). It also, as a result, includes a couple of methods that are not defined
by ActiveRecord::Persistence in earlier versions of Rails, and will not
automatically include methods added to this module in future versions of
Rails.
It would be possible to make this automatic using reflection, and instead
using a whitelist of allowed methods:
ActiveRecord::Persistence.public_instance_methods
However, at present this test is not dependent on ActiveRecord, so I have left
this for future work if desired.
2016-06-29 13:36:29 -04:00
|
|
|
DISABLED_PERSISTENCE_METHODS = [
|
|
|
|
:connection,
|
|
|
|
:decrement!,
|
|
|
|
:delete,
|
|
|
|
:destroy!,
|
|
|
|
:destroy,
|
|
|
|
:increment!,
|
|
|
|
:reload,
|
|
|
|
:save!,
|
|
|
|
:save,
|
|
|
|
:toggle!,
|
|
|
|
:touch,
|
|
|
|
:update!,
|
|
|
|
:update,
|
|
|
|
:update_attribute,
|
|
|
|
:update_attributes!,
|
|
|
|
:update_attributes,
|
|
|
|
:update_column,
|
2020-06-05 15:15:18 -04:00
|
|
|
:update_columns
|
Stub strategy disables all persistence instance methods
Previously, instances created with the Stub strategy disabled a number of
methods defined by ActiveRecord::Persistence, to ensure that stubbed instances
did not read or write to the database. However, this blacklist was incomplete,
allowing some methods (e.g. #save!) to be called on stub instances.
This expands the blacklist to disable all methods defined by
ActiveRecord::Persistence that are not explicitly defined on stub instances
(currently #new_record?, #persisted?), or do not talk to the database at all
(#becomes, #becomes!).
The blacklist is correct as of current Rails master (the pre-release for Rails
5.0). It also, as a result, includes a couple of methods that are not defined
by ActiveRecord::Persistence in earlier versions of Rails, and will not
automatically include methods added to this module in future versions of
Rails.
It would be possible to make this automatic using reflection, and instead
using a whitelist of allowed methods:
ActiveRecord::Persistence.public_instance_methods
However, at present this test is not dependent on ActiveRecord, so I have left
this for future work if desired.
2016-06-29 13:36:29 -04:00
|
|
|
].freeze
|
|
|
|
|
2020-04-26 15:33:43 -04:00
|
|
|
def self.next_id=(id)
|
|
|
|
@@next_id = id
|
|
|
|
end
|
|
|
|
|
2012-02-10 16:56:07 -05:00
|
|
|
def association(runner)
|
2012-04-25 15:29:02 -04:00
|
|
|
runner.run(:build_stubbed)
|
2011-12-02 21:32:38 -05:00
|
|
|
end
|
|
|
|
|
2012-04-13 14:20:19 -04:00
|
|
|
def result(evaluation)
|
|
|
|
evaluation.object.tap do |instance|
|
|
|
|
stub_database_interaction_on_result(instance)
|
2018-10-26 14:47:44 -04:00
|
|
|
set_timestamps(instance)
|
2018-10-28 16:01:48 -04:00
|
|
|
clear_changes_information(instance)
|
2012-04-13 14:20:19 -04:00
|
|
|
evaluation.notify(:after_stub, instance)
|
2011-12-16 11:30:04 -05:00
|
|
|
end
|
2011-12-02 21:32:38 -05:00
|
|
|
end
|
|
|
|
|
2022-02-03 21:41:09 -05:00
|
|
|
def to_sym
|
|
|
|
:stub
|
|
|
|
end
|
|
|
|
|
2011-12-02 21:32:38 -05:00
|
|
|
private
|
|
|
|
|
|
|
|
def next_id
|
|
|
|
@@next_id += 1
|
|
|
|
end
|
|
|
|
|
2011-12-16 11:30:04 -05:00
|
|
|
def stub_database_interaction_on_result(result_instance)
|
2019-07-12 13:32:50 -04:00
|
|
|
if has_settable_id?(result_instance)
|
|
|
|
result_instance.id ||= next_id
|
|
|
|
end
|
2012-06-22 14:33:30 -04:00
|
|
|
|
2011-11-22 18:01:01 -05:00
|
|
|
result_instance.instance_eval do
|
2011-06-27 16:44:37 -04:00
|
|
|
def persisted?
|
2019-07-12 13:32:50 -04:00
|
|
|
true
|
2011-06-27 16:44:37 -04:00
|
|
|
end
|
|
|
|
|
2009-04-28 10:39:32 -04:00
|
|
|
def new_record?
|
2019-07-12 13:32:50 -04:00
|
|
|
false
|
2009-04-28 10:39:32 -04:00
|
|
|
end
|
|
|
|
|
2017-01-15 08:26:03 -05:00
|
|
|
def destroyed?
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
Stub strategy disables all persistence instance methods
Previously, instances created with the Stub strategy disabled a number of
methods defined by ActiveRecord::Persistence, to ensure that stubbed instances
did not read or write to the database. However, this blacklist was incomplete,
allowing some methods (e.g. #save!) to be called on stub instances.
This expands the blacklist to disable all methods defined by
ActiveRecord::Persistence that are not explicitly defined on stub instances
(currently #new_record?, #persisted?), or do not talk to the database at all
(#becomes, #becomes!).
The blacklist is correct as of current Rails master (the pre-release for Rails
5.0). It also, as a result, includes a couple of methods that are not defined
by ActiveRecord::Persistence in earlier versions of Rails, and will not
automatically include methods added to this module in future versions of
Rails.
It would be possible to make this automatic using reflection, and instead
using a whitelist of allowed methods:
ActiveRecord::Persistence.public_instance_methods
However, at present this test is not dependent on ActiveRecord, so I have left
this for future work if desired.
2016-06-29 13:36:29 -04:00
|
|
|
DISABLED_PERSISTENCE_METHODS.each do |write_method|
|
|
|
|
define_singleton_method(write_method) do |*args|
|
2018-12-12 11:05:13 -05:00
|
|
|
raise "stubbed models are not allowed to access the database - "\
|
2020-06-05 15:15:18 -04:00
|
|
|
"#{self.class}##{write_method}(#{args.join(",")})"
|
Stub strategy disables all persistence instance methods
Previously, instances created with the Stub strategy disabled a number of
methods defined by ActiveRecord::Persistence, to ensure that stubbed instances
did not read or write to the database. However, this blacklist was incomplete,
allowing some methods (e.g. #save!) to be called on stub instances.
This expands the blacklist to disable all methods defined by
ActiveRecord::Persistence that are not explicitly defined on stub instances
(currently #new_record?, #persisted?), or do not talk to the database at all
(#becomes, #becomes!).
The blacklist is correct as of current Rails master (the pre-release for Rails
5.0). It also, as a result, includes a couple of methods that are not defined
by ActiveRecord::Persistence in earlier versions of Rails, and will not
automatically include methods added to this module in future versions of
Rails.
It would be possible to make this automatic using reflection, and instead
using a whitelist of allowed methods:
ActiveRecord::Persistence.public_instance_methods
However, at present this test is not dependent on ActiveRecord, so I have left
this for future work if desired.
2016-06-29 13:36:29 -04:00
|
|
|
end
|
2016-02-05 15:04:57 -05:00
|
|
|
end
|
2009-04-28 10:39:32 -04:00
|
|
|
end
|
2018-10-26 14:47:44 -04:00
|
|
|
end
|
2012-06-22 14:33:30 -04:00
|
|
|
|
2019-07-12 13:32:50 -04:00
|
|
|
def has_settable_id?(result_instance)
|
|
|
|
!result_instance.class.respond_to?(:primary_key) ||
|
|
|
|
result_instance.class.primary_key
|
|
|
|
end
|
|
|
|
|
2018-10-26 14:47:44 -04:00
|
|
|
def clear_changes_information(result_instance)
|
|
|
|
if result_instance.respond_to?(:clear_changes_information)
|
|
|
|
result_instance.clear_changes_information
|
2012-06-22 14:33:30 -04:00
|
|
|
end
|
2018-10-26 14:47:44 -04:00
|
|
|
end
|
2016-12-16 05:22:13 -05:00
|
|
|
|
2018-10-26 14:47:44 -04:00
|
|
|
def set_timestamps(result_instance)
|
|
|
|
if missing_created_at?(result_instance)
|
|
|
|
result_instance.created_at = Time.current
|
|
|
|
end
|
2017-10-21 23:58:05 -04:00
|
|
|
|
2018-10-26 14:47:44 -04:00
|
|
|
if missing_updated_at?(result_instance)
|
|
|
|
result_instance.updated_at = Time.current
|
2016-12-16 05:22:13 -05:00
|
|
|
end
|
2009-04-28 10:39:32 -04:00
|
|
|
end
|
2015-11-09 21:38:36 -05:00
|
|
|
|
2018-10-26 14:47:44 -04:00
|
|
|
def missing_created_at?(result_instance)
|
|
|
|
result_instance.respond_to?(:created_at) &&
|
|
|
|
result_instance.respond_to?(:created_at=) &&
|
|
|
|
result_instance.created_at.blank?
|
|
|
|
end
|
|
|
|
|
|
|
|
def missing_updated_at?(result_instance)
|
|
|
|
result_instance.respond_to?(:updated_at) &&
|
|
|
|
result_instance.respond_to?(:updated_at=) &&
|
|
|
|
result_instance.updated_at.blank?
|
2015-11-09 21:38:36 -05:00
|
|
|
end
|
2009-01-06 15:22:08 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|