【发布时间】:2016-11-27 18:10:37
【问题描述】:
我想在 Rails 应用程序中显示模型的文本摘要。
目前我正在这样做:
class ServiceOrder < ApplicationRecord
has_many :items, class_name: 'ServiceOrderItem',
dependent: :destroy,
inverse_of: :service_order
def link_text
items.left_outer_joins(:product)
.select("string_agg(coalesce(products.description, service_order_items.description), '; ') as description")
.group("service_order_items.service_order_id")
.map(&:description)
.first
end
end
class ServiceOrderItem < ApplicationRecord
belongs_to :service_order, inverse_of: :items
belongs_to :product, optional: true
end
class Product < ApplicationRecord
end
困扰我的是我试图选择单个值,而不是模型。
这个查询确实返回了一个“假”模型并提取了我想要的值,但它有点 hacky:
- 添加我需要的适当关系
items.left_outer_joins(:product)
- 添加我想要的选择值
.select("string_agg(coalesce(products.description, service_order_items.description), '; ') as description")
- 按子句添加分组
.group("service_order_items.service_order_id")
- 执行查询并提取返回的“假”模型的描述
.map(&:description)
- 我知道这个查询只返回一个结果,但是它构建了一个包含所有结果的数组,所以我从数组中提取了一个结果
.first
我想要的查询是这样的:
select string_agg(coalesce(products.description, service_order_items.description), '; ')
from service_order_items
left outer join products on service_order_items.product_id = products.id
where service_order_items.service_order_id = :id
group by service_order_items.service_order_id;
这是我正在生成的查询,问题是结果包含在模型对象中,然后我将其转换为数组,然后提取我想要的值。
那么,我如何告诉活动记录选择单个原始值而不是模型列表?
顺便说一句,在.map 之前添加.first 是行不通的,因为它在执行的SQL 中包含我不能拥有的顺序(order by service_order_items.id)。
架构:
create_table "products", force: :cascade do |t|
t.integer "organization_id"
t.string "code"
t.string "description"
t.string "brand"
t.string "unit_of_measure"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.decimal "selling_price"
t.index ["organization_id"], name: "index_products_on_organization_id", using: :btree
end
create_table "service_order_items", force: :cascade do |t|
t.integer "service_order_id"
t.decimal "quantity"
t.string "description"
t.integer "product_id"
t.decimal "unit_price"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["product_id"], name: "index_service_order_items_on_product_id", using: :btree
t.index ["service_order_id"], name: "index_service_order_items_on_service_order_id", using: :btree
end
create_table "service_orders", force: :cascade do |t|
t.integer "organization_id"
t.text "description"
t.integer "state_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "customer_id"
t.integer "sequential_id"
t.date "start_date"
t.date "end_date"
t.index ["customer_id"], name: "index_service_orders_on_customer_id", using: :btree
t.index ["organization_id"], name: "index_service_orders_on_organization_id", using: :btree
t.index ["state_id"], name: "index_service_orders_on_state_id", using: :btree
end
【问题讨论】:
标签: ruby-on-rails postgresql rails-activerecord