I'm looking for some help with my code...
# save text file to string
data = File.read("workdata.txt")
# split string into blocks of text relevant to each journey
journeys = data.split(/\n\s\n/)
# store the amount of journeys as a variable called journeys_size
journeys_size = journeys.length
# split each journey into lines and save to an array called "journey_lines"
#journey_lines = journeys.map { |i| i.split(/\n/) }
# cretae an array called "all_journey_objects" to hold all journeys
all_journey_objects = []
# step through the journey arrays
#journey_lines.each do |line|
next if line[0].include?("position") # skip the journey block of text if it contains position
destinations = []
destination1 = line[12].upcase
destination2 = line[13].scan(/[a-z]+/i).join(" ").upcase
# destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase # <---- When i uncomment this line **
# destination4 = line[15].scan(/[a-z]+/i).join(" ").upcase
# destination5 = line[16].scan(/[a-z]+/i).join(" ").upcase
puts destination1
puts destination2
# puts destination3 # <---- When i uncomment this line **
# puts destination5
# puts destination4
# journey = Journey.new(line[0] , line[1] , line[6] , destinations, etas, windows)
# all_journey_objects << journey
end
The problem I am having is the following error when executed:
watcher.rb:47: in 'block in <main>': undefined method'scan' for nil:NilClass (NoMethodError)
I think the reason is because the "workdata.txt" file that I am working with, contains some journeys which only have two destinations. So, as soon as i uncomment the lines to create a third destination variable it throws an error. Maybe because it is trying to run a method against an object that doesn't exist?
I am stuck with finding a way around this. Any help would be appreciated...
If this is line 47:
destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase
undefined method `scan' for nil:NilClass indicates that you are sending scan to nil. In other words, line[14] is nil.
You could simply add an if statement:
if line[14]
destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase
end
Or an inline if:
destination3 = line[14].scan(/[a-z]+/i).join(" ").upcase if line[14]
Related
I've defined this method on ruby ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14] and (Rails 4.2.5.2)
def log_method_backtrace
backtrace = []
(4..8).map do |i| # 4 because before is ... map, log_method_backtrace...
b = caller[i][/\/(?:.(?!\/))+$/]
b = b[1..-2] # *This is the error line
b = b.sub(':in `', '#')
backtrace << "#{b} <- "
end
log "(Method called from #{backtrace.join})"
end
When I call it it throw this error:
NoMethodError: undefined method `[]' for nil:NilClass from (pry):5:in `block in log_method_backtrace'
But if I place a debugger breakpoint (I'm using binding.pry) in that line, and run the same line it works.
caller is a native Ruby method that returns the current execution stack as an array of strings. The problem I was having was because, as my code was running in the console one of the lines was:
"(pry):7:in `<main>'"
All the other lines had a filename/line/method name format as:
/...../gems/pry-0.9.12.6/lib/pry/pry_instance.rb:328:in `eval'
The regular expresion that I was using [/\/(?:.(?!\/))+$/] was expected to capture the filename as the line had no a filename it returned nil and the b[-1..2] was throwing an error as b was `nil.
While I'm debugging the caller variable got replaced on the binding.pry execution time, making the code work.
This is how I fixed the code to make it work:
def log_method_backtrace
backtrace = []
(4..8).map do |i| # 4 because before is ... map, log_method_backtrace...
line = caller[i]
b = line[/\/(?:.(?!\/))+$/] || line
b = b[1..-2]
b = b.sub(':in `', '#')
backtrace << "#{b} <- "
end
log "(Method called from #{backtrace.join})"
end
I am getting an error when executing my test.
Failure/Error: expect(industry_sic_code).to include page.sic_code
TypeError:
no implicit conversion of Array into String
# ./spec/os/bal/company/company_filter_clean_harbors_industries_stub.rb:62:in `block (2 levels) in <top (required)>'
The Method:
def sic_code
subtables = #b.table(:class => 'industry-codes').tables(:class => 'industry-code-table')
subtables.each do |subtable|
if subtable.tbody.h4.text == "US SIC 1987:"
subtable.tr.next_siblings.each do |tr|
codes = tr.cell
puts codes.text.to_s
end
end
end
end
The Test:
it 'Given I search for a random Clean Harbors Industry' do
#Pick a random clean industry from the file
data = CSV.foreach(file_path, headers: true).map{ |row| row.to_h }
random = data.sample
random_industry = random["Class"]
industry_sic_code = random["SIC Code"]
end
it 'Then the result has the expected SIC code' do
page = DetailPage.new(#b)
page.view
expect(industry_sic_code).to include page.sic_code
end
I have tried to implicitly change each variable to a string but it still complain about the array issue.
When I include some puts statments, I get some really wonky responses. The method itself returns the expected result.
When I used the method in the test I end up with the code gibberish below.
here are the sic codes from the method
5511
Here are the codes from the test
#<Watir::Table:0x00007fa3cb23f020>
#<Watir::Table:0x00007fa3cb23ee40>
#<Watir::Table:0x00007fa3cb23ec88>
#<Watir::Table:0x00007fa3cb23ead0>
#<Watir::Table:0x00007fa3cb23e918>
#<Watir::Table:0x00007fa3cb23e738>
#<Watir::Table:0x00007fa3cb23e580>
Your sic_code method returns subtables array, that's why you have this error. It doesn't matter that the method puts something, every method in ruby implicitly returns result of its last line, in your case it is subtables.each do ... end, so you have an array.
You need to explicitly return needed value. Not sure if I correctly understood what are you doing in your code, but try something like this:
def sic_code
subtables = #b.table(:class => 'industry-codes').tables(:class => 'industry-code-table')
result = [] # you need to collect result somewhere to return it later
subtables.each do |subtable|
if subtable.tbody.h4.text == "US SIC 1987:"
subtable.tr.next_siblings.each do |tr|
codes = tr.cell
result << codes.text.to_s
end
end
end
result.join(', ')
end
I have written an assertion that collects new records created while it yields to a block. Here's an example, with a failing assertion inside that block:
product =
assert_latest_record Product do # line 337
post :create,
:product => { ... }
assert false # line 340
end
The source of my assertion is below, but I don't think it's relevant. It does not intercept Minitest exceptions, or even call rescue or ensure.
The problem is when an assertion inside that block fails. The fault diagnostic message reports the line number as 337 the line of the outer assertion, not 340, the line of the inner assertion that failed. This is important if, for example, my colleagues have written a run-on test with way too many lines in it; isolating a failing line becomes more difficult.
Why doesn't Minitest report the correct line number?
The source:
##
# When a test case calls methods that write new ActiveModel records to a database,
# sometimes the test needs to assert those records were created, by fetching them back
# for inspection. +assert_latest_record+ collects every record in the given model or
# models that appear while its block runs, and returns either a single record or a ragged
# array.
#
# ==== Parameters
#
# * +models+ - At least 1 ActiveRecord model or association.
# * +message+ - Optional string or ->{block} to provide more diagnostics at failure time.
# * <code>&block</code> - Required block to call and monitor for new records.
#
# ==== Example
#
# user, email_addresses =
# assert_latest_record User, EmailAddress, ->{ 'Need moar records!' } do
# post :create, ...
# end
# assert_equal 'franklyn', user.login # 1 user, so not an array
# assert_equal 2, email_addresses.size
# assert_equal 'franklyn#gmail.com', email_addresses.first.mail
# assert_equal 'franklyn#hotmail.com', email_addresses.second.mail
#
# ==== Returns
#
# The returned value is a set of one or more created records. The set is normalized,
# so all arrays of one item are replaced with the item itself.
#
# ==== Operations
#
# The last argument to +assert_latest_record+ can be a string or a callable block.
# At failure time the assertion adds this string or this block's return value to
# the diagnostic message.
#
# You may call +assert_latest_record+ with anything that responds to <code>.pluck(:id)</code>
# and <code>.where()</code>, including ActiveRecord associations:
#
# user = User.last
# email_address =
# assert_latest_record user.email_addresses do
# post :add_email_address, user_id: user.id, ...
# end
# assert_equal 'franklyn#philly.com', email_address.mail
# assert_equal email_address.user_id, user.id, 'This assertion is redundant.'
#
def assert_latest_record(*models, &block)
models, message = _get_latest_record_args(models, 'assert')
latests = _get_latest_record(models, block)
latests.include?(nil) and _flunk_latest_record(models, latests, message, true)
pass # Increment the test runner's assertion count
return latests.size > 1 ? latests : latests.first
end
##
# When a test case calls methods that might write new ActiveModel records to a
# database, sometimes the test must check that no records were written.
# +refute_latest_record+ watches for new records in the given class or classes
# that appear while its block runs, and fails if any appear.
#
# ==== Parameters
#
# See +assert_latest_record+.
#
# ==== Operations
#
# refute_latest_record User, EmailAddress, ->{ 'GET should not create records' } do
# get :index
# end
#
# The last argument to +refute_latest_record+ can be a string or a callable block.
# At failure time the assertion adds this string or this block's return value to
# the diagnostic message.
#
# Like +assert_latest_record+, you may call +refute_latest_record+ with anything
# that responds to <code>pluck(:id)</code> and <code>where()</code>, including
# ActiveRecord associations.
#
def refute_latest_record(*models, &block)
models, message = _get_latest_record_args(models, 'refute')
latests = _get_latest_record(models, block)
latests.all?(&:nil?) or _flunk_latest_record(models, latests, message, false)
pass
return
end
##
# Sometimes a test must detect new records without using an assertion that passes
# judgment on whether they should have been written. Call +get_latest_record+ to
# return a ragged array of records created during its block, or +nil+:
#
# user, email_addresses, posts =
# get_latest_record User, EmailAddress, Post do
# post :create, ...
# end
#
# assert_nil posts, "Don't create Post records while creating a User"
#
# Unlike +assert_latest_record+, +get_latest_record+ does not take a +message+ string
# or block, because it has no diagnostic message.
#
# Like +assert_latest_record+, you may call +get_latest_record+ with anything
# that responds to <code>.pluck(:id)</code> and <code>.where()</code>, including
# ActiveRecord associations.
#
def get_latest_record(*models, &block)
assert models.any?, 'Call get_latest_record with one or more ActiveRecord models or associations.'
refute_nil block, 'Call get_latest_record with a block.'
records = _get_latest_record(models, block)
return records.size > 1 ? records : records.first
end # Methods should be easy to use correctly and hard to use incorrectly...
def _get_latest_record_args(models, what) #:nodoc:
message = nil
message = models.pop unless models.last.respond_to?(:pluck)
valid_message = message.nil? || message.kind_of?(String) || message.respond_to?(:call)
models.length > 0 && valid_message and return models, message
raise "call #{what}_latest_record(models..., message) with any number\n" +
'of Model classes or associations, followed by an optional diagnostic message'
end
private :_get_latest_record_args
def _get_latest_record(models, block) #:nodoc:
id_sets = models.map{ |model| model.pluck(*model.primary_key) } # Sorry about your memory!
block.call
record_sets = []
models.each_with_index do |model, index|
pk = model.primary_key
set = id_sets[index]
records =
if set.length == 0
model
elsif pk.is_a?(Array)
pks = pk.map{ |k| "`#{k}` = ?" }.join(' AND ')
pks = [ "(#{pks})" ] * set.length
pks = pks.join(' OR ')
model.where.not(pks, *set.flatten)
else
model.where.not(pk => set)
end
records = records.order(pk).to_a
record_sets.push records.size > 1 ? records : records.first
end
return record_sets
end
private :_get_latest_record
def _flunk_latest_record(models, latests, message, polarity) #:nodoc:
itch_list = []
models.each_with_index do |model, index|
records_found = latests[index] != nil
records_found == polarity or itch_list << model.name
end
itch_list = itch_list.join(', ')
diagnostic = "should#{' not' unless polarity} create new #{itch_list} record(s) in block"
message = nil if message == ''
message = message.call.to_s if message.respond_to?(:call)
message = [ message, diagnostic ].compact.join("\n")
raise Minitest::Assertion, message
end
private :_flunk_latest_record
You could try to configure it to log exceptions in test_helper.rb:
def MiniTest.filter_backtrace(backtrace)
backtrace
end
I'm not sure if this is the default, but depending on your configuration, the backtrace might not be shown.
I am trying to create a ruby tool that goes through a file looking for a certain string, and if it finds that word than it stores it in a variable. If NOT then it prints “word not found” on the console. Is this possible? How can i code this?
You can use File#open method and readlinesmethod like this.
test.txt
This is a test string.
Lorem imsum.
Nope.
code
def get_string_from_file(string, file_path)
File.open(file_path) do |f|
f.readlines.each { |line| return string if line.include?(string) }
end
nil
end
file_path = './test.txt'
var = get_string_from_file('Lorem', file_path)
puts var || "word not found"
# => "Lorem"
var = get_string_from_file('lorem', file_path)
puts var || "word not found"
# => "word not found"
I hope this heps.
Here's few examples of how you could find a certain word in a text file using IO from the Ruby core: http://ruby-doc.org/core-2.3.1/
In find_word_in_text_file.rb:
# SETUP
#
filename1 = 'file1.txt'
filename2 = 'file2.txt'
body1 = <<~EOS
PHRASES
beside the point
irrelevant.
case in point
an instance or example that illustrates what is being discussed: the “green revolution” in agriculture is a good case in point.
get the point
understand or accept the validity of someone's idea or argument: I get the point about not sending rejections.
make one's point
put across a proposition clearly and convincingly.
make a point of
make a special and noticeable effort to do (a specified thing): she made a point of taking a walk each day.
EOS
body2 = <<~EOS
nothing to see here
or here
or here
EOS
# write body to file
File.open(filename1, 'w+') {|f| f.write(body1)}
# write file without matching word
File.open(filename2, 'w+') {|f| f.write(body2)}
# METHODS
#
# 1) search entire file as one string
def file_as_string_rx(filename, string)
# http://ruby-doc.org/core-2.3.1/Regexp.html#method-c-escape
# http://ruby-doc.org/core-2.3.1/Regexp.html#method-c-new
rx = Regexp.new(Regexp.escape(string), true) # => /whatevs/i
# read entire file to string
# http://ruby-doc.org/core-2.3.1/IO.html#method-i-read
text = IO.read(filename)
# search entire file for string; return first match
found_word = text[rx]
# print word or default string
puts found_word || "word not found"
# —OR—
#STDOUT.write found_word || "word not found"
#STDOUT.write "\n"
end
# 2) search line by line
def line_by_line_rx(filename, string)
# http://ruby-doc.org/core-2.3.1/Regexp.html#method-c-escape
# http://ruby-doc.org/core-2.3.1/Regexp.html#method-c-new
rx = Regexp.new(Regexp.escape(string), true) # => /whatevs/i
# create array to store line numbers of matches
matches_array = []
# search each line for string
# http://ruby-doc.org/core-2.3.1/IO.html#method-c-readlines
#lines = IO.readlines(filename)
#
# http://ruby-doc.org/core-2.3.1/Enumerable.html#method-i-each_with_index
# http://stackoverflow.com/a/5546681/1076207
# "Be wary of "slurping" files. That's when you
# read the entire file into memory at once.
# The problem is that it doesn't scale well.
#lines.each_with_index do |line,i|
#
# —OR—
#
# http://ruby-doc.org/core-2.3.1/IO.html#method-c-foreach
i = 1
IO.foreach(filename) do |line|
# add line number if match found within line
matches_array.push(i) if line[rx]
i += 1
end
# print array or default string
puts matches_array.any? ? matches_array.inspect : "word not found"
# —OR—
#STDOUT.write matches_array.any? ? matches_array.inspect : "word not found"
#STDOUT.write "\n"
end
# RUNNER
#
string = "point"
puts "file_as_string_rx(#{filename1.inspect}, #{string.inspect})"
file_as_string_rx(filename1, string)
puts "\nfile_as_string_rx(#{filename2.inspect}, #{string.inspect})"
file_as_string_rx(filename2, string)
puts "\nline_by_line_rx(#{filename1.inspect}, #{string.inspect})"
line_by_line_rx(filename1, string)
puts "\nline_by_line_rx(#{filename2.inspect}, #{string.inspect})"
line_by_line_rx(filename2, string)
# CLEANUP
#
File.delete(filename1)
File.delete(filename2)
Command line:
$ ruby find_word_in_text_file.rb
file_as_string_rx("file1.txt", "point")
point
file_as_string_rx("file2.txt", "point")
word not found
line_by_line_rx("file1.txt", "point")
[3, 6, 7, 9, 10, 12, 15, 16]
line_by_line_rx("file2.txt", "point")
word not found
I'm trying to run a puppet apply and thrown with bunch of errors.
hiera -c /etc/puppet/hiera.yaml classes
generates the following :
/usr/share/ruby/vendor_ruby/2.0/psych.rb:205:in `parse': (<unknown>): found character that cannot start any token while scanning for the next token at line 238 column 3 (Psych::SyntaxError)
from /usr/share/ruby/vendor_ruby/2.0/psych.rb:205:in `parse_stream'
from /usr/share/ruby/vendor_ruby/2.0/psych.rb:153:in `parse'
from /usr/share/ruby/vendor_ruby/2.0/psych.rb:129:in `load'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend/yaml_backend.rb:18:in `block (2 levels) in lookup'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/filecache.rb:53:in `read_file'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend/yaml_backend.rb:17:in `block in lookup'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:104:in `block in datasourcefiles'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:76:in `block in datasources'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:74:in `map'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:74:in `datasources'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:99:in `datasourcefiles'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend/yaml_backend.rb:16:in `lookup'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:206:in `block in lookup'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:203:in `each'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera/backend.rb:203:in `lookup'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/lib/hiera.rb:60:in `lookup'
from /usr/local/share/ruby/gems/2.0/gems/hiera-1.3.4/bin/hiera:225:in `<top (required)>'
from /usr/local/bin/hiera:23:in `load'
from /usr/local/bin/hiera:23:in `<main>'
contents of the file:
require 'psych.so'
require 'psych/nodes'
require 'psych/streaming'
require 'psych/visitors'
require 'psych/handler'
require 'psych/tree_builder'
require 'psych/parser'
require 'psych/omap'
require 'psych/set'
require 'psych/coder'
require 'psych/core_ext'
require 'psych/deprecated'
require 'psych/stream'
require 'psych/json/tree_builder'
require 'psych/json/stream'
require 'psych/handlers/document_stream'
###
# = Overview
#
# Psych is a YAML parser and emitter.
# Psych leverages libyaml [Home page: http://pyyaml.org/wiki/LibYAML]
# or [Git repo: https://github.com/zerotao/libyaml] for its YAML parsing
# and emitting capabilities. In addition to wrapping libyaml, Psych also
# knows how to serialize and de-serialize most Ruby objects to and from
# the YAML format.
#
# = I NEED TO PARSE OR EMIT YAML RIGHT NOW!
#
# # Parse some YAML
# Psych.load("--- foo") # => "foo"
#
# # Emit some YAML
# Psych.dump("foo") # => "--- foo\n...\n"
# { :a => 'b'}.to_yaml # => "---\n:a: b\n"
#
# Got more time on your hands? Keep on reading!
#
# == YAML Parsing
#
# Psych provides a range of interfaces for parsing a YAML document ranging from
# low level to high level, depending on your parsing needs. At the lowest
# level, is an event based parser. Mid level is access to the raw YAML AST,
# and at the highest level is the ability to unmarshal YAML to ruby objects.
#
# === Low level parsing
#
# The lowest level parser should be used when the YAML input is already known,
# and the developer does not want to pay the price of building an AST or
# automatic detection and conversion to ruby objects. See Psych::Parser for
# more information on using the event based parser.
#
# === Mid level parsing
#
# Psych provides access to an AST produced from parsing a YAML document. This
# tree is built using the Psych::Parser and Psych::TreeBuilder. The AST can
# be examined and manipulated freely. Please see Psych::parse_stream,
# Psych::Nodes, and Psych::Nodes::Node for more information on dealing with
# YAML syntax trees.
#
# === High level parsing
#
# The high level YAML parser provided by Psych simply takes YAML as input and
# returns a Ruby data structure. For information on using the high level parser
# see Psych.load
#
# == YAML Emitting
#
# Psych provides a range of interfaces ranging from low to high level for
# producing YAML documents. Very similar to the YAML parsing interfaces, Psych
# provides at the lowest level, an event based system, mid-level is building
# a YAML AST, and the highest level is converting a Ruby object straight to
# a YAML document.
#
# === Low level emitting
#
# The lowest level emitter is an event based system. Events are sent to a
# Psych::Emitter object. That object knows how to convert the events to a YAML
# document. This interface should be used when document format is known in
# advance or speed is a concern. See Psych::Emitter for more information.
#
# === Mid level emitting
#
# At the mid level is building an AST. This AST is exactly the same as the AST
# used when parsing a YAML document. Users can build an AST by hand and the
# AST knows how to emit itself as a YAML document. See Psych::Nodes,
# Psych::Nodes::Node, and Psych::TreeBuilder for more information on building
# a YAML AST.
#
# === High level emitting
#
# The high level emitter has the easiest interface. Psych simply takes a Ruby
# data structure and converts it to a YAML document. See Psych.dump for more
# information on dumping a Ruby data structure.
module Psych
# The version is Psych you're using
VERSION = '2.0.0'
# The version of libyaml Psych is using
LIBYAML_VERSION = Psych.libyaml_version.join '.'
class Exception < RuntimeError
end
class BadAlias < Exception
end
###
# Load +yaml+ in to a Ruby data structure. If multiple documents are
# provided, the object contained in the first document will be returned.
# +filename+ will be used in the exception message if any exception is raised
# while parsing.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.load("--- a") # => 'a'
# Psych.load("---\n - a\n - b") # => ['a', 'b']
#
# begin
# Psych.load("--- `", "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
def self.load yaml, filename = nil
result = parse(yaml, filename)
result ? result.to_ruby : result
end
###
# Parse a YAML string in +yaml+. Returns the first object of a YAML AST.
# +filename+ is used in the exception message if a Psych::SyntaxError is
# raised.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Sequence:0x00>
#
# begin
# Psych.parse("--- `", "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# See Psych::Nodes for more information about YAML AST.
def self.parse yaml, filename = nil
parse_stream(yaml, filename) do |node|
return node
end
false
end
###
# Parse a file at +filename+. Returns the YAML AST.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
def self.parse_file filename
File.open filename, 'r:bom|utf-8' do |f|
parse f, filename
end
end
###
# Returns a default parser
def self.parser
Psych::Parser.new(TreeBuilder.new)
end
###
# Parse a YAML string in +yaml+. Returns the full AST for the YAML document.
# This method can handle multiple YAML documents contained in +yaml+.
# +filename+ is used in the exception message if a Psych::SyntaxError is
# raised.
#
# If a block is given, a Psych::Nodes::Document node will be yielded to the
# block as it's being parsed.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
#
# Psych.parse_stream("--- a\n--- b") do |node|
# node # => #<Psych::Nodes::Document:0x00>
# end
#
# begin
# Psych.parse_stream("--- `", "file.txt")
# rescue Psych::SyntaxError => ex
# ex.file # => 'file.txt'
# ex.message # => "(file.txt): found character that cannot start any token"
# end
#
# See Psych::Nodes for more information about YAML AST.
def self.parse_stream yaml, filename = nil, &block
if block_given?
parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
parser.parse yaml, filename
else
parser = self.parser
parser.parse yaml, filename
parser.handler.root
end
end
###
# call-seq:
# Psych.dump(o) -> string of yaml
# Psych.dump(o, options) -> string of yaml
# Psych.dump(o, io) -> io object passed in
# Psych.dump(o, io, options) -> io object passed in
#
# Dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
# to control the output format. If an IO object is passed in, the YAML will
# be dumped to that IO object.
#
# Example:
#
# # Dump an array, get back a YAML string
# Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
#
# # Dump an array to an IO object
# Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
#
# # Dump an array with indentation set
# Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n"
#
# # Dump an array to an IO with indentation set
# Psych.dump(['a', ['b']], StringIO.new, :indentation => 3)
#def self.dump o, io = nil, options = {}
def self.dump o, io = nil, options = {}
if Hash === io
options = io
io = nil
end
visitor = Psych::Visitors::YAMLTree.new options
visitor << o
visitor.tree.yaml io, options
end
###
# Dump a list of objects as separate documents to a document stream.
#
# Example:
#
# Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n"
def self.dump_stream *objects
visitor = Psych::Visitors::YAMLTree.new {}
objects.each do |o|
visitor << o
end
visitor.tree.yaml
end
###
# Dump Ruby object +o+ to a JSON string.
def self.to_json o
visitor = Psych::Visitors::JSONTree.new
visitor << o
visitor.tree.yaml
end
###
# Load multiple documents given in +yaml+. Returns the parsed documents
# as a list. If a block is given, each document will be converted to ruby
# and passed to the block during parsing
#
# Example:
#
# Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
#
# list = []
# Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
# list << ruby
# end
# list # => ['foo', 'bar']
#
def self.load_stream yaml, filename = nil
if block_given?
parse_stream(yaml, filename) do |node|
yield node.to_ruby
end
else
parse_stream(yaml, filename).children.map { |child| child.to_ruby }
end
end
###
# Load the document contained in +filename+. Returns the yaml contained in
# +filename+ as a ruby object
def self.load_file filename
File.open(filename, 'r:bom|utf-8') { |f| self.load f, filename }
end
# :stopdoc:
#domain_types = {}
def self.add_domain_type domain, type_tag, &block
key = ['tag', domain, type_tag].join ':'
#domain_types[key] = [key, block]
#domain_types["tag:#{type_tag}"] = [key, block]
end
def self.add_builtin_type type_tag, &block
domain = 'yaml.org,2002'
key = ['tag', domain, type_tag].join ':'
#domain_types[key] = [key, block]
end
def self.remove_type type_tag
#domain_types.delete type_tag
end
#load_tags = {}
#dump_tags = {}
def self.add_tag tag, klass
#load_tags[tag] = klass
#dump_tags[klass] = tag
end
class << self
attr_accessor :load_tags
attr_accessor :dump_tags
attr_accessor :domain_types
end
# :startdoc:
end
I have seen some references quoting
require 'yaml'
YAML::ENGINE.yamler = 'syck'
cannot find a config/boot.rb to try this.
I ripped out system wide ruby and the gems. Trying rvm and i still get similar errors :
I'm running hiera in debug mode :
[lame#TTBOX ~]$ hiera -d -c eye
Cannot find config file: eye
[lame#ipTTBOX ~]$ hiera -d eye
DEBUG: 2014-11-25 05:47:37 +0700: Hiera YAML backend starting
DEBUG: 2014-11-25 05:47:37 +0700: Looking up eye in YAML backend
DEBUG: 2014-11-25 05:47:37 +0700: Looking for data source default
/home/lame/.rvm/gems/ruby-2.1.5/gems/psych-2.0.6/lib/psych.rb:370:in `parse': (<unknown>): found character that cannot start any token while scanning for the next token at line 238 column 3 (Psych::SyntaxError)
from /home/lame/.rvm/gems/ruby-2.1.5/gems/psych-2.0.6/lib/psych.rb:370:in `parse_stream'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/psych-2.0.6/lib/psych.rb:318:in `parse'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/psych-2.0.6/lib/psych.rb:245:in `load'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend/yaml_backend.rb:18:in `block (2 levels) in lookup'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/filecache.rb:53:in `read_file'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend/yaml_backend.rb:17:in `block in lookup'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:104:in `block in datasourcefiles'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:76:in `block in datasources'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:74:in `map'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:74:in `datasources'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:99:in `datasourcefiles'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend/yaml_backend.rb:16:in `lookup'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:206:in `block in lookup'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:203:in `each'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera/backend.rb:203:in `lookup'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/lib/hiera.rb:60:in `lookup'
from /home/lame/.rvm/gems/ruby-2.1.5/gems/hiera-1.3.4/bin/hiera:225:in `<top (required)>'
from /home/lame/.rvm/gems/ruby-2.1.5/bin/hiera:23:in `load'
from /home/lame/.rvm/gems/ruby-2.1.5/bin/hiera:23:in `<main>'
from /home/lame/.rvm/gems/ruby-2.1.5/bin/ruby_executable_hooks:15:in `eval'
from /home/lame/.rvm/gems/ruby-2.1.5/bin/ruby_executable_hooks:15:in `<main>'
Are you suggesting me to have a look at the hiera file itself ?
Your error message says to look at line 238, column 3 of your yaml file. Check to see if you have any illegal characters there.