ruby-1.9.2-p180 :023 > buffer = ''
ruby-1.9.2-p180 :024 > i = "buffer << \\\"[#user_id,#account_id]\\\""
=> "buffer << \\\"[#user_id,#account_id]\\\""
ruby-1.9.2-p180 :025 > eval i
SyntaxError: (eval):1: syntax error, unexpected $undefined
buffer << \"[#user_id,#account_id]\"
^
(eval):1: unterminated string meets end of file
from (irb):25:in `eval'
ruby-1.9.2-p180 :026 > j = "buffer << \"[#user_id,#account_id]\""
=> "buffer << \"[#user_id,#account_id]\""
ruby-1.9.2-p180 :027 > eval j
=> "[#user_id,#account_id]"
How do I convert i into j?
or
How to convert "buffer << \\"[#user_id,#account_id]\\"" into "buffer << \"[#user_id,#account_id]\" ?
The answer to your question "how do i convert i into j":
i.gsub(/\\/, '')
However, it very much looks as if the question is wrong and should rather be "how to I rewrite the surrounding code in order not having to do stuff like this in the first place".
Related
I'm reading in a csv file
require 'csv'
recipients = CSV.read('recipients.csv', headers: true)
found = []
if User.find_by(email: recipients['email'])
found << recipients['email']
end
table = CSV.table('recipients.csv')
table.delete_if do |t|
found.each { |f| t['email'] == f['email']}
end
CSV.open('/tmp/users.csv', 'wb') do |w|
w << found.to_csv
end
The following line: found.each { |f| t['email'] == f['email']}
results in a
TypeError: no implicit conversion of String into Integer
from lib/scripts/foo.rb:13:in[]'`
It's obvious I don't grok how to use delete_if and how to resolve the type mismatch in this case.
So, help is very much appreciated.
in line number 13
found.each { |f| t['email'] == f['email']}
f is an instance of Array and your are trying to pass a String as an index, so this might have occurred.
Explanation
> a=[]
=> []
2.2.1 :015 > a['email']
TypeError: no implicit conversion of String into Integer
from (irb):15:in `[]'
> a=['email', 'ram']
=> ["email", "ram"]
2.2.1 :018 > a['email']
TypeError: no implicit conversion of String into Integer
from (irb):18:in `[]'
Is it possible to intercept IRB inputs? Specifically for class#Fixnum?
Example:
5
=> 5
What I need to do is: (pseudo code)
if IRB.input.is_a?(Fixnum)
some_method(IRB.input) # some_method(5)
end
Look at this file.
You can find Irb#eval_input method and patch them:
# code before
#scanner.set_input(#context.io) do
signal_status(:IN_INPUT) do
if l = #context.io.gets
if l.match(/^\d+$/)
puts 'Integer found!'
end
print l if #context.verbose?
else
if #context.ignore_eof? and #context.io.readable_after_eof?
l = "\n"
if #context.verbose?
printf "Use \"exit\" to leave %s\n", #context.ap_name
end
else
print "\n"
end
end
l
end
end
# code after
Irb output example:
spark#think:~$ irb
2.1.5 :001 > 123
Integer found!
=> 123
2.1.5 :002 > "string"
=> "string"
I have two test cases where a data_valid? method is called. The first returns false and the second returns true, why?
55: def data_valid? d
56: crc = d[-1]
57: data = d[1..-2]
58: len = d[0]
=> 59: binding.pry
60: (data ^ len) == crc
61: end
2.0.0 (#<MicroAeth::Message:0x007fbefc3ceae8>):0 > (data ^ len) == crc
=> false
2.0.0 (#<MicroAeth::Message:0x007fbefc3ceae8>):0 > (data ^ len)
=> "\xB1"
2.0.0 (#<MicroAeth::Message:0x007fbefc3ceae8>):0 > crc
=> "\xB1"
2.0.0 (#<MicroAeth::Message:0x007fbefc3ceae8>):0 > exit
have a good day!
F
From: /Users/rudolph9/Projects/CombustionEmissionsTesting/micro_aeth.rb # line 59 MicroAeth::Message#data_valid?:
55: def data_valid? d
56: crc = d[-1]
57: data = d[1..-2]
58: len = d[0]
=> 59: binding.pry
60: (data ^ len) == crc
61: end
2.0.0 (#<MicroAeth::Message:0x007fbefe83a8c8>):0 > (data ^ len) == crc
=> true
2.0.0 (#<MicroAeth::Message:0x007fbefe83a8c8>):0 > (data ^ len)
=> "+"
2.0.0 (#<MicroAeth::Message:0x007fbefe83a8c8>):0 > crc
=> "+"
The following is my extension of the String class where I'm comparing the return of the custom XOR method ^.
class ::String
###
# #return the first charater in the string as an integer
def byte
self.bytes[0]
end
###
# XOR two strings
# #str assumed to be a one byte string or integer
def ^ str
if str.class == String
str = str.byte
elsif str.class == Fixnum
nil
else
raise "invalid arg: #{str.class} \n Must be String or Fixnum"
end
self.bytes.each do |i|
str = str ^ i
end
str.chr
end
end
I believe it has something to do with the first comparing non-ASCII characters. How do I properly set up the conditional?
You can use String#force_encoding to force a string into a specified encoding
2.0.0-p195 :001 > "\xB1".encoding
=> #<Encoding:UTF-8>
2.0.0-p195 :002 > eight_bit = "\xB1".force_encoding(Encoding::ASCII_8BIT)
=> "\xB1"
2.0.0-p195 :003 > eight_bit.encoding
=> #<Encoding:ASCII-8BIT>
2.0.0-p195 :004 > eight_bit == "\xB1"
=> false
2.0.0-p195 :005 > eight_bit.force_encoding(Encoding::UTF_8) == "\xB1"
=> true
2.0.0-p195 :006 > eight_bit.force_encoding("\xB1".encoding) == "\xB1"
=> true
Note the default encoding for Ruby 2.0.0 is UTF-8
irb(main):009:0> a = "good"
=> "good"
irb(main):010:0> a = "good" + "morning"
=> "goodmorning"
irb(main):011:0> a = "good"
=> "good"
irb(main):012:0> a << " morning"
=> "good morning"
Till now both the concatenation operators work fine.
irb(main):013:0> a = "good"
=> "good"
irb(main):014:0> a.freeze
=> "good"
irb(main):015:0> a.frozen?
=> true
irb(main):016:0> a << " welcome"
RuntimeError: can't modify frozen String
from (irb):16
from /usr/bin/irb:12:in `<main>'
irb(main):017:0> a = a + " welcome"
=> "good welcome"
But with a frozen string a difference is clearly visible from IRB that << and + are not behaving as they are supposed to. Could anyone tell me the reason for this?
They are doing exactly what they're supposed to. << modifies the string it is called on, while + is closer to str.dup << arg. This behavior is the defined, documented standard.
#Linuxios answer is perfect.
But still here I have tried to show that modification with more transparent way:
#ubuntu:~$ irb --simple-prompt
>> a = "good"
=> "good"
>> a.freeze
=> "good"
>> a.frozen?
=> true
>> a.object_id
=> 10557720 # holds the reference to the "good" string object.
>> a = a + " morning"
=> "good morning"
>> a.object_id
=> 10415700 # holds the reference to the new string object "good morning".
>> a.frozen?
=> false
>> ObjectSpace._id2ref(10415700)
=> "good morning"
>> ObjectSpace._id2ref(10557720)
=> "good"
>> ObjectSpace._id2ref(10557720).frozen?
=> true
We can conclude that - yes , string "good" is still frozen. Only the thing what happened is a referencing the new object "good morning". Only the reference assignment to a has been changed.
<< and + behave differently on ALL string objects, not just frozen ones. One (<<) modifies a string, and the other (+) returns a new string without modifying the original:
With <<:
string1 = "good"
#=> "good"
string2 = string1
#=> "good"
string1 << " morning"
#=> "good morning"
string1
#=> "good morning"
string2
#=> "good morning"
With +:
string1 = "good"
#=> "good"
string2 = string1
#=> "good"
string1 = string1 + " morning"
#=> "good morning"
string1
#=> "good morning"
string2
#=> "good"
Object#freeze is specifically designed to disallow the sort of behavior I demonstrated above with << (it prevents objects from being modified), so calling << on a frozen string results in an error.
Why isnt that working:
>> s = "hi"
=> "hi"
>> s == ("hi"|"ho")
NoMethodError: undefined method `|' for "hi":String
from (irb):2
>>
I don't get it.. Is there a solution for this kind of syntax? Because
s == ("hi"|"ho")
#is shorther than
s == "hi" || s == "ho"
Yes, the bitwise operator | is not defined in the String class: http://ruby-doc.org/core/classes/String.html
Consider this for expressiveness:
["hi", "ho"].include? myStr
irb(main):001:0> s = "hi"
=> "hi"
irb(main):002:0> ["hi", "ho"]
=> ["hi", "ho"]
irb(main):003:0> ["hi", "ho"].include? s
=> true
irb(main):004:0> s = "foo"
=> "foo"
irb(main):005:0> ["hi", "ho"].include? s
=> false
In most high level languages that syntax will not work, you have to stick to the longer syntax of:
s == "hi" || s == "ho"
Note that | is a bitwise or, whereas || is a regular or
You could use the include? method on array if you've got several == tests to do:
["hi", "ho"].include?(s)
Not shorter for two checks admittedly but it will be shorter for three or more.
This syntax doesn't exist in any language as far as I know.
What you are saying
s == ("hi"|"ho")
Literally translates to 'bitwise OR the strings "hi" and "ho" together and then compare them with s'. If you can't see why this is not what you are looking for, try writing down the ASCII codes for "hi" and "ho" and then bitwise ORing them together. You are going to get complete gibberish.
You could make it work that way:
irb> class Pair
def initialize(strA,strB)
#strA,#strB = strA,strB
end
def ==(string)
string == #strA || string == #strB
end
def |(other)
Pair.new(self,other)
end
end
#=> nil
irb> class String
def |(other)
Pair.new(self,other)
end
alias old_equals :==
def ==(other)
if other.kind_of? Pair
other == self
else
old_equals other
end
end
end
#=> nil
irb> ("one"|"two") == "one"
#=> true
irb> ("one"|"two") == "two"
#=> true
irb> ("one"|"two") == "three"
#=> false
irb> "one" == ("one"|"two")
#=> true
irb> "three" == ("one"|"two"|"three")
#=> true
But since this involves some monkey-patching of a fairly lowlevel class, I wouldn't advise relying on it. Other people will hate reading your code.
Ruby supports binary 'or' and other binary operations on values of type Fixnum and Bignum, meaning any integer. Bitwise operations aren't supported on strings or any other type, as far as I know.
As other people have mentioned, you probably want something other than binary operations altogether. However, you can easily get integer representations of characters, so you can compare characters like so:
a = "Cake"
b = "Pie"
puts a[0] | b[0] # Prints "83" - C is 67 and P is 80.
You can get an array of the comparisons easily with some conversions.
a = "Cake"
b = "Pie " # Strings of uneven length is trivial but more cluttered.
a_arr = a.split(//)
b_arr = b.split(//)
c_arr = []
a.each_with_index { |char, i| c.push(a[i].to_i | b[i].to_i) }
# If you *really* want an ASCII string back...
c = c_arr.collect(&:chr).join
You could use a regex:
Like so:
regex = /hi|ho/
s = "hi"
t = "foo"
s =~ regex
#=> 0
t =~ regex
#=> nil