Boolean values with SQLite and Sequel - ruby

Sequel supports a boolean type.
It stores true and false as t and f in SQLite.
If you read again, the data are converted back to true and false
SQLite itself prefers to store true as 1 and false as 0 (and some SQLite-administartion tools expect it).
If I store my boolean also as '1', Sequel also converts the value to 'true':
require 'sequel'
DB = Sequel.sqlite()#'test.db')
DB.create_table(:test){
boolean :my_truth
nvarchar :descr, :size => 10
}
DB[:test].insert(1, '1')
p DB[:test].filter(:descr => '1').first #-> {:my_truth=>true, :descr=>"1"}
But if I select for true, no value is found:
DB[:test].filter(:my_truth => true).each{|ds|
puts "\t%s" % ds[:descr]
}
The values true and "t" are found:
DB[:test].insert(true, 'true')
DB[:test].insert('t', '"t"')
DB[:test].filter(:my_truth => true).each{|ds|
puts "\t%s" % ds[:descr] #true and 't'
}
There is a similar situation for false-values like 0... (see example code after the question)
So my question:
How can i make DB[:test].filter(:my_truth => true) to detect 1-values and
DB[:test].filter(:my_truth => false) to detect 0-values?
I'm not looking for something like DB[:test].filter(:my_truth => [true,1])
Similar question for Activerecord
Rails 3 SQLite3 Boolean false
I use Sequel 3.33.0
Example code:
require 'sequel'
DB = Sequel.sqlite()#'test.db')
DB.create_table(:test){
boolean :my_truth
nvarchar :descr, :size => 10
fixnum :line #code line, where data is inserted
}
#All true:
DB[:test].insert(true, 'true', __LINE__)
DB[:test].insert('true', '"true"', __LINE__)
DB[:test].insert(1, 'one', __LINE__)
DB[:test].insert('t', 't', __LINE__)
#All false:
DB[:test].insert(false,'false', __LINE__)
DB[:test].insert('false','"false"', __LINE__)
DB[:test].insert(0,'zero', __LINE__)
DB[:test].insert('f', 'f', __LINE__)
DB[:test].insert('F', 'F', __LINE__)
DB[:test].insert(nil, 'nil', __LINE__)
DB[:test].insert('n', 'n', __LINE__)
DB[:test].insert('N', 'N', __LINE__)
#Also true
DB[:test].insert('x', 'x', __LINE__)
DB[:test].insert(' ', 'space', __LINE__)
DB[:test].insert('', 'empty', __LINE__)
puts "All true values:"
DB[:test].filter(:my_truth => true).each{|ds|
puts "\t%s (line %i)" % [ds[:descr], ds[:line] ]
}
puts "All false values:"
DB[:test].filter(:my_truth => false).each{|ds|
puts "\t%s (line %i)" % [ds[:descr], ds[:line] ]
}
puts "Data:"
DB[:test].each{|ds|
puts "\t%-5s is <%s> (line %i)" % [ ds[:descr], ds[:my_truth].inspect, ds[:line] ]
}
Result:
All true values:
true (line 10)
t (line 13)
All false values:
false (line 16)
f (line 19)
Data:
true is <true> (line 10)
"true" is <true> (line 11)
one is <true> (line 12)
t is <true> (line 13)
false is <false> (line 16)
"false" is <false> (line 17)
zero is <false> (line 18)
f is <false> (line 19)
F is <false> (line 20)
nil is <nil> (line 21)
n is <false> (line 22)
N is <false> (line 23)
x is <true> (line 26)
space is <true> (line 27)
empty is <true> (line 28)

You can use the integer_booleans setting to use 1/0 as true/false, instead of 't'/'f', see http://sequel.rubyforge.org/rdoc-adapters/classes/Sequel/SQLite/DatabaseMethods.html. Here's an example:
DB = Sequel.sqlite(:integer_booleans=>true)

Related

Ruby - How do I shorten my method

