3

I have complex structure in YAML like this

yaml = <<-STR
'Tunisie Telecom':
  regex: 'StarTrail TT[);/ ]'
  device: 'smartphone'
  model: 'StarTrail'

Palm:
  regex: '(?:Pre|Pixi)/(\d+)\.(\d+)|Palm|Treo|Xiino'
  device: 'smartphone'
  models:
    - regex: '((?:Pre|Pixi))/(\d+\.\d+)'
      model: '$1 $2'
    - regex: 'Palm(?:[ \-])?((?!OS|Source|scape)[a-z0-9]+)'
      model: '$1'
STR

I'm try to parse it with YAML.mapping:

class Mobile
  YAML.mapping(
    name: Hash(String, Hash(String, String))
  )
end

puts Mobile.from_yaml(yaml)

And got parse exception:

Missing yaml attribute: name at line 1, column 1 (YAML::ParseException)
  from /usr/local/Cellar/crystal-lang/0.24.2_1/src/yaml/nodes/nodes.cr:30:9 in 'raise'
  from mobiles_mapping.cr:0:3 in 'initialize'
  from mobiles_mapping.cr:20:3 in 'new'
  from /usr/local/Cellar/crystal-lang/0.24.2_1/src/yaml/from_yaml.cr:2:3 in 'from_yaml'
  from mobiles_mapping.cr:25:1 in '__crystal_main'
  from /usr/local/Cellar/crystal-lang/0.24.2_1/src/crystal/main.cr:11:3 in '_crystal_main'
  from /usr/local/Cellar/crystal-lang/0.24.2_1/src/crystal/main.cr:112:5 in 'main_user_code'
  from /usr/local/Cellar/crystal-lang/0.24.2_1/src/crystal/main.cr:101:7 in 'main'
  from /usr/local/Cellar/crystal-lang/0.24.2_1/src/crystal/main.cr:135:3 in 'main'

But if I try to parse with YAML.parse:

{"Tunisie Telecom" => {"regex" => "StarTrail TT[);/ ]", "device" => "smartphone", "model" => "StarTrail"}, "Palm" => {"regex" => "(?:Pre|Pixi)/(d+).(d+)|Palm|Treo|Xiino", "device" => "smartphone", "models" => [{"regex" => "((?:Pre|Pixi))/(d+.d+)", "model" => "$1 $2"}, {"regex" => "Palm(?:[ -])?((?!OS|Source|scape)[a-z0-9]+)", "model" => "$1"}]}}

What's my mistake?

Online example: https://play.crystal-lang.org/#/r/41yk

UPD: I understood: macros can't found key 'name' but how can parse without key => val like in my case where we have only key?

Sergey Fedorov
  • 3,696
  • 2
  • 17
  • 21

1 Answers1

4

What you have is a Hash(String, Mobile), where Mobile is similar to

class Mobile
  YAML.mapping({
    regex: String,
    device: String,
    model: String?,
    models: Array(...)?
  })
end

So, to parse that you should call Hash(String, Mobile).from_yaml.

The code you wrote would work (ish) if your YAML was:

name:
  'Tunisie Telecom':
    regex: 'StarTrail TT[);/ ]'
    device: 'smartphone'
    model: 'StarTrail'

  Palm:
    regex: '(?:Pre|Pixi)/(\d+)\.(\d+)|Palm|Treo|Xiino'
    device: 'smartphone'
    models:
      - regex: '((?:Pre|Pixi))/(\d+\.\d+)'
        model: '$1 $2'
      - regex: 'Palm(?:[ \-])?((?!OS|Source|scape)[a-z0-9]+)'
        model: '$1'
Stephie
  • 3,135
  • 17
  • 22
  • Thanks @RX14, you are right! But in original YAML-file (https://github.com/matomo-org/device-detector/blob/master/regexes/device/mobiles.yml) i do not have key 'name', see update. My problem is that I can not specify this structure (without name) in YAML.mapping. – Sergey Fedorov May 11 '18 at 12:55
  • 1
    @SergeyFedorov yes, I think you need to re-read my answer. I understand that your YAML doesn't have the `name` key, and I gave the correct answer for if it doesn't have the `name` key. I gave the example YAML to help you understand the difference between what you wrote and what I wrote – Stephie May 11 '18 at 17:12