我正试图在我的多态关联中定义一个引用属性 "状态 "的作用域。
我的现实世界的问题是,我有一些引用特定项目的文章和事件。我将这些内容捕获为 item_references。我的文章和事件可以处于草稿或发布状态。我希望能够在关联(item_referenceable)状态为发布的地方提取item_references。
像这样。
scope :published_resource, -> { where("item_referenceable.published?") }
但这显然是行不通的,因为 item_referenceable
是一个实例方法,我在类的层面上工作。我怀疑我需要在join前面下功夫,但我很难理解如何下功夫。
以下是我代码的相关部分。
模型:
class Article < ApplicationRecord
has_many :item_references, as: :item_referenceable
accepts_nested_attributes_for :item_references, allow_destroy: true,
:reject_if => proc { |att| att[:item_unique_id].blank? }
end
class Event < ApplicationRecord
has_many :item_references, as: :item_referenceable
accepts_nested_attributes_for :item_references, allow_destroy: true,
:reject_if => proc { |att| att[:item_unique_id].blank? }
end
class ItemReference < ApplicationRecord
belongs_to :item_referenceable, polymorphic: true
scope :in_articles, -> { where("item_referenceable_type = 'Article'") }
end
Schema Extracts:
create_table "events", id do |t|
t.string "title"
t.datetime "start_date_time"
t.datetime "end_date_time"
t.string "state"
create_table "article", id do |t|
t.string "title"
t.string "slug"
t.text "body"
t.string "state"
create_table "item_references", id do |t|
t.text "item_unique_reference"
t.string "item_referenceable_type"
t.bigint "item_referenceable_id"
t.index ["item_referenceable_type", "item_referenceable_id"], name: "idx_item_refs"
这个问题很可能会扩大,因为我最终会在多个模型中引用项目,比如课程,博客等。我想知道是否有可能在不指定具体模型名称的情况下定义范围,并使用 item_referenceable_type 来引用模型名称。
这是我不成功的尝试。
scope :published_resource, -> { joins(:item_referenceable_type).where('item_references.item_referenceable.published?') }
我最终想生成一个API 通过 item_unique_id 显示所有引用该项目的文章和事件。
像这样。
{
"title": "Retrieve all item references",
"items": [
{
"item_unique_id": "O12",
"articles": [
{
"resource_id": 1,
"title": "Penguin",
"state": "published",
"slug": "test-article"
}
],
"events": []
},
我在上面的阶段使用了 ItemReference.all.group_by(&:item_unique_id)
但它会检索所有资源(EventsArticles),无论它们是否被发布。
下面是我建议如何处理这个问题:(用简写的方式,因为扩展的功能几乎肯定是一个需求。
class Publishable
PUBLISHABLES = {articles: Article, events: Event}
attr_reader :results
attr_accessor :limit, :conditions
def initialize(conditions={})
@conditions = conditions
@results = {}
end
def as_json(options={})
fetch if results.empty?
results.as_json(options)
end
def published!
conditions.merge!({stage: 'Published'})
self
end
private
def fetch
PUBLISHABLES.each do |node, klass|
results[node] = klass.where(conditions).limit(limit)
end
end
end
那么你可以简单地调用
publishables = Publishable.new
publishables.published!
publishables.limit = 10
publishables.results
正如我所提到的,这只是为了给你举个例子,是非常过度简化的,我当然会考虑扩展这个功能,但希望它能帮助你指出一个方向。