gpt4 book ai didi

ruby-on-rails - Ruby-on-Rails 4 和 PostgreSQL 中使用 GUID 作为 ID 的 MTM 关系

转载 作者:行者123 更新时间:2023-11-29 13:31:21 26 4
gpt4 key购买 nike

Rails 的新手,使用 Ruby On Rails 4.0.3 和 Ruby 2.2.0 以及 PostgreSQL,我正在尝试使用 GUID 作为 Id 来构建这个数据库结构。

我的目标:我想有很多电话号码属于很多人作为例子。

所以我built a little test app which can be found here基本上是followed the Association guide创建多对多表。

所以这是我的模型,为清楚起见添加了注释:

class Address < ActiveRecord::Base
belongs_to :contact
end

class Contact < ActiveRecord::Base
has_many :addresses
has_many :phoneNumbers
end

class PhoneNumber < ActiveRecord::Base
has_many :contacts
end

这是迁移设置:

class CreateAddresses < ActiveRecord::Migration
def change
create_table :addresses, id: :uuid do |t|
#t.belongs_to :contacts
t.text :street1
t.text :city

t.timestamps
end

add_column :addresses, :contact_id, :uuid
end
end

class CreateContacts < ActiveRecord::Migration
def change
create_table :contacts, id: :uuid do |t|
t.text :firstName
t.text :lastName

t.timestamps
end
end
end

class CreatePhoneNumbers < ActiveRecord::Migration
def change
create_table :phone_numbers, id: :uuid do |t|
t.text :number
t.text :name

t.timestamps
end
end
end

# the MTM
class CreateContactsPhoneNumbers < ActiveRecord::Migration
def change
create_table :contacts_phone_numbers, id: :uuid

add_column :contacts_phone_numbers, :contact_id, :uuid
add_column :contacts_phone_numbers, :phone_number_id, :uuid
end
end

SQL 是这样输出的:

CREATE TABLE addresses (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
street1 text,
city text,
created_at timestamp without time zone,
updated_at timestamp without time zone,
contact_id uuid
);

CREATE TABLE contacts (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
"firstName" text,
"lastName" text,
created_at timestamp without time zone,
updated_at timestamp without time zone
);

CREATE TABLE phone_numbers (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
number text,
name text,
created_at timestamp without time zone,
updated_at timestamp without time zone
);

CREATE TABLE contacts_phone_numbers (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
contact_id uuid,
phone_number_id uuid
);

这是我的示例种子脚本的一部分

varC = Contact.create(firstName: "John", lastName: "Doe")
varA = Address.create(street1: "10 Somewhere Pl", city: "Ogurek", contact: varC)

这里注意一下,在本次迁移之后,这样查询就可以成功获取到联系人了

puts Address.first.contact.firstname
# John

但是,一旦我将种子脚本更改为:

varC = Contact.create(firstName: "John", lastName: "Doe")
varA = Address.create(street1: "10 Somewhere Pl", city: "Ogurek", contact: varC)

varP = PhoneNumber.create(number: "2342342345", name: "home")
varC.phoneNumbers = varP
varC.save

varP.contacts = varC
varP.save

然后我运行 rake db:migrate,我将得到以下输出(注意错误):

==  EnablePostgresUuid: migrating =============================================
-- execute("create extension \"uuid-ossp\"")
-> 0.0018s
== EnablePostgresUuid: migrated (0.0024s) ====================================

== CreateAddresses: migrating ================================================
-- create_table(:addresses, {:id=>:uuid})
-> 0.0036s
-- add_column(:addresses, :contact_id, :uuid)
-> 0.0005s
== CreateAddresses: migrated (0.0053s) =======================================

== CreateContacts: migrating =================================================
-- create_table(:contacts, {:id=>:uuid})
-> 0.0024s
== CreateContacts: migrated (0.0031s) ========================================

== CreatePhoneNumbers: migrating =============================================
-- create_table(:phone_numbers, {:id=>:uuid})
-> 0.0023s
== CreatePhoneNumbers: migrated (0.0029s) ====================================

== CreateContactsPhoneNumbers: migrating =====================================
-- create_table(:contacts_phone_numbers, {:id=>:uuid})
-> 0.0014s
-- add_column(:contacts_phone_numbers, :contact_id, :uuid)
-> 0.0004s
-- add_column(:contacts_phone_numbers, :phone_number_id, :uuid)
-> 0.0003s
== CreateContactsPhoneNumbers: migrated (0.0038s) ============================