I have a hash here:
VALID_CHOICES = {
'r' => 'rock',
'p' => 'paper',
'sc' => 'scissors',
'l' => 'lizard',
'sp' => 'spock'
}
And a method which basically compares here:
def win?(first, second)
(first == 'sc' && second == 'p') ||
(first == 'p' && second == 'r') ||
(first == 'r' && second == 'l') ||
(first == 'l' && second == 'sp') ||
(first == 'sp' && second == 'sc') ||
(first == 'sc' && second == 'l') ||
(first == 'l' && second == 'p') ||
(first == 'p' && second == 'sp') ||
(first == 'sp' && second == 'r') ||
(first == 'r' && second == 'sc')
end
How can I rewrite my method in very short concise code that means exactly the same thing? Any idea? Is it possible to do it using hashes?
You should define clear rules for what each token can win:
WINS = {
'r' => %w{l sc},
'p' => %w{r sp},
'sc' => %w{p l},
'l' => %w{p sp},
'sp' => %w{r sc}
}
Now you can determine wins using a simple lookup:
def win?(first, second)
WINS[first].include?(second)
end
While there may be several 'clever' ways to avoid an explicit structure like WINS, explicit rules are much more understandable - and therefore, more maintainable. Conciseness in code is considered a positive attribute where it improves the readability of the code. Conciseness to the extreme that causes the code to be difficult to understand is not something to strive for.
In addition to user2864740's comment and Cary Swoveland's explanation, you could also use a hash to map "winning pairs" to their respective verb:
WINS = {
%w[scissors paper] => 'cuts',
%w[paper rock] => 'covers',
%w[rock lizard] => 'crushes',
%w[lizard spock] => 'poisons',
%w[spock scissors] => 'smashes',
%w[scissors lizard] => 'decapitates',
%w[lizard paper] => 'eats',
%w[paper spock] => 'disproves',
%w[spock rock] => 'vaporizes',
%w[rock scissors] => 'crushes'
}
It returns the corresponding verb if the key's first item beats the second:
WINS[['paper', 'rock']] #=> "covers"
and nil if it doesn't:
WINS[['rock', 'paper']] #=> nil
In your method:
def win?(first, second)
WINS.has_key?([first, second])
end
Or to check both sides:
if WINS.has_key?([first, second])
# first wins
elsif WINS.has_key?([second, first])
# second wins
else
# tie
end
Or more verbose:
def result(first, second)
if verb = WINS[[first, second]]
"first wins: #{first} #{verb} #{second}"
elsif verb = WINS[[second, first]]
"second wins: #{second} #{verb} #{first}"
else
"tie"
end
end
result('rock', 'scissors')
#=> "first wins: rock crushes scissors"
result('spock', 'lizard')
#=> "second wins: lizard poisons spock"
result('paper', 'paper')
#=> "tie"
Of course, you can also use your abbreviations (sc, p, r, l, sp) instead of whole words.

Is this any condition type in ruby? !!() , !() , !0, !!0

I was just playing with irb. And I tried such syntax which returns me true/false
Can anyone please describe me why and how this behavior happened? Is this any condition type?
For Eg:
> !!()
=> false
> !()
=> true
> !0
=> false
> !!0
=> true
I appreciate if anyone can describe me this syntax.
()
# => nil
parenthesis are precedence 'operator', parenthesis with no expression return nil, as you see. So no wonder that:
!()
# => true
!!() # == !(!()) == !(true)
# => false
0 is truthy in Ruby (in fact, only nil and false are falsy):
puts 'truthy' if 0
truthy
# => nil
so the opposite of 0 is false:
!0
# => false
and !!0 is opposite to false:
!!0 # == !(!0) == !(false)
# => true
() evaluates as nil, which evaluates similar to false. Adding the ! Operator (once, twice, or however many times) simply changes false to true and true to false...

Difference between + and << in Ruby

