提问人:Romuloux 提问时间:11/8/2023 最后编辑:Romuloux 更新时间:11/8/2023 访问量:31
数据库模型中的 Rails 建模和/或逻辑,带有 Acts As Taggable 开启
Rails Modeling And/Or Logic in a database model with Acts As Taggable On
问:
我正在尝试对逻辑进行建模,该逻辑将允许基于布尔逻辑的用户定义搜索返回 的某个子集。下面是代码。它没有经过测试,可能有错别字,因为它写在 SO 上只是为了思考这个问题。TaggedModel
# Basic widget, could be anything.
class TaggedModel < ActiveRecord
acts_as_taggable_on
end
# Represents a single piece of logic that can
# be chained together to create complex queries.
# Currently this would create n + 1 db queries, n = number of statements
# @attr inner_join_type [String] And/Or when it comes to tags within the statement.
# @attr preceding_statement [TagStatement] @optional The statement preceding this one.
# @attr preceding_statement_join_type [String] @optional And/Or to apply with
class TagStatement < ActiveRecord
acts_as_taggable_on
JOIN_TYPES = ['or','and']
belongs_to :preceding_statement, optional: true, class: 'TagStatement'
has_one :subsequent_statement, class: 'TagStatement', foreign_key: :preceding_statement_id
validates :inner_join_type, presence: true, inclusion: { in: JOIN_TYPES }
validates :preceding_statement_join_type, presence: true, inclusion: { in: JOIN_TYPES }, if: :preceding_statement
# Scope for all master statements.
# @return [ActiveRecord::Relation]
def self.master_statements
where(preceding_statement_id: nil)
end
# If the statement is a master statement.
# @return [Boolean]
def is_master
preceding_statement_id.nil?
end
# The basic statement applying to a single tagged model.
# @return [ActiveRecord::Relation<TaggedModel>]
def statement
if inner_join_type === 'or'
TaggedModel.tagged_with(tags, any: true)
else
TaggedModel.tagged_with(tags, match_all: true)
end
end
# Chains all the statements from this record and subsequent records.
# TODO: Write all the logic in here. Some sort of looping statement to go
# through all the records returned by the statements of the current model
# plus any subsequent models adding removing as necessary the ids from the
# ids array.
# @return [ActiveRecord::Relation<TaggedModel> The tagged models that apply given statement logic
def chained_statement(ids=[])
ids = []
if is_master
ids = (ids + statement.&ids).uniq # Uniq probably extra here
else
if preceding_statement_join_type == 'or'
ids.push(statement.&ids).uniq # Or so just add all ids together
else
ids = ids & statement.&ids # AND so remove any ids not present in statement ids.
end
end
if subsequent_statement
ids = subsequent_statement.chained_statement(ids)
end
ids
end
end
用户可以执行的操作示例:
创建一组语句,用于查找标记有
(“蓝色”或“红色”)AND ('green') => 标记为蓝色或红色但始终带有绿色的模型。 (“蓝色”和“红色”)OR ('green' AND 'RED') => 标有蓝色和红色或绿色和红色的型号。
我觉得我走在正确的轨道上,但也许我正在重新发明轮子?
答: 暂无答案
评论