sequel 中不同型号的相同 dataset-/filter-logic(干)
Same dataset-/filter-logic on different models in sequel (DRY)
我正在构建一个带有 sequel 数据库后端的 sinatra 网络应用程序。这个应用程序的主要任务是收集来自不同机器人的状态消息,将它们存储在数据库中并提供各种查看它们的方法。这些消息的一个共同点是,它们在 lat/lon 中提供 WGS84 位置。
现在我想提供各种过滤器来根据消息的位置查询消息,但我只想编写这些过滤器一次,只测试一次但在所有模型中重复使用它们-classes lat/lon 个条目。
将其归结为一个非常简单的示例:
Sequel.migration do
up do
create_table(:auvmessages) do
primary_key :id
Float :lat
Float :lon
String :message
end
create_table(:asvmessages) do
primary_key :id
Float :lat
Float :lon
Integer :chargestate
end
end
end
class Auvessage < Sequel::Model
dataset_module do
def north_of(lat)
self.where{ latitude > lat}
end
end
end
class Asvessage < Sequel::Model
dataset_module do
def north_of(lat)
self.where{ latitude > lat}
end
end
end
在两个模型中,classes 都具有 north_of(lat)
来过滤来自给定纬度以北的消息。这个函数比较简单,重复两三遍就可以了,但是复杂一点的情况呢?
我在 dataset_module
之外尝试了一些模块,但似乎没有什么是对的。
有没有更好的方法可以在不同的模型上重复使用过滤器?我搜索了很多,但没有找到满意的答案。
编辑:
为了让我的问题更精确一点:我想将所有功能如 north_of(lat)
(还有 lot)移动到服务 class.我现在想知道的是将该服务 class 集成到 sequel 模型中的最佳方式:
- "Just"包含吗?
- 扩展 dataset_module,如果是,怎么做?
- 正在编写数据集插件?
- ...
这是 Bob 叔叔 Screaming Architecture 博客 post 的 link,可能会有帮助。
现在,回答您的问题,似乎 north_of
以及许多其他方法实际上是您的域逻辑的一部分。此逻辑不应进入持久性抽象、控制器或视图等。
为一组对象设计、构建和编写测试,以使用您问题领域的语言解决您的问题。然后,您将拥有一组丰富的功能,您可以简单地在 Model
s、Controller
s、CLI 等
上使用
我通常将我的服务对象放在 lib/
目录中并编写简单的单元测试,没有任何设置测试数据库的持久性样板。他们通常 运行 也非常快。
您可以将现有模块传递给 dataset_module
:
module NorthOf
def north_of(lat)
where{latitude > lat}
end
end
Auvessage.dataset_module NorthOf
Asvessage.dataset_module NorthOf
作为后续行动:我采用了@jeremy-evans 并通过模块的参数化方案对其进行了扩展。所以从现在开始,我可以通过模拟来测试我的过滤器,我的模型 类 在它们的 dataset_module.
中只有一个包含列表
我喜欢
作为解释,我稍微修改了示例:
Sequel.migration do
up do
create_table(:auvmessages) do
primary_key :id
Float :lat
Float :lon
String :message
end
create_table(:asvmessages) do
primary_key :id
Float :gps_lat
Float :gps_lon
Integer :chargestate
end
end
end
module GPSFilter
def self.create(lat_name, lon_name)
Module.new do
include GPS
define_method :lat_col_name do
lat_name
end
define_method :lon_col_name do
lon_name
end
end
end
def north_of(lat)
where( "#{lat_col_name} > #{lat}" )
end
##### default parameters #####
def lon_col_name
"lon"
end
def lat_col_name
"lat"
end
end
class Auvmessage < Sequel::Model
dataset_module do
include GPSFilter
end
end
class Asvmessage < Sequel::Model
dataset_module do
include GPSFilter.create :gps_lat, :gps_lon
end
end
我正在构建一个带有 sequel 数据库后端的 sinatra 网络应用程序。这个应用程序的主要任务是收集来自不同机器人的状态消息,将它们存储在数据库中并提供各种查看它们的方法。这些消息的一个共同点是,它们在 lat/lon 中提供 WGS84 位置。
现在我想提供各种过滤器来根据消息的位置查询消息,但我只想编写这些过滤器一次,只测试一次但在所有模型中重复使用它们-classes lat/lon 个条目。
将其归结为一个非常简单的示例:
Sequel.migration do
up do
create_table(:auvmessages) do
primary_key :id
Float :lat
Float :lon
String :message
end
create_table(:asvmessages) do
primary_key :id
Float :lat
Float :lon
Integer :chargestate
end
end
end
class Auvessage < Sequel::Model
dataset_module do
def north_of(lat)
self.where{ latitude > lat}
end
end
end
class Asvessage < Sequel::Model
dataset_module do
def north_of(lat)
self.where{ latitude > lat}
end
end
end
在两个模型中,classes 都具有 north_of(lat)
来过滤来自给定纬度以北的消息。这个函数比较简单,重复两三遍就可以了,但是复杂一点的情况呢?
我在 dataset_module
之外尝试了一些模块,但似乎没有什么是对的。
有没有更好的方法可以在不同的模型上重复使用过滤器?我搜索了很多,但没有找到满意的答案。
编辑:
为了让我的问题更精确一点:我想将所有功能如 north_of(lat)
(还有 lot)移动到服务 class.我现在想知道的是将该服务 class 集成到 sequel 模型中的最佳方式:
- "Just"包含吗?
- 扩展 dataset_module,如果是,怎么做?
- 正在编写数据集插件?
- ...
这是 Bob 叔叔 Screaming Architecture 博客 post 的 link,可能会有帮助。
现在,回答您的问题,似乎 north_of
以及许多其他方法实际上是您的域逻辑的一部分。此逻辑不应进入持久性抽象、控制器或视图等。
为一组对象设计、构建和编写测试,以使用您问题领域的语言解决您的问题。然后,您将拥有一组丰富的功能,您可以简单地在 Model
s、Controller
s、CLI 等
我通常将我的服务对象放在 lib/
目录中并编写简单的单元测试,没有任何设置测试数据库的持久性样板。他们通常 运行 也非常快。
您可以将现有模块传递给 dataset_module
:
module NorthOf
def north_of(lat)
where{latitude > lat}
end
end
Auvessage.dataset_module NorthOf
Asvessage.dataset_module NorthOf
作为后续行动:我采用了@jeremy-evans
我喜欢
作为解释,我稍微修改了示例:
Sequel.migration do
up do
create_table(:auvmessages) do
primary_key :id
Float :lat
Float :lon
String :message
end
create_table(:asvmessages) do
primary_key :id
Float :gps_lat
Float :gps_lon
Integer :chargestate
end
end
end
module GPSFilter
def self.create(lat_name, lon_name)
Module.new do
include GPS
define_method :lat_col_name do
lat_name
end
define_method :lon_col_name do
lon_name
end
end
end
def north_of(lat)
where( "#{lat_col_name} > #{lat}" )
end
##### default parameters #####
def lon_col_name
"lon"
end
def lat_col_name
"lat"
end
end
class Auvmessage < Sequel::Model
dataset_module do
include GPSFilter
end
end
class Asvmessage < Sequel::Model
dataset_module do
include GPSFilter.create :gps_lat, :gps_lon
end
end