Получение ошибки - «не может использоваться совместно (ArgumentError)» Ruby - PullRequest
0 голосов
/ 29 апреля 2018

Я работаю над курсом Ruby и столкнулся с ошибкой при запуске одного из примеров. Вот мой класс по Ruby:

require 'json'

class User

  attr_accessor :email, :name, :permissions

  def initialize(*args)
    @email = args[0]
    @name = args[1]
    @permissions = User.permisisons_from_template
  end

  def self.permisisons_from_template
    file = File.read 'user_permissions_template.json'
    JSON.load(file, nil, symbolize_names: true)
  end

  def save
    self_json = {email: @email, name: @name, permissions: @permissions}.to_json
    open('users.json', 'a') do |file|
      file.puts self_json
    end
  end

end

Код файла моего бегуна выглядит следующим образом:

require 'pp'
require_relative 'user'

user = User.new 'john.doe@example.com', 'John Doe'

pp user

user.save

Я получаю эту ошибку, когда запускаю команду "ruby runner.rb":

/usr/local/rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/json/common.rb:156:in `initialize': options :symbolize_names and :create_additions cannot be  used in conjunction (ArgumentError)
        from /usr/local/rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/json/common.rb:156:in `new'
        from /usr/local/rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/json/common.rb:156:in `parse'
        from /usr/local/rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/json/common.rb:335:in `load'
        from /home/ec2-user/environment/section2_project/user.rb:15:in `permisisons_from_template'
        from /home/ec2-user/environment/section2_project/user.rb:10:in `initialize'
        from runner.rb:4:in `new'
        from runner.rb:4:in `<main>'

Я искал справку на сайте и предложил исправить это, чтобы удалить параметр nil. Теперь я из .Net, и я предположил, что я мог бы использовать proc: nil, и это также сработало бы, что и сработало. Я предполагаю, что ему не нравилось смешивать именованные параметры и позиционные параметры, но это не .Net, так что, возможно, мне просто повезло с моим предположением. Модератор сайта не был уверен, почему код не удался и почему удаление nil устранило проблему. Итак, мой вопрос:

Почему строка JSON.load(file, nil, symbolize_names: true) не работает, но JSON.load(file, proc: nil, symbolize_names: true) работает? Спасибо.

Wade

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

Это связано с тем, как аргументы передаются в методах ruby.

Здесь вы можете найти источник модуля json для метода загрузки.

А здесь ниже моя версия;) для своего рода объяснения.

def load(source, proc = nil, options = {})
  # firs parameter required, second and third are optional
  puts "source: #{source}"
  puts "proc: #{proc}"
  puts "options: #{options}"
  puts "- "*20
end

my_dummy_proc = Proc.new{|e| e}

load('filename_1',my_dummy_proc , {option1: :option1, option2: :option2}) # the 3rd is a hash
load('filename_2', my_dummy_proc, option1: :option1, option2: :option2) # the 3rd as a hash but with no braces
load('filename_3') # you can pass just the first argument
load('filename_4', my_dummy_proc) # you can pass just the first and the second
load('filename_5', option1: :option1, option2: :option2) # but not just the first and the third, unless you set the 2nd to nil (a sort of placeholder) if you skip nil as 2nd parameter, the hash is assigned to the second argument
load('filename_6', nil, option1: :option1, option2: :option2) # if no 2nd argument is passed, you need to set the second parameter to nil (as a placeholder)

О сообщении об ошибке, которое вы получили :symbolize_names and :create_additions cannot be used in conjunction, если вы попытаетесь, это должно работать:

JSON.load(file, nil, symbolize_names: true, create_additions: false)

0 голосов
/ 11 ноября 2018

Изменить symbolize_names: true на symbolize_names: false.

0 голосов
/ 29 апреля 2018

Здесь происходит то, что аргументы не анализируются так, как вы ожидаете. В Ruby есть функция, где любые key: value в конце списка аргументов превращаются в Hash без необходимости помещать {} вокруг них.

Например, если вы пишете метод:

def load(source, options = {})
end

Это можно назвать load(source), в этом случае options будет {}, или как что-то вроде load(source, foo: 5, bar: true), в этом случае options будет {foo: 5, bar: true}

Другая деталь заключается в том, что необязательные параметры со значениями по умолчанию заполняются слева направо.

Почему это актуально?

Что ж, в случае JSON.load(file, proc: nil, symbolize_names: true) proc: nil, symbolize_names: true становится хешем {proc: nil, symbolize_names: true}, и это затем заполняет позицию proc в списке аргументов, оставляя параметр options со значением по умолчанию. то есть вы на самом деле не устанавливаете symbolize_names: true, когда вы думали, что это так.

В случае JSON.load(file, nil, symbolize_names: true), nil заполняет значение параметра proc, и symbolize_names: true становится options. Это объединяется с параметрами по умолчанию в библиотеке JSON для предоставления полного набора параметров, {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true, :symbolize_names=>true}, который затем содержит конфликт, на который ссылается сообщение об ошибке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...