Rails 方法:查找具有多个 where 子句的深层嵌套关联
Rails way: Finding a deeply nested association with many where clause
这似乎是一个简单的问题,但对我来说却有点困惑。我想找到一个好的方法来处理这个问题。
我有5个模型。
工作
class Job < ActiveRecord::Base
has_many :job_entries_jobs
has_many :job_entries, through: :job_entries_jobs
end
工作条目
class JobEntry < ActiveRecord::Base
has_many :attachments
has_many :job_entries_jobs
has_many :pinned_entries, through: :job_entries_jobs
has_many :jobs, through: :job_entries_jobs
belongs_to :user, class_name: 'User', foreign_key: 'user_id'
end
JobEntriesJob
class JobEntriesJob < ActiveRecord::Base
self.table_name = 'job_entries_jobs'
has_many :pinned_entries
belongs_to :job_entry
belongs_to :job, touch: true
end
固定条目
class PinnedEntry < ActiveRecord::Base
self.table_name = "pinned_entries"
belongs_to :job_entries_job
has_and_belongs_to_many :users
end
用户
class User < ActiveRecord::Base
has_many :job_entries
has_many :pinned_entries
end
我可以通过 job_id
和 user_id
获得 pinned_entries(job_id 和 user_id 从 request
参数获得)通过 associations
以 rails
的方式(我可以通过使用 SQL
获得 pinned_entries )。如果是,我应该把这个 code
放在哪里?
如果我有一个 attachment
模型怎么样
class Attachment < ActiveRecord::Base
self.table_name = 'attachments'
belongs_to :job_entry, :class_name => 'JobEntry', :foreign_key => 'job_entry_id'
end
而我要include
attachment
(一个link和文件名)和JobEntry
(content
)?
这是应该的输出
{
"listPinnedEntries": [
{
"id": 1
"user_id":
"text": "content of entry",
"user": {
"id":
"username": "jamesnguyen"
},
"attachments": [
{
"id":
"job_entry_id":
"comment": "file name",
"file": {
"url": "link here"
}
},
{
"id":
"job_entry_id":
"comment": "file name",
"file": {
"url": "link here"
}
}
]
}]
}
感谢您的帮助
鉴于 job_id
和 user_id
:
user = User.find(user_id)
pinned_entries = user.pinned_entries.includes(:job_entries_job).where(job_entries_jobs: {job_id: job_id})
更新(关于附件的第二个问题):
由于您正在生成值的散列,因此修改您的 PinnedEntry 模型(或者甚至可能是 @Robin 回答的 Job 模型和 User 模型)比进行脏循环更容易:
class PinnedEntry < ActiveRecord::Base
self.table_name = "pinned_entries"
belongs_to :job_entries_job
belongs_to :job_entry, through: :job_entries_job
has_many :attachments, through: :job_entry
has_and_belongs_to_many :users
end
然后,继续我上面的第一个回答:
pinned_entries.as_json(
only: [:id, :user_id, :text],
include: [
user: {
only: [:id, :username]
},
attachments: {
only: [:id, :job_entry_id, :comment]
}
]
)
这将 return 一个与您想要的值相同的散列值。注意:我没有从您的附件模型中包含 file: url
,没有 belongs_to :file
或可以帮助我确定附件模型与 file
和 [=18= 的关系的东西].如果它不是属性,那么我认为您必须手动将它们添加到生成的哈希中。
添加额外的 has_many
to the models Job
and User
and link it with your PinnedEntry
via the :through
可能是个好主意。
您的 Job
模型将更改为:
class Job < ActiveRecord::Base
has_many :job_entries_jobs
has_many :job_entries, through: :job_entries_jobs
has_many :pinned_entries: through: :job_entries
end
然后您可以像往常一样在 Job
记录上使用 .pinned_entries
。因此,您更改了 User
模型。
这似乎是一个简单的问题,但对我来说却有点困惑。我想找到一个好的方法来处理这个问题。 我有5个模型。
工作
class Job < ActiveRecord::Base
has_many :job_entries_jobs
has_many :job_entries, through: :job_entries_jobs
end
工作条目
class JobEntry < ActiveRecord::Base
has_many :attachments
has_many :job_entries_jobs
has_many :pinned_entries, through: :job_entries_jobs
has_many :jobs, through: :job_entries_jobs
belongs_to :user, class_name: 'User', foreign_key: 'user_id'
end
JobEntriesJob
class JobEntriesJob < ActiveRecord::Base
self.table_name = 'job_entries_jobs'
has_many :pinned_entries
belongs_to :job_entry
belongs_to :job, touch: true
end
固定条目
class PinnedEntry < ActiveRecord::Base
self.table_name = "pinned_entries"
belongs_to :job_entries_job
has_and_belongs_to_many :users
end
用户
class User < ActiveRecord::Base
has_many :job_entries
has_many :pinned_entries
end
我可以通过 job_id
和 user_id
获得 pinned_entries(job_id 和 user_id 从 request
参数获得)通过 associations
以 rails
的方式(我可以通过使用 SQL
获得 pinned_entries )。如果是,我应该把这个 code
放在哪里?
如果我有一个 attachment
模型怎么样
class Attachment < ActiveRecord::Base
self.table_name = 'attachments'
belongs_to :job_entry, :class_name => 'JobEntry', :foreign_key => 'job_entry_id'
end
而我要include
attachment
(一个link和文件名)和JobEntry
(content
)?
这是应该的输出
{
"listPinnedEntries": [
{
"id": 1
"user_id":
"text": "content of entry",
"user": {
"id":
"username": "jamesnguyen"
},
"attachments": [
{
"id":
"job_entry_id":
"comment": "file name",
"file": {
"url": "link here"
}
},
{
"id":
"job_entry_id":
"comment": "file name",
"file": {
"url": "link here"
}
}
]
}]
}
感谢您的帮助
鉴于 job_id
和 user_id
:
user = User.find(user_id)
pinned_entries = user.pinned_entries.includes(:job_entries_job).where(job_entries_jobs: {job_id: job_id})
更新(关于附件的第二个问题):
由于您正在生成值的散列,因此修改您的 PinnedEntry 模型(或者甚至可能是 @Robin 回答的 Job 模型和 User 模型)比进行脏循环更容易:
class PinnedEntry < ActiveRecord::Base
self.table_name = "pinned_entries"
belongs_to :job_entries_job
belongs_to :job_entry, through: :job_entries_job
has_many :attachments, through: :job_entry
has_and_belongs_to_many :users
end
然后,继续我上面的第一个回答:
pinned_entries.as_json(
only: [:id, :user_id, :text],
include: [
user: {
only: [:id, :username]
},
attachments: {
only: [:id, :job_entry_id, :comment]
}
]
)
这将 return 一个与您想要的值相同的散列值。注意:我没有从您的附件模型中包含 file: url
,没有 belongs_to :file
或可以帮助我确定附件模型与 file
和 [=18= 的关系的东西].如果它不是属性,那么我认为您必须手动将它们添加到生成的哈希中。
添加额外的 has_many
to the models Job
and User
and link it with your PinnedEntry
via the :through
可能是个好主意。
您的 Job
模型将更改为:
class Job < ActiveRecord::Base
has_many :job_entries_jobs
has_many :job_entries, through: :job_entries_jobs
has_many :pinned_entries: through: :job_entries
end
然后您可以像往常一样在 Job
记录上使用 .pinned_entries
。因此,您更改了 User
模型。