我正在寻找在Ruby on Rails 5.1中实现以下内容的正确方法:
我有一个ActiveRecord 平台,其属性为{em> LONGTEXT 的属性structure_xml
。它包含纯XML。我想添加一个包含辅助方法的包装器来查询XML(使用Nokogiri),例如找到某些节点或验证它。
我目前的解决方案
非ActiveRecord模型结构实现了所需的方法:
def Structure
def initialize(xml)
@xml_root = Nokogiri::XML(xml).root
end
def get_node_by_id(node_id)
@xml_root.xpath(".//Node[@id='#{node_id}']").first
end
...
end
如果需要,ActiveRecord模型会初始化此模型:
class Platform < ApplicationRecord
attr_accessor :structure
def structure
@structure || (@structure = Structure.new(structure_xml))
end
...
end
它有效,但对我来说似乎并不理想。实现这个的正确方法是什么?
答案 0 :(得分:1)
我相信,Rails的方式是引入类似的DSL(未经过测试,但它应该开箱即用):
module Structured
def self.extended base
base.send :define_method, :structure do
@structure ||= {}
end
end
def structured(*fields)
fields.each do |field|
define_method "#{field}_structure" do
structure[field] ||= Structure.new(public_send field)
end
end
end
end
在初始化程序中的某处:
ApplicationRecord.extend Structured
并在您的Platform
中(假设它有一个包含原始xml的字段data
):
class Platform < ApplicationRecord
structured :data
def print_it_out
data_structure.get_node_by_id(3)
end
end
答案 1 :(得分:1)
你似乎正走在正确的道路上。我可能会做同样的改变:
class Platform < ApplicationRecord
delegate :xml_root, :my_method1, :my_method2, to: :structure
def structure
@structure ||= Structure.new(structure_xml)
end
...
end
delegate
允许您调用另一个对象中定义的操作,而无需浏览它。
只有在需要命名空间,多个类中的相同方法以及这些方法独立于类的对象时才创建模块。
答案 2 :(得分:0)