我正在研究Ruby课程,在运行其中一个示例时遇到了错误。这是我的Ruby类:
lineterminator
我的跑步者文件代码如下所示:
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
运行此命令时出现此错误" ruby runner.rb":
require 'pp'
require_relative 'user'
user = User.new 'john.doe@example.com', 'John Doe'
pp user
user.save
我在网站上寻求帮助,建议修复是删除nil参数。现在,我来自.Net背景,我推测我可以使用/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>'
,这也可以。我的假设是,它不喜欢命名参数和位置参数的混合,但这不是.Net,所以我可能只是对我的猜测很幸运。网站的主持人不确定代码失败的原因以及为什么删除nil修复了问题。所以,我的问题是:
为什么行proc: nil
失败,但JSON.load(file, nil, symbolize_names: true)
有效?感谢。
瓦德
答案 0 :(得分:7)
这里发生的事情是,这些论点并没有按照你期望的方式进行解析。 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)
1}}
另一个细节是具有默认值的可选参数从左到右填充。
为什么这有关系?
好吧,在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
会变为{:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true, :symbolize_names=>true}
。这与JSON库中的默认选项结合使用,以提供完整的选项集{{1}},然后包含错误消息引用的冲突。
答案 1 :(得分:1)
它与如何在ruby方法中传递参数有关。
Here你可以找到负载方法的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)
答案 2 :(得分:0)
将symbolize_names: true
更改为symbolize_names: false
。