gpt4 book ai didi

ruby-on-rails - Ruby 和 SQL 中的重复业务逻辑

转载 作者:数据小太阳 更新时间:2023-10-29 07:08:26 26 4
gpt4 key购买 nike

我有一个 PORO(普通旧 Ruby 对象)来处理一些业务逻辑。它接收一个 ActiveRecord 对象并对其进行分类。为了简单起见,以下面为例:

class Classificator
STATES = {
1 => "Positive",
2 => "Neutral",
3 => "Negative"
}

def initializer(item)
@item = item
end

def name
STATES.fetch(state_id)
end

private

def state_id
return 1 if @item.value > 0
return 2 if @item.value == 0
return 3 if @item.value < 0
end
end

但是,我还想根据这些 state_id“虚拟属性”对对象进行分组查询。我目前正在通过在 SQL 查询中创建此属性并在 GROUP BY 语句中使用它来处理这个问题。看例子:

class Classificator::Query
SQL_CONDITIONS = {
1 => "items.value > 0",
2 => "items.value = 0",
3 => "items.value < 0"
}

def initialize(relation = Item.all)
@relation = relation
end

def count
@relation.select(group_conditions).group('state_id').count
end

private
def group_conditions
'CASE ' + SQL_CONDITIONS.map do |k, v|
'WHEN ' + v.to_s + " THEN " + k.to_s
end.join(' ') + " END AS state_id"
end
end

这样,我就可以将此业务逻辑放入 SQL 中,并以非常高效的方式进行此类查询。

问题是:我有重复的业务逻辑。它存在于“ruby”代码中,用于对单个对象进行分类,也存在于“SQL”中,用于对数据库级别的对象集合进行分类。

这是一种不好的做法吗?有没有办法避免这种情况?我实际上能够做到这一点,执行以下操作:

item = Item.find(4)
items.select(group_conditions).where(id: item.id).select('state_id')

但是通过这样做,我失去了对未持久保存在数据库中的对象进行分类的能力。另一种出路是使用 Iterator 对 ruby​​ 中的每个对象进行分类,但那样我会失去数据库性能。

如果我需要两个案例中最好的一个,似乎不可避免地要保留重复的业务逻辑。但我只想确定这一点。 :)

谢谢!

最佳答案

我宁愿保持数据库简单,并尽可能将逻辑放在 Ruby 代码中。由于分类未存储在数据库中,因此我不希望查询返回它。

我的解决方案是定义一个将包含在 ActiveRecord 模型类中的关注点。

module Classified
extend ActiveSupport::Concern

STATES = {
1 => "Positive",
2 => "Neutral",
3 => "Negative"
}

included do
def state_name
STATES.fetch(state_id)
end

private

def state_id
(0 <=> value.to_i) + 2
end
end
end

class Item < ActiveRecord::Base
include Classified
end

我像往常一样从数据库中获取项目。

items = Item.where(...)

因为每个 item 都知道自己的分类值,所以我不必向数据库询问它。

items.each do |item|
puts item.state_name
end

关于ruby-on-rails - Ruby 和 SQL 中的重复业务逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36200972/

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