我有一个组织和动作代码模型。注册高级帐户时,组织可以输入折扣的操作码。因此,组织使用了no或1个动作代码,而许多组织可以使用动作代码。
目前的关联:
Organizations migration file: t.references :actioncode, index: true, foreign_key: true
Organization model: belongs_to :actioncode
Actioncode model: has_many :organizations
此设置的初始问题:actioncode_id不一定是强制性的播种时我曾经得到错误代码ActiveRecord::AssociationTypeMismatch: Actioncode(#23575660) expected, got Fixnum(#5494220)
。原因似乎是actioncode_id已成为组织模型中的必填列。情况并非如此; actioncode也应该是nil
,因为在支付高级帐户时,组织也可以不使用/拥有任何操作码。
当前情况:升级到PostgreSQL之后:作为回应,我已将我的数据库升级为PostgreSQL。然而,现在在迁移时我收到错误消息(请参阅帖子底部的完整消息):
PG :: UndefinedTable:ERROR:relation" actioncodes"不存在
错误消息:有什么想法导致此错误?删除'当前关联'下的三行。我对迁移和播种没有任何问题。事实上,保留所有三行但从第一行删除index: true, foreign_key: true
并且它也正确迁移。当我在迁移时保留index: true
时,会出现错误:SyntaxError: xxx_create_organizations.rb:17: syntax error, unexpected tSYMBEG, expecting => t.boolean :activated
。当我保留foreign_key: true
时,它会生成原始错误消息PG::UndefinedTable
。
如果我将第一行更改为错误代码:t.references :actioncode_id, index: true, foreign_key: true
,则会出现以下错误:
PG::UndefinedTable: ERROR: relation "actioncode_ids" does not exist
: ALTER TABLE "organizations" ADD CONSTRAINT "fk_rails_604f95d1a1"
FOREIGN KEY ("actioncode_id_id")
REFERENCES "actioncode_ids" ("id")
所以在最后一行给出了_ids,Rails似乎确实遇到了表名的问题。将self.table_name = 'actioncodes'
添加到动作代码模型文件没有任何区别。怎么办?
替代协会:
我想知道我是否需要一个替代协会来满足我的需求。我已经调查了其他几个协会,但我不确定该怎么做。最佳案例场景我在组织模型中只有一个包含已使用的操作码的列,如果没有使用操作码,则为nil。我需要一个模型关联来打印所有使用过特定操作码的组织。
替代关联1:此关联的问题在于,操作码仍然是组织模型中的必需变量,因此不能为零。
Organization migration: t.references :actioncode, index: true, foreign_key: true
Organization model: has_one :actioncode
Actioncode model: has_many :organizations
备用关联2:此关联将在actioncodes表中保存organization_id(我猜是一个数组),而从我的角度来看,将actioncode_id包含在组织表中会更有意义。此外,下面的代码仍然需要每个组织的操作代码。
Organization model: has_one :actioncode
Actioncodes migration file: t.belongs_to :organization, index: true
另类关联3:我还考虑过创建一个额外的关联模型,但这让我想知道当我遵循这个策略时,我是否不会过度思考,因为这样做会添加一个额外的表/模型。另外,我不确定下面的组织模型是否仍然需要折扣价值,因此不能真正解决原始问题。但如果这是可行的方法,我想:
Organization model: has_one :discount
has_one :actioncode, through: :discount
Discount model: belongs_to :organization
has_one :actioncode
Actioncode model: belongs_to :discount
Discount migration: t.belongs_to :organization, index: true
doesn;t need any other columns
Actioncode migration: t.belongs_to :discount, index: true
替代协会4:最后,has_and_belongs_to_many协会对我来说没有任何意义,因为我理解它的目的是为了很多:许多关系,而组织:actioncode是一个很多:1/0的关系。
我应该使用哪种设置,并且没有将actioncode作为组织的强制变量?
其他信息:在rake db:migrate
和rake db:drop
之后运行rake db:create
的SQL:
== 20150410153815 CreateUsers: migrating ===============================
-- create_table(:users)
-> 0.0582s
== 20150410153815 CreateUsers: migrated (0.0628s) ======================
== 20150410200022 AddIndexToUsersEmailAndUsername: migrating ===========
-- add_index(:users, :email, {:unique=>true})
-> 0.0109s
-- add_index(:users, :username, {:unique=>true})
-> 0.0100s
== 20150410200022 AddIndexToUsersEmailAndUsername: migrated (0.0219s) ==
== 20150416113853 CreateOrganizations: migrating ==============================
-- create_table(:organizations)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedTable: ERROR: relation "actioncodes" does not exist
: ALTER TABLE "organizations" ADD CONSTRAINT "fk_rails_4ecaa2493e"
FOREIGN KEY ("actioncode_id")
REFERENCES "actioncodes" ("id")
/usr/local/rvm/gems/ruby-2.1.5/gems/activerecord-4.2.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec'
<<SNIP>>
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "actioncodes" does not exist
: ALTER TABLE "organizations" ADD CONSTRAINT "fk_rails_4ecaa2493e"
FOREIGN KEY ("actioncode_id")
REFERENCES "actioncodes" ("id")
/usr/local/rvm/gems/ruby-2.1.5/gems/activerecord-4.2.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec'
<<SNIP>>
其他信息:运行当前关联的迁移中的SQL(运行rake db:drop
然后rake db:setup
):
-- enable_extension("plpgsql")
-> 0.0664s
-- create_table("actioncodes", {:force=>:cascade})
-> 0.0412s
-- add_index("actioncodes", ["actioncode"], {:name=>"index_actioncodes_on_actioncode", :unique=>true, :using=>:btree})
-> 0.0217s
-- create_table("organizations", {:force=>:cascade})
-> 0.0237s
-- add_index("organizations", ["summ"], {:name=>"index_organizations_on_summ", :unique=>true, :using=>:btree})
-> 0.0106s
-- add_index("organizations", ["name"], {:name=>"index_organizations_on_name", :unique=>true, :using=>:btree})
-> 0.0197s
<<SNIP, OTHER TABLES >>
-- initialize_schema_migrations_table()
-> 0.0352s
-- enable_extension("plpgsql")
-> 0.0405s
-- create_table("actioncodes", {:force=>:cascade})
-> 0.0176s
-- add_index("actioncodes", ["actioncode"], {:name=>"index_actioncodes_on_actioncode", :unique=>true, :using=>:btree})
-> 0.0085s
-- create_table("organizations", {:force=>:cascade})
-> 0.0148s
-- add_index("organizations", ["summ"], {:name=>"index_organizations_on_summ", :unique=>true, :using=>:btree})
-> 0.0113s
-- add_index("organizations", ["name"], {:name=>"index_organizations_on_name", :unique=>true, :using=>:btree})
-> 0.0195s
<<SNIP, OTHER TABLES >>
-- initialize_schema_migrations_table()
-> 0.0342s
rake aborted!
ActiveRecord::AssociationTypeMismatch: Actioncode(#39911240) expected, got Fixnum(#20092360)
/usr/local/rvm/gems/ruby-2.1.5/gems/activerecord-4.2.1/lib/active_record/associations/association.rb:216:in `raise_on_type_mismatch!'
<<SNIP >>
答案 0 :(得分:1)
这里有逻辑/流量问题。
Organization
不应属于Actioncode
,如果Organization
可以拥有一个代码。或不。这就是为什么
组织
has_one :actioncode
Actioncode
belongs_to :organization
这样Organization
不会保留actioncode_id
,但Actioncode
会保留organization_id
。
<强>更新强>:
按照我上面提到的那样,让Actioncode
成为type
或value
字段,例如包含'AC-08821'
字符串。这样你就可以保持这两个模型之间预期的关系,并且仍然可以搜索具有相同value
的所有代码。
或强>
创建关联表,例如使用has_and_belongs_to_many
基本上,您创建另一个表,表示两个模型之间的连接。
答案 1 :(得分:1)
基于,“......组织没有或1个动作代码,许多组织都可以使用动作代码”,您的建模是正确的,只是迁移创建的外键不允许空值在actioncode_id列中。您可以检查迁移SQL以查看使用的命令。
也许您正在使用的数据库不允许使用nil外键列,但大多数都是。您可能必须使用SQL而不是Rails构造外键以允许空值。
来自postgresql文档:http://www.postgresql.org/docs/9.3/static/ddl-constraints.html
现在无法使用未出现在products表中的非NULL product_no条目创建订单。
注意,“......使用非NULL product_no条目...”,空条目应该没问题,并且您的建模是正确的。