编辑4.我的解释中的一些东西是不正确的...附件是一个(做得很差的图形),它显示了表格以及模式是如何的,然后我的主要问题是给出我提供的提供者通过provider_location表通过组位置ID连接,该组位置保存组,最终保存组名。这就是我想知道的,构建一个这样的表如何获得组名?来自提供商的所有方式。这就像我需要一个has_many贯穿。 (大注:图像中的提供商地址和组地址实际上是提供商位置和组位置)
编辑x 3:谢谢@mrshoco。它让我更接近,现在它像我的结构其他东西不太正确....我在运行provider_test_location.rb时出现此错误
vagrant@precise32:/vagrant/ipanmv2$ rake test test/models/provider_location_tes
t.rb
Run options: --seed 18117
# Running:
E
Finished in 0.190900s, 5.2383 runs/s, 5.2383 assertions/s.
1) Error:
ProviderLocationTest#test_fetching_a_group_name_for_a_provider:
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: provider_
locations.group_id: SELECT groups.group_name FROM "groups" INNER JOIN "provider_
locations" ON "provider_locations"."group_id" = "groups"."id" INNER JOIN "provid
ers" ON "providers"."id" = "provider_locations"."provider_id" WHERE "providers".
"first_name" = 'Shane'
test/models/provider_location_test.rb:37:in `puts'
test/models/provider_location_test.rb:37:in `puts'
test/models/provider_location_test.rb:37:in `block in <class:ProviderLocatio
nTest>'
1 runs, 1 assertions, 0 failures, 1 errors, 0 skips
这是完整的单元测试
require 'test_helper'
class ProviderLocationTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
test "adding a provider to a group location" do
group = Group.new
group.group_name = 'My Awesome'
group.save
adr = Address.new
adr.city = 'Las Cruces'
adr.state = 'New Mexico'
adr.zip = '88012'
adr.address_line_one = '382 Dark side of moon'
adr.address_line_two = ''
adr.save
gl = GroupLocation.new
gl.group = group
gl.address=adr
gl.save
prv = Provider.new
prv.first_name = 'Shane'
prv.last_name = 'Thomas'
prv.save
pl = ProviderLocation.new
pl.provider = prv
pl.group_location = gl ###############ISSUE
assert pl.save, 'Provider location did not save'
puts Group.joins(:providers).where(providers: { first_name: 'Shane' }).select('groups.group_name')
end
end
模型如下:
class Provider < ActiveRecord::Base
belongs_to :designation
belongs_to :specialty
has_many :provider_locations
has_many :invoices
has_many :groups, through: :provider_locations
end
class ProviderLocation < ActiveRecord::Base
belongs_to :provider
belongs_to :group_location
end
class Group < ActiveRecord::Base
#validations
validates :group_name, presence: true
#associations
has_many :providers, through: :provider_locations
has_many :invoices
has_one :billing
has_many :addresses, through: :group_locations
has_many :group_locations
belongs_to :billing_address, class_name: 'Address', foreign_key: 'billing_address_id'
belongs_to :mailing_address, class_name: 'Address', foreign_key: 'mailing_address_id'
has_and_belongs_to_many :insurances
has_many :provider_locations
end
class GroupLocation < ActiveRecord::Base
belongs_to :address
belongs_to :group
end
class Address < ActiveRecord::Base
has_many :group_locations
has_many :billings
end
答案 0 :(得分:2)
# Group name given a provider name
Group.joins(:providers).where('providers.first_name' => 'Shane').select('groups.name')
# address/location of the provider given the group name
Provider.joins(:groups).where("groups.name" => "your_group_name").first.provider_locations.first
答案 1 :(得分:1)
让我试着去理解,我看到它的方式你有5个表,其中三个表示模型:
另外两个是连接表:
如果我理解正确,你有这个,因为一个组有很多地址,提供者也是如此。提供者也直接与组建立关系,因为它不受地址的影响,我认为你缺少的是groups_providers的连接表,这当然需要迁移来创建所述表。在这种情况下,你会有一些排序:
class Provider < ActiveRecord::Base
has_many_and_belongs_to_many :groups
end
但是。提供者和组之间的关系仅取决于地址,提供者和组之间的关系通过地址:
class Provider < ActiveRecord::Base
has_many :addresses
has_many :groups, though: addresses
end
# This is not tested, just illustrating the idea.
组,提供者和地址之间的关系也可能依赖于三个嵌入式中的两个的ID,在这种情况下,我想知道更多关于此设计背后的原因。
答案 2 :(得分:1)
我创建了一个项目,说明了问题的解决方案,并且可行。你可以在https://github.com/dimakura/stackoverflow-projects/tree/master/32260679-dealing-with-associations找到它。下面是相同概念的描述,因此浏览存储库是完全可选的。
实际上,有两种方法可以解决您的问题,它们都可以在适当的环境中使用。
但是,让我们首先创建表格和模型。
我简化了你的表格,省略了不相关的细节。以下是创建它们的脚本。
群组表格:
create_table :groups do |t|
t.string :group_name
t.timestamps null: false
end
地址表格:
create_table :addresses do |t|
t.string :city
t.string :state
t.string :zip
t.string :address_line_one
t.string :address_line_two
t.timestamps null: false
end
group_locations 表格:
create_table :group_locations do |t|
t.references :group, index: true, foreign_key: true
t.references :address, index: true, foreign_key: true
t.timestamps null: false
end
提供商表:
create_table :providers do |t|
t.string :first_name
t.string :last_name
t.timestamps null: false
end
provider_locations 表格:
create_table :provider_locations do |t|
t.references :provider, index: true, foreign_key: true
t.references :group_location, index: true, foreign_key: true
t.timestamps null: false
end
以下是Address
,Group
和GroupLocation
模型之间的关系:
class Address < ActiveRecord::Base
has_many :group_locations
end
class Group < ActiveRecord::Base
has_many :group_locations
end
class GroupLocation < ActiveRecord::Base
belongs_to :group
belongs_to :address
has_many :provider_locations
end
ProviderLocation
也很简单:
class ProviderLocation < ActiveRecord::Base
belongs_to :provider
belongs_to :group_location
end
相对复杂的是Provider
:
class Provider < ActiveRecord::Base
has_many :provider_locations
has_many :group_locations, through: :provider_locations
has_many :groups, through: :group_locations
end
您现在可以看到,从给定的Provider
开始,您可以轻松导航到Group
。
现在让我们测试一下我们的设置。
我们在此请求中定义了您的问题:
...如何通过组位置通过提供商位置获取提供商可能属于的所有组...
正如我在开始时说的,有两种方法可以解决您的问题,具体取决于给出的内容。
让我们首先假设我们选择了一个提供商,并希望所有与此单一提供商相关的群组。
class ProviderLocationTest < ActiveSupport::TestCase
def setup
group = Group.create(group_name: 'My Awesome')
adr = Address.create(city: 'Las Cruces', state: 'New Mexico', zip: '88012', address_line_one: '382 Dark Side of the Moon', address_line_two: '')
gl =GroupLocation.create(group: group, address: adr)
@provider = Provider.create(first_name: 'Shane', last_name: 'Thomas')
pl = ProviderLocation.create(provider: @provider, group_location: gl)
end
test 'getting groups for a single provider' do
assert_equal ['My Awesome'], @provider.groups.map{ |group| group.group_name }
end
end
与单一提供商合作是一种很好的方式。
但是还有另一种情况,我们想要选择属于多个提供商的所有组。更糟糕的是,我们可能会收到请求:&#34;为年龄不超过50岁的提供者提供所有群组。
在这种情况下,我们可以利用直接加入。
下面我们将说明如何在我们想要为名字为Shane的所有提供商获取组时使用加入。
test 'getting groups based on arbitrary query' do
group_names = Group.joins(group_locations: [ provider_locations: :provider]).where("providers.first_name=?", 'Shane').map{ |group| group.group_name }
assert_equal ['My Awesome'], group_names
end