如何在水晶的宏中合并命名元组?



我正在尝试基于两个命名元组的合并在类(OtherThing)中进行JSON.mapping

class Thing
MAPPING = {
id:                  {type: String, default: UUID.random.to_s},
email:               {type: String, nilable: true},
}
JSON.mapping({{MAPPING}})
end
class OtherThing
MAPPING = Thing::MAPPING.merge({
address:                              String,
city:                                 String,
zip:                                  {type: String, nilable: true},
latitude:                             {type: Float64, nilable: true},
longitude:                            {type: Float64, nilable: true},
})
JSON.mapping({{MAPPING}})
end

这会产生错误,具体取决于我如何组织代码。

一个错误:

Error expanding macro
FOR expression must be an array, hash or tuple literal, not Call:
Thing::MAPPING.merge
{% for key, value in _properties_ %}
^~~~~~~~~~~~

另一个可能的错误:

undefined macro method 'NamedTupleLiteral#merge'OtherThingJSON.mapping

简而言之 — 不,您现在无法在宏中插值常量。

@asterite:

问题是映射宏期望 HashLiteral 作为 参数,但现在他们收到一个路径

在您的情况下,命名元组宏获得了调用节点。在讨论 Crystal repo 时,https://github.com/crystal-lang/crystal/issues/2388 找到了理论上可以解决此问题的解决方法,但 JSON.mapping 它是旧方法,将在下一个版本中删除,而是尝试 JSON::可序列化

感谢@Blacksmoke16的帮助指出这一点,您可以通过使用 splats 定义自己的宏来实现预期的结果。

下面的代码应该可以工作。功劳归@Blacksmoke16

macro define(*args)
JSON.mapping(    
{% for t in args %}
{{t.double_splat}},
{% end %}
)
end
class Thing
MAPPING = {
id:                  {type: String, default: UUID.random.to_s},
email:               {type: String, nilable: true},
}
define {{MAPPING}}
end
class OtherThing
MAPPING = {
address:                              String,
city:                                 String,
zip:                                  {type: String, nilable: true},
latitude:                             {type: Float64, nilable: true},
longitude:                            {type: Float64, nilable: true},
}
define {{MAPPING}}, {{Thing::MAPPING}}
end

相关内容

  • 没有找到相关文章

最新更新