当我有一个时间戳时,Minitest 会出错 has many through jointable
Getting errors with Minitest when I have a timestamp for a has many through jointable
我有一个连接table,因为一个有很多并且属于很多通过,包含许多其他属性的连接table有一个时间戳,实现明智没有麻烦,
用户
class User < ApplicationRecord
has_many :affiliations
has_many :organizations, through: :affiliations
end
组织
class Organization < ApplicationRecord
has_many :affiliations
has_many :users, through: :affiliations
end
隶属关系
class Affiliation < ApplicationRecord
belongs_to :user
belongs_to :organization
has_many :xxxxxs
end
从属关系存储的不仅是属于,它本身还包含用户的等级以及组织中不属于的等级等信息。它本身就是一个强大的模型。
对于固定装置,我还没有用于连接的文件table,
user.yml
user1:
email: aaa@aaa.com
organizations: org1
organization.yml
org1
name: foo
但是当我 运行 使用 minitest 进行测试时,它给了我一个错误。
Error:
PublicControllerTest#test_should_get_index:
ActiveRecord::StatementInvalid: Mysql2::Error: Field 'created_at' doesn't have a default value: INSERT INTO `affiliations` (`user_id`, `dominion_id`) VALUES (794918725, 299359653)
奇怪的是,它发生在甚至不使用上述 table、
的测试中
class PublicControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
end
此操作完全没有任何作用,此时它只是普通的 html
class PublicController < ApplicationController
def index
end
end
在控制器中什么都不做。
当删除时间戳时它们会消失,但记录关联创建时间是必要的信息。有什么我需要在测试中做的吗?
我正在使用 Rails edge (5.0.0rc1) 是否有可能是这导致了错误?
更新 3.
在灯具种子数据中为您的 user1 设置 "organizations: org1" - 似乎这是导致问题的原因,因为用户只能通过您的联合连接到组织 table.
我没有在规范中找到任何明确的内容,但是相关的内容 here
Fixtures bypass the normal Active Record object creation process.
After reading them from YAML file, they are inserted into database
directly using insert query. So they skip callbacks and validations
check. This also has an interesting side-effect which can be used for
drying up fixtures.
更新 2.
我错误地假设您不能在由 Rails 管理的 has_and_belongs_to_many jointable 中设置时间戳。事实上,在 HasAndBelongsToMany Rails 内部将为 table - here
创建一个 ActiveRecord::Base class
def through_model
habtm = JoinTableResolver.build lhs_model, association_name, options
join_model = Class.new(ActiveRecord::Base) {
class << self;
...
并且ActiveRecord::Base包括时间戳module
因此,您的错误应该是由标准 Rails 关联以外的其他方式在 jointable 中创建条目引起的。
原创.
我不相信您可以在 ActiveRecord 中为 has_and_belongs_to_many 关系自动管理 jointable 中的时间戳字段。这在旧 Rails(例如下面的 3.2 - link)中(有意)不起作用,而且听起来最近也没有改变。
如果你想扩展连接 table,你可以为它创建一个专用的 ActiveRecord 模型并使用 use has_many :through association。这样,如果您将其添加到 table 定义中,它将自动支持时间戳。
有关 HABTM 加入的时间戳,请参阅 https://github.com/rails/rails/issues/4653table
AFAICT Rails 3.1 does not populate timestamps on a join table. The
only difference is that in 3.2, when you add timestamps, they are
marked as NOT NULL.
@veganstraightedge the timestamps didn't "work" in 3.1 - they just
didn't raise an error when the join table was saved with them as null.
the difference here is that in 3.2 timestamps are created with a NOT
NULL constraint.
基本上,这可能是因为您没有用于连接的 ActiveRecord 模型 classtable(更新 2 - 实际上您有!),时间戳是 ActiveRecord 模型的特征。 Rails 5.0rc1 中的时间戳没有太大变化 - sources - 时间戳是一个扩展 ActiveRecord class.
的模块
顺便说一下,现在建议使用 create_join_table 迁移助手,它将创建 "pure" table(只有两个 ID,没有时间戳):
https://github.com/rails/rails/pull/4726
SO 有类似错误的问题 - Rails 3.2 + MySQL: Error: Field 'created_at' doesn't have a default value: INSERT INTO
Rails 3.2 doesn't automatically populate the timestamp fields for join
tables of :habtm relationships.
或者(警告 - 理论!),您可以尝试使用关联回调或关联扩展 - http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Association callbacks
Similar to the normal callbacks that hook into the life cycle of an
Active Record object, you can also define callbacks that get triggered
when you add an object to or remove an object from an association
collection.
class Project
has_and_belongs_to_many :developers, after_add: :evaluate_velocity
def evaluate_velocity(developer)
...
end
end
Extensions
The extension argument allows you to pass a block into a
has_and_belongs_to_many association. This is useful for adding new finders, > creators and other factory-type methods to be used as part of
the association.
has_and_belongs_to_many :contractors do
def find_or_create_by_name(name)
first_name, last_name = name.split(" ", 2)
find_or_create_by(first_name: first_name, last_name: last_name)
end
end
Extensions can refer to the internals of the association proxy using
these three attributes of the proxy_association accessor:
proxy_association.owner returns the object that the association is a part of.
proxy_association.reflection returns the reflection object that describes the association.
proxy_association.target returns the associated object for belongs_to or has_one, or the collection of associated objects for has_many or has_and_belongs_to_many.
您的模型之间的关系无法用联接表示 table。它们需要由常规模型 table 表示(并且它需要 id,created_at,updated_at)。它们应该都是常规的,ActiveRecord::Base 型号。
在这种情况下,您有一个加入模型、从属关系,而不是一个加入table
所以对于这三个,你需要一个常规的活动记录库table(包含id,created_at,updated_at)
Join tables 仅用于 has_and_belongs_to_many 关联,这些允许 tables 没有 id,created_at, updated_at
我有一个连接table,因为一个有很多并且属于很多通过,包含许多其他属性的连接table有一个时间戳,实现明智没有麻烦,
用户
class User < ApplicationRecord
has_many :affiliations
has_many :organizations, through: :affiliations
end
组织
class Organization < ApplicationRecord
has_many :affiliations
has_many :users, through: :affiliations
end
隶属关系
class Affiliation < ApplicationRecord
belongs_to :user
belongs_to :organization
has_many :xxxxxs
end
从属关系存储的不仅是属于,它本身还包含用户的等级以及组织中不属于的等级等信息。它本身就是一个强大的模型。
对于固定装置,我还没有用于连接的文件table,
user.yml
user1: email: aaa@aaa.com organizations: org1
organization.yml
org1 name: foo
但是当我 运行 使用 minitest 进行测试时,它给了我一个错误。
Error:
PublicControllerTest#test_should_get_index:
ActiveRecord::StatementInvalid: Mysql2::Error: Field 'created_at' doesn't have a default value: INSERT INTO `affiliations` (`user_id`, `dominion_id`) VALUES (794918725, 299359653)
奇怪的是,它发生在甚至不使用上述 table、
的测试中class PublicControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
end
此操作完全没有任何作用,此时它只是普通的 html
class PublicController < ApplicationController
def index
end
end
在控制器中什么都不做。
当删除时间戳时它们会消失,但记录关联创建时间是必要的信息。有什么我需要在测试中做的吗?
我正在使用 Rails edge (5.0.0rc1) 是否有可能是这导致了错误?
更新 3.
在灯具种子数据中为您的 user1 设置 "organizations: org1" - 似乎这是导致问题的原因,因为用户只能通过您的联合连接到组织 table.
我没有在规范中找到任何明确的内容,但是相关的内容 here
Fixtures bypass the normal Active Record object creation process. After reading them from YAML file, they are inserted into database directly using insert query. So they skip callbacks and validations check. This also has an interesting side-effect which can be used for drying up fixtures.
更新 2.
我错误地假设您不能在由 Rails 管理的 has_and_belongs_to_many jointable 中设置时间戳。事实上,在 HasAndBelongsToMany Rails 内部将为 table - here
创建一个 ActiveRecord::Base classdef through_model
habtm = JoinTableResolver.build lhs_model, association_name, options
join_model = Class.new(ActiveRecord::Base) {
class << self;
...
并且ActiveRecord::Base包括时间戳module
因此,您的错误应该是由标准 Rails 关联以外的其他方式在 jointable 中创建条目引起的。
原创.
我不相信您可以在 ActiveRecord 中为 has_and_belongs_to_many 关系自动管理 jointable 中的时间戳字段。这在旧 Rails(例如下面的 3.2 - link)中(有意)不起作用,而且听起来最近也没有改变。
如果你想扩展连接 table,你可以为它创建一个专用的 ActiveRecord 模型并使用 use has_many :through association。这样,如果您将其添加到 table 定义中,它将自动支持时间戳。
有关 HABTM 加入的时间戳,请参阅 https://github.com/rails/rails/issues/4653table
AFAICT Rails 3.1 does not populate timestamps on a join table. The only difference is that in 3.2, when you add timestamps, they are marked as NOT NULL.
@veganstraightedge the timestamps didn't "work" in 3.1 - they just didn't raise an error when the join table was saved with them as null. the difference here is that in 3.2 timestamps are created with a NOT NULL constraint.
基本上,这可能是因为您没有用于连接的 ActiveRecord 模型 classtable(更新 2 - 实际上您有!),时间戳是 ActiveRecord 模型的特征。 Rails 5.0rc1 中的时间戳没有太大变化 - sources - 时间戳是一个扩展 ActiveRecord class.
的模块顺便说一下,现在建议使用 create_join_table 迁移助手,它将创建 "pure" table(只有两个 ID,没有时间戳): https://github.com/rails/rails/pull/4726
SO 有类似错误的问题 - Rails 3.2 + MySQL: Error: Field 'created_at' doesn't have a default value: INSERT INTO
Rails 3.2 doesn't automatically populate the timestamp fields for join tables of :habtm relationships.
或者(警告 - 理论!),您可以尝试使用关联回调或关联扩展 - http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Association callbacks
Similar to the normal callbacks that hook into the life cycle of an Active Record object, you can also define callbacks that get triggered when you add an object to or remove an object from an association collection.
class Project
has_and_belongs_to_many :developers, after_add: :evaluate_velocity
def evaluate_velocity(developer)
...
end
end
Extensions
The extension argument allows you to pass a block into a has_and_belongs_to_many association. This is useful for adding new finders, > creators and other factory-type methods to be used as part of the association.
has_and_belongs_to_many :contractors do
def find_or_create_by_name(name)
first_name, last_name = name.split(" ", 2)
find_or_create_by(first_name: first_name, last_name: last_name)
end
end
Extensions can refer to the internals of the association proxy using these three attributes of the proxy_association accessor:
proxy_association.owner returns the object that the association is a part of.
proxy_association.reflection returns the reflection object that describes the association.
proxy_association.target returns the associated object for belongs_to or has_one, or the collection of associated objects for has_many or has_and_belongs_to_many.
您的模型之间的关系无法用联接表示 table。它们需要由常规模型 table 表示(并且它需要 id,created_at,updated_at)。它们应该都是常规的,ActiveRecord::Base 型号。
在这种情况下,您有一个加入模型、从属关系,而不是一个加入table
所以对于这三个,你需要一个常规的活动记录库table(包含id,created_at,updated_at)
Join tables 仅用于 has_and_belongs_to_many 关联,这些允许 tables 没有 id,created_at, updated_at