用于枚举的 i18n-tasks 自定义扫描器
i18n-tasks custom scanner for enums
我想为 i18n-tasks 创建一个自定义扫描器,它可以检测 enums 在 中声明为 hashes型号.
我的 enum 声明模式永远是这样的:
class Conversation < ActiveRecord::Base
enum status: { active: 0, archived: 1}, _prefix: true
enum subject: { science: 0, literature: 1, music: 2, art: 3 }, _prefix: true
end
枚举将始终声明为散列,并且始终具有数字散列值,并且始终在声明末尾具有选项 _prefix: true。散列中可以有任意数量的值。
我的自定义扫描仪目前看起来像这样:
require 'i18n/tasks/scanners/file_scanner'
class ScanModelEnums < I18n::Tasks::Scanners::FileScanner
include I18n::Tasks::Scanners::OccurrenceFromPosition
# @return [Array<[absolute key, Results::Occurrence]>]
def scan_file(path)
text = read_file(path)
text.scan(/enum\s([a-zA-Z]*?):\s\{.*\W(\w+):.*\}, _prefix: true$/).map do |prefix, attribute|
occurrence = occurrence_from_position(
path, text, Regexp.last_match.offset(0).first)
model = File.basename(path, ".rb") #.split('/').last
name = prefix + "_" + attribute
["activerecord.attributes.%s.%s" % [model, name], occurrence]
end
end
end
I18n::Tasks.add_scanner 'ScanModelEnums'
然而,这只是 return 每个散列的最后一个元素:
activerecord.attributes.conversation.status_archived
activerecord.attributes.conversation.subject_art
如何 return 每个散列的所有元素?我想看到这样的结果:
activerecord.attributes.conversation.status_active
activerecord.attributes.conversation.status_archived
activerecord.attributes.conversation.subject_science
activerecord.attributes.conversation.subject_literature
activerecord.attributes.conversation.subject_music
activerecord.attributes.conversation.subject_art
作为参考,i18n-tasks github 存储库提供了一个 example of a custom scanner.
它使用的文件扫描器class可以找到here。
这不是答案,这只是我所做的另一种尝试,它输出二维数组而不是单个数组:
require 'i18n/tasks/scanners/file_scanner'
class ScanModelEnums < I18n::Tasks::Scanners::FileScanner
include I18n::Tasks::Scanners::OccurrenceFromPosition
# @return [Array<[absolute key, Results::Occurrence]>]
def scan_file(path)
text = read_file(path)
text.scan(/enum\s([a-zA-Z]*?):\s\{(.*)\}, _prefix: true/).map do |prefix, attributes|
retval = []
model = File.basename(path, ".rb")
names = attributes.split(",").map!{ |e| e.strip; e.split(":").first.strip }
names.each do |attribute|
pos = (Regexp.last_match.offset(0).first + 8 + prefix.length + attributes.index(attribute))
occurrence = occurrence_from_position(
path, text, pos)
name = prefix + "_" + attribute
# p "================"
# p type
# p message
# p ["activerecord.attributes.%s.%s" % [model, name], occurrence]
# p "================"
retval.push(["activerecord.attributes.%s.%s" % [model, name], occurrence])
end
retval
end
end
end
I18n::Tasks.add_scanner 'ScanModelEnums'
然而,这给了我一个关于第二个检测到的属性的错误:
gems/i18n-tasks-0.9.34/lib/i18n/tasks/scanners/results/key_occurrences.rb:48:in `each': undefined method `path' for ["activerecord.attributes.conversation.status_archived", Occurrence(app/models/project.rb:3:32:98::)]:Array (NoMethodError)
这个有效:
def scan_file(path)
result = []
text = read_file(path)
text.scan(/enum\s([a-zA-Z]*?):\s\{(.*)}, _prefix: true$/).each do |prefix, body|
occurrence = occurrence_from_position(path, text,
Regexp.last_match.offset(0).first)
body.scan(/(\w+):/).flatten.each do |attr|
model = File.basename(path, ".rb")
name = "#{prefix}_#{attr}"
result << ["activerecord.attributes.#{model}.#{name}", occurrence]
end
end
result
end
它类似于您的'answer'方法,但使用正则表达式获取'{...}'之间的所有内容,然后使用另一个正则表达式获取每个枚举键名。
您的 'answer' 版本引发错误的可能原因是它实际上返回一个三维数组,而不是两个:
- 外层
.map
是所有迭代的数组
- 每次迭代returns
retval
,这是一个数组
retail
的每个元素都是 ['key', occurrence]
对的数组。
我想为 i18n-tasks 创建一个自定义扫描器,它可以检测 enums 在 中声明为 hashes型号.
我的 enum 声明模式永远是这样的:
class Conversation < ActiveRecord::Base
enum status: { active: 0, archived: 1}, _prefix: true
enum subject: { science: 0, literature: 1, music: 2, art: 3 }, _prefix: true
end
枚举将始终声明为散列,并且始终具有数字散列值,并且始终在声明末尾具有选项 _prefix: true。散列中可以有任意数量的值。
我的自定义扫描仪目前看起来像这样:
require 'i18n/tasks/scanners/file_scanner'
class ScanModelEnums < I18n::Tasks::Scanners::FileScanner
include I18n::Tasks::Scanners::OccurrenceFromPosition
# @return [Array<[absolute key, Results::Occurrence]>]
def scan_file(path)
text = read_file(path)
text.scan(/enum\s([a-zA-Z]*?):\s\{.*\W(\w+):.*\}, _prefix: true$/).map do |prefix, attribute|
occurrence = occurrence_from_position(
path, text, Regexp.last_match.offset(0).first)
model = File.basename(path, ".rb") #.split('/').last
name = prefix + "_" + attribute
["activerecord.attributes.%s.%s" % [model, name], occurrence]
end
end
end
I18n::Tasks.add_scanner 'ScanModelEnums'
然而,这只是 return 每个散列的最后一个元素:
activerecord.attributes.conversation.status_archived
activerecord.attributes.conversation.subject_art
如何 return 每个散列的所有元素?我想看到这样的结果:
activerecord.attributes.conversation.status_active
activerecord.attributes.conversation.status_archived
activerecord.attributes.conversation.subject_science
activerecord.attributes.conversation.subject_literature
activerecord.attributes.conversation.subject_music
activerecord.attributes.conversation.subject_art
作为参考,i18n-tasks github 存储库提供了一个 example of a custom scanner.
它使用的文件扫描器class可以找到here。
这不是答案,这只是我所做的另一种尝试,它输出二维数组而不是单个数组:
require 'i18n/tasks/scanners/file_scanner'
class ScanModelEnums < I18n::Tasks::Scanners::FileScanner
include I18n::Tasks::Scanners::OccurrenceFromPosition
# @return [Array<[absolute key, Results::Occurrence]>]
def scan_file(path)
text = read_file(path)
text.scan(/enum\s([a-zA-Z]*?):\s\{(.*)\}, _prefix: true/).map do |prefix, attributes|
retval = []
model = File.basename(path, ".rb")
names = attributes.split(",").map!{ |e| e.strip; e.split(":").first.strip }
names.each do |attribute|
pos = (Regexp.last_match.offset(0).first + 8 + prefix.length + attributes.index(attribute))
occurrence = occurrence_from_position(
path, text, pos)
name = prefix + "_" + attribute
# p "================"
# p type
# p message
# p ["activerecord.attributes.%s.%s" % [model, name], occurrence]
# p "================"
retval.push(["activerecord.attributes.%s.%s" % [model, name], occurrence])
end
retval
end
end
end
I18n::Tasks.add_scanner 'ScanModelEnums'
然而,这给了我一个关于第二个检测到的属性的错误:
gems/i18n-tasks-0.9.34/lib/i18n/tasks/scanners/results/key_occurrences.rb:48:in `each': undefined method `path' for ["activerecord.attributes.conversation.status_archived", Occurrence(app/models/project.rb:3:32:98::)]:Array (NoMethodError)
这个有效:
def scan_file(path)
result = []
text = read_file(path)
text.scan(/enum\s([a-zA-Z]*?):\s\{(.*)}, _prefix: true$/).each do |prefix, body|
occurrence = occurrence_from_position(path, text,
Regexp.last_match.offset(0).first)
body.scan(/(\w+):/).flatten.each do |attr|
model = File.basename(path, ".rb")
name = "#{prefix}_#{attr}"
result << ["activerecord.attributes.#{model}.#{name}", occurrence]
end
end
result
end
它类似于您的'answer'方法,但使用正则表达式获取'{...}'之间的所有内容,然后使用另一个正则表达式获取每个枚举键名。
您的 'answer' 版本引发错误的可能原因是它实际上返回一个三维数组,而不是两个:
- 外层
.map
是所有迭代的数组 - 每次迭代returns
retval
,这是一个数组 retail
的每个元素都是['key', occurrence]
对的数组。