Below are two identical classes with the difference of the operators + and <<. These can be found in the inject method. In the + case the tests pass and in the << some of them fail. Why?
class Integer
ROMAN_NUMERALS = {
0 => '',
1 => 'I', 2 => 'II', 3 => 'III', 4 => 'IV', 5 => 'V', 6 => 'VI', 7 => 'VII', 8 => 'VIII', 9 => 'IX',
10 => 'X', 20 => 'XX', 30 => 'XXX', 40 => 'XL', 50 => 'L', 60 => 'LX', 70 => 'LXX', 80 => 'LXXX', 90 => 'XC',
100 => 'C', 200 => 'CC', 300 => 'CCC', 400 => 'CD', 500 => 'D', 600 => 'DC', 700 => 'DCC', 800 => 'DCCC', 900 => 'CM',
1000 => 'M', 2000 => 'MM', 3000 => 'MMM'
}
def to_roman
to_s.reverse.chars.each_with_index.inject("") do |roman_numeral, (character, index)|
ROMAN_NUMERALS[character.to_i * 10 ** index] << roman_numeral
end
end
end
I get different results to when I run
class Integer
ROMAN_NUMERALS = {
0 => '',
1 => 'I', 2 => 'II', 3 => 'III', 4 => 'IV', 5 => 'V', 6 => 'VI', 7 => 'VII', 8 => 'VIII', 9 => 'IX',
10 => 'X', 20 => 'XX', 30 => 'XXX', 40 => 'XL', 50 => 'L', 60 => 'LX', 70 => 'LXX', 80 => 'LXXX', 90 => 'XC',
100 => 'C', 200 => 'CC', 300 => 'CCC', 400 => 'CD', 500 => 'D', 600 => 'DC', 700 => 'DCC', 800 => 'DCCC', 900 => 'CM',
1000 => 'M', 2000 => 'MM', 3000 => 'MMM'
}
def to_roman
to_s.reverse.chars.each_with_index.inject("") do |roman_numeral, (character, index)|
ROMAN_NUMERALS[character.to_i * 10 ** index] + roman_numeral
end
end
end
The tests I am using are below
require 'minitest/autorun'
require_relative 'roman'
class RomanTest < MiniTest::Unit::TestCase
def test_1
assert_equal 'I', 1.to_roman
end
def test_2
assert_equal 'II', 2.to_roman
end
def test_3
assert_equal 'III', 3.to_roman
end
def test_4
assert_equal 'IV', 4.to_roman
end
def test_5
assert_equal 'V', 5.to_roman
end
def test_6
assert_equal 'VI', 6.to_roman
end
def test_9
assert_equal 'IX', 9.to_roman
end
def test_27
assert_equal 'XXVII', 27.to_roman
end
def test_48
assert_equal 'XLVIII', 48.to_roman
end
def test_59
assert_equal 'LIX', 59.to_roman
end
def test_93
assert_equal 'XCIII', 93.to_roman
end
def test_141
assert_equal 'CXLI', 141.to_roman
end
def test_163
assert_equal 'CLXIII', 163.to_roman
end
def test_402
assert_equal 'CDII', 402.to_roman
end
def test_575
assert_equal 'DLXXV', 575.to_roman
end
def test_911
assert_equal 'CMXI', 911.to_roman
end
def test_1024
assert_equal 'MXXIV', 1024.to_roman
end
def test_3000
assert_equal 'MMM', 3000.to_roman
end
end
See how the specs fail in one case but not in the other. I thought these are meant to work in the same way.
This line is a problem...
ROMAN_NUMERALS[character.to_i * 10 ** index] << roman_numeral
It will return a string which is the value of the correct ROMAN_NUMERALS key plus roman_numeral, which is what you want, BUT it is also changing the value in the ROMAN_NUMERALS hash! The shovel operator << changes the string on the left of the operator (it's what we call a mutating operator).
So if you test for 1001 the unit 1 will return "I" (that's fine) then the zero will return an empty string BUT will change the value for zero into "I"... the second zero will return "I" (incorrect) and will change the value for zero into "II". The 1 in the thousands position will return "M" but then change the hash value into "MII".
When the line ROMAN_NUMERALS[character.to_i * 10 ** index] << roman_numeral is being executed you are replacing the value corresponding to the key character.to_i * 10 ** index with its value plus roman_numeral.
Now that your question has been answered, I would like to suggest an alternative method and also a different way to perform your tests. This requires Ruby v1.9+, so we can depend on the order of the hash keys.
Code
First, reverse the order of the hash elements.
RNR = Hash[ROMAN_NUMERALS.to_a.reverse]
#=> {3000=>"MMM", 2000=>"MM", 1000=>"M",..., 2=>"II", 1=>"I", 0=>""}
Then:
class Integer
def to_roman
num = self
roman = ""
while num > 0
i,r = RNR.find { |i,r| i <= num }
roman << r
num -= i
end
roman
end
end
Test objectives
We need to test a substantial number of integer values and make sure that we are testing each integer against the correct roman numeral equivalent. Both of these objectives can be met by creating a method that converts roman numerals to integers:
RNRI = RNR.invert
#=> {"MMM"=>3000, "MM"=>2000, "M"=>1000,..., "II"=>2, "I"=>1, ""=>0}
class String
def roman_to_integer
num = 0
roman = self
while roman.size > 0
r, i = RNRI.find { |r,m| roman =~ /^#{r}/ }
num += i
roman = roman[r.size..-1]
end
num
end
end
Examples
Now let's invoke both Integer#to_roman and String#roman_to_integer for various integer values:
def check_one(i)
roman = i.to_roman
puts "#{i}.to_roman = #{roman}, #{roman}.roman_to_integer = " +
#{roman.roman_to_integer}"
end
check_one(402) # 'CDII'
# 402.to_roman = CDII, CDII.roman_to_integer = 402
check_one(575) # 'DLXXV'
# 575.to_roman = DLXXV, DLXXV.roman_to_integer = 575
check_one(911) # 'CMXI'
# 911.to_roman = CMXI, CMXI.roman_to_integer = 911
check_one(1024) # 'MXXIV'
# 1024.to_roman = MXXIV, MXXIV.roman_to_integer = 1024
check_one(3000) # 'MMM'
# 3000.to_roman = MMM, MMM.roman_to_integer = 3000
Tests
So now in your testing you can use:
def test_all(n)
(1..n).each { |i| test_one(i) }
end
def test_one(i)
roman = i.to_roman
assert_equal(i, roman.roman_to_integer, "#{i}.to_roman=#{roman}, " +
"#{roman}.roman_to_integer = #{roman.roman_to_integer}")
end

Write a function to return "true" or "false" if passed "1"/"0" or "true"/"false"

I need a simple function to return "true" or "false" the argument passed to it is:
1 or 0, or true or false
I currently had something like this, so the answer, if possible, should be concise as per below:
def boolean(value); return value ? ( value == 1 ? "true" : "false) : nil; end
Thanks.
Some ideas:
def boolean(x)
%w{1 true}.include?(x).to_s
end
def boolean(x)
(x == '1' || x == 'true').to_s
end
There's also the wannabe bool gem:
require 'wannabe_bool'
'1'.to_b # => true
'0'.to_b # => false
'true'.to_b # => true
'false'.to_b # => false
You might want to have a look how Rails does this typecasting in its database connection adapter:
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set
# convert something to a boolean
def value_to_boolean(value)
if value.is_a?(String) && value.empty?
nil
else
TRUE_VALUES.include?(value)
end
end
See: docs for ActiveRecord::ConnectionAdapters::Column
I think this'll work, comments are welcome though:
def b(k); return k ? ( (k == "1" || k == "true") ? "true" : "false" ) : nil; end
puts b("1")
puts b("0")
puts b("true")
puts b("false")
Result:
true
false
true
false

Why are non-ASCII characters not equal?

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

Resources