** Invoke db:seed (first_time)
** Execute db:seed
** Invoke db:abort_if_pending_migrations (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:abort_if_pending_migrations
rake aborted!
undefined method `each' for #<PhoneNumber:0xa532460>
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activemodel-4.0.3/lib/active_model/attribute_methods.rb:439:in `method_missing'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activerecord-4.0.3/lib/active_record/attribute_methods.rb:155:in `method_missing'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activerecord-4.0.3/lib/active_record/associations/collection_association.rb:333:in `replace'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activerecord-4.0.3/lib/active_record/associations/collection_association.rb:42:in `writer'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activerecord-4.0.3/lib/active_record/associations/builder/association.rb:78:in `phoneNumbers='
/_apps/test_site/rails_test1/rtest1/db/seeds.rb:5:in `<top (required)>'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activesupport-4.0.3/lib/active_support/dependencies.rb:223:in `load'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activesupport-4.0.3/lib/active_support/dependencies.rb:223:in `block in load'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activesupport-4.0.3/lib/active_support/dependencies.rb:214:in `load_dependency'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activesupport-4.0.3/lib/active_support/dependencies.rb:223:in `load'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/railties-4.0.3/lib/rails/engine.rb:540:in `load_seed'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activerecord-4.0.3/lib/active_record/tasks/database_tasks.rb:154:in `load_seed'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/activerecord-4.0.3/lib/active_record/railties/databases.rake:181:in `block (2 levels) in <top (required)>'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/task.rb:236:in `call'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/task.rb:236:in `block in execute'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/task.rb:231:in `each'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/task.rb:231:in `execute'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/task.rb:175:in `block in invoke_with_call_chain'
/home/vagrant/.rvm/rubies/ruby-head/lib/ruby/2.2.0/monitor.rb:211:in `mon_synchronize'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/task.rb:168:in `invoke_with_call_chain'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/task.rb:161:in `invoke'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:149:in `invoke_task'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:106:in `block (2 levels) in top_level'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:106:in `each'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:106:in `block in top_level'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:115:in `run_with_threads'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:100:in `top_level'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:78:in `block in run'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:165:in `standard_exception_handling'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/lib/rake/application.rb:75:in `run'
/home/vagrant/.rvm/gems/ruby-head@rails4/gems/rake-10.1.1/bin/rake:33:in `<top (required)>'
/home/vagrant/.rvm/gems/ruby-head@rails4/bin/rake:23:in `load'
/home/vagrant/.rvm/gems/ruby-head@rails4/bin/rake:23:in `<main>'
Tasks: TOP => db:seed

因此我的问题:如何使用 ActiveRecord 添加可以具有 MTM 关系的可查询模型,以及如何保存和查询它?

最佳答案

好吧,所以我终于想通了,这里是它的全部荣耀:

首先,我不得不改为使用 has_and_belongs_to_many 关联而不是 has_many :through ,就像我尝试的那样(尽管我确定我也可以通过某种方式弄清楚 has_many :through ),但据我了解指南,因为我不关心连接表,我可以只使用 has_and_belongs_to_many 关联。然而,我们的问题是我们使用的是 GUID 而不是整数。

所以我在 Associations guid 中漏掉了一些东西, 有一行及其在括号中:

(尽管您需要记住在数据库中创建连接表)

所以我将模型更改为:

class Contact < ActiveRecord::Base
has_many :addresses
has_and_belongs_to_many :phoneNumbers
end

class PhoneNumber < ActiveRecord::Base
has_and_belongs_to_many :contacts
end

和迁移:

class CreateContacts < ActiveRecord::Migration
def change
create_table :contacts, id: :uuid do |t|
t.text :firstName
t.text :lastName

t.timestamps
end
end
end

class CreatePhoneNumbers < ActiveRecord::Migration
def change
create_table :phone_numbers, id: :uuid do |t|
t.text :number
t.text :name

t.timestamps
end
end
end

然后我添加了这个迁移:

class CreateContactsPhoneNumbers < ActiveRecord::Migration
def change
create_table :contacts_phone_numbers, id: :uuid do |t|
t.uuid :contact_id
t.uuid :phone_number_id
end
end
end

以上所有内容产生了以下 SQL:

CREATE TABLE contacts (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
"firstName" text,
"lastName" text,
created_at timestamp without time zone,
updated_at timestamp without time zone
);

CREATE TABLE phone_numbers (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
number text,
name text,
created_at timestamp without time zone,
updated_at timestamp without time zone
);

CREATE TABLE contacts_phone_numbers (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
contact_id uuid,
phone_number_id uuid
);

我可以添加从我的 seeds.rb 中获取的模型:

c = Contact.create(firstName: "John", lastName: "Smith")
p = PhoneNumber.create(number: "2342342345", name: "home", contacts: [c])

我把最终的解决方案放在了 BitBucket test project 上,请看Commit 762a546 .

因此,如果有人对我如何解决这个问题以更符合真正的 Rubyists 的做法有任何指示,我很乐意在评论中提出。谢谢。

关于ruby-on-rails - Ruby-on-Rails 4 和 PostgreSQL 中使用 GUID 作为 ID 的 MTM 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22340760/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com