How do you set a boolean value in Redis? - ruby

When I set a boolean value (true) to a key in Redis, the value is coerced to a string ("true"). With memcached, I get back what I put in. But with Redis it seems to stringify everything. I can't find any docs on how to fix this boolean issue. No special boolean_set methods or boolean options.
I'm using Ruby.
Example follows.
Set up:
require 'redis'
#redis = Redis.new
running in irb:
irb(main):034:0> bool = true
=> true
irb(main):035:0> bool
=> true
irb(main):036:0> #redis.set("example", bool)
=> "OK"
irb(main):037:0> #redis.get("example")
=> "true"
irb(main):038:0> #redis.get("example") == bool
=> false

"The Redis String type is the simplest type of value you can associate with a Redis key. It is the only data type in Memcached, so it is also very natural for newcomers to use it in Redis." - it's impossible to do in an "easy" way.
But regarding what for you need it, you can create some class to write/read of any type of data.
For example, how it's implementing in Rails ActiveRecord Cache
Some simple interpretation of this pretty big class with using of next Marshal's methods: dump and load
class RedisAnyTypesHandler
def initialize(redis)
#redis = redis
end
def write(key, value)
#redis.set(key, serialize(value))
end
def read(key)
deserialize(#redis.get(key))
end
private
def serialize(value)
Marshal.dump(value)
end
def deserialize(value)
Marshal.load(value)
end
end
Now you can play with any type of data:
> redis_handler = RedisAnyTypesHandler.new(#redis)
> bool = true
=> true
> redis_handler.write('example', bool)
=> "OK"
> redis_handler.read('example') == bool
=> true
> class Foo
> attr_accessor :foo
> end
=> nil
> foo = Foo.new
=> #<Foo:0x0000556dc19097f8>
> foo.foo = 2
=> 2
> redis_handler.write('example_2', foo)
=> "OK"
> redis_handler.read('example_2').foo
=> 2

Related

compose objects without initializing objects that are not in hash

I am trying to compose an object Transaction from objects TranFee and Rate.
class Transaction
attr_reader :tranfee, :rate
def initialize(hash)
#tranfee = PaymentType::TranFee.new(hash)
#rate = PaymentType::Rate.new(hash)
end
end
module PaymentType
def initialize(args = {}, regex)
args.each do |key,value|
if key =~ regex
instance_variable_set("##{key}", value) unless value.nil?
eigenclass = class << self; self; end
eigenclass.class_eval do
attr_reader key
end
end
end
end
class TranFee
include PaymentType
def initialize(args, regex = /\Atran.*/)
super(args, regex)
end
end
class Rate
include PaymentType
def initialize(args, regex = /\Arate.*/)
super(args, regex)
end
end
end
The rate and TranFee objects are created from a hash like the one below.
reg_debit = {"name" => "reg_debit", "rate_base" => 0.0005,
"tran_fee" => 0.21, "rate_basis_points" => 0.002, "tran_auth_fee" => 0.10}
I am initializing the objects based on regex because the hash will eventually contain more values and I want the program to adjust as more items/classes are added.
Additionally there will be some instances where there are no key's starting with "tran". Does anyone know how to make Transaction create only a Rate object if TranFee has no instance variables inside of it? (in otherwords, if the hash returns nothing when keys =~ /\Atran.*/)
an example would be when the hash looks like this reg_debit = {"name" => "reg_debit", "rate_base" => 0.0005, "rate_basis_points" => 0.002}, right now the output is
#<Transaction:0x007ff98c070548 #tranfee=#<PaymentType::TranFee:0x007ff98c070520>, #rate=#<PaymentType::Rate:0x007ff98c0704a8 #rate_base=0.0005, #rate_basis_points=0.002>>
So I am getting a TranFee object with nothing in it and I would like for that to drop off in this situation. not sure if there may be a better way to design this? I was trying to think of a way to use ostruct or struct, but I havnt been able to figure it out. thanks for any help here.
I believe your strategy is very problematic - creating attributes to a class from user input doesn't sound like a very good idea.
Furthermore, adding methods (like attr_reader) to every instances can have severe performance issues.
If all you want is a data structure to hold your data, keep using a Hash. If you want a structure you can query using a dot notation instead of bracket notation, you might want to consider a gem like hashie or hashr.
If you want some code to make the flat data-structure hierarchical, I can suggest something like this:
hierarchical_hash = hash.each_with_object({}) do |(k, v), h|
if k.match(/^([^_]+)_(.+)$/)
root_key = $1
child_key = $2
h[root_key] ||= {}
h[root_key][child_key] = v
else
h[k] = v
end
end
# => {
# => "name" => "reg_debit",
# => "rate" => {
# => "base" => 0.0005,
# => "basis_points" => 0.002
# => },
# => "tran" => {
# => "fee" => 0.21,
# => "auth_fee" => 0.1
# => }
# => }
Your question raises some interesting issues. I will try to explain how you can fix it, but, as #Uri mentions, there may be better ways to address your problem.
I've assumed #tranfee is to be set equal to the first value in the hash whose key begins with "tran" and that #rate is to be set equal to the first value in the hash whose key begins with "rate". If that interpretation is not correct, please let me know.
Note that I've put initialize in the PaymentType module in a class (Papa) and made TranFee and Rate subclasses. That's the only way you can use super within initialize in the subclasses of that class.
Code
class Transaction
attr_reader :tranfee, :rate
def initialize(hash={})
o = PaymentType::TranFee.new(hash)
#tranfee = o.instance_variable_get(o.instance_variables.first)
o = PaymentType::Rate.new(hash)
#rate = o.instance_variable_get(o.instance_variables.first)
end
end
.
module PaymentType
class Papa
def initialize(hash, prefix)
key, value = hash.find { |key,value| key.start_with?(prefix) && value }
(raise ArgumentError, "No key beginning with #{prefix}") unless key
instance_variable_set("##{key}", value)
self.class.singleton_class.class_eval { attr_reader key }
end
end
class TranFee < Papa
def initialize(hash)
super hash, "tran"
end
end
class Rate < Papa
def initialize(hash)
super hash, "rate"
end
end
end
I believe the method Object#singleton_class has been available since Ruby 1.9.3.
Example
reg_debit = {"name" => "reg_debit", "rate_base" => 0.0005, "tran_fee" => 0.21,
"rate_basis_points" => 0.002, "tran_auth_fee" => 0.10}
a = Transaction.new reg_debit
p Transaction.instance_methods(false) #=> [:tranfee, :rate]
p a.instance_variables #=> [:#tranfee, :#rate]
p a.tranfee #=> 0.21
p a.rate #=> 0.0005

Ruby - Setter methods for hash properties

I've been tooling around with Ruby by converting a pen and paper RPG to a script.
Right now I have a character's stats kept in a hash, which I would like to be able to set via public method. I got that working with:
class Character
attr_reader :str, :con, :dex, :wis, :int, :level, :mods, :stats
def initialize str, con, dex, wis, int, cha, level = 1
#stats = { :str => str, :con => con, :dex => dex, :wis => wis, :int => int, :cha => cha }
#mods = {}
#level = level
#stats.each_pair do |key, value|
#mods[key] = ((value / 2 ) -5).floor
end
end
def []=(index, value)
#stats[index] = value
end
end
This allows me to instantiate a new character, then update #stats by running newChar.stats[:str] = 12
However, I also seem to be able to modify the #mods using this method as well, which is undesirable. newChar.mods[:str] = 15 will successfully alter the #mods hash, which from my understanding should not be possible with the current setter method.
On a slightly separate note, the iterator I'm using to create my #mods hash seems clunky but I haven't found anything better to accomplish the task.
You did not even call your []= method in your example. This would be done like so:
newChar[:str] = 123
instead of
newChar.stats[:str] = 123
so to call newChar.stats[:str] = 123 you do not even need you method definition. The reason is that newChar.stats as well as newChar.mods will both return the actual hash which can then be altered.
One possible workaround is to freeze the #mods variable so it can't be altered any more:
def initialize str, con, dex, wis, int, cha, level = 1
# omitted ...
#stats.each_pair do |key, value|
#mods[key] = ((value / 2 ) -5).floor
end
#mods.freeze
end
This is a good solution if you never want to be able to change #mods again. Trying to set a value will result in an error:
newChar.mods[:con] = 123
# RuntimeError: can't modify frozen Hash
Inside your class, you can, however, overwrite #mods entirely.
To summarize, the full class would be:
class Character
attr_reader :str, :con, :dex, :wis, :int, :level, :mods, :stats
def initialize str, con, dex, wis, int, cha, level = 1
#stats = { :str => str, :con => con, :dex => dex, :wis => wis, :int => int, :cha => cha }
#mods = {}
#level = level
#stats.each_pair do |key, value|
#mods[key] = ((value / 2 ) -5).floor
end
#mods.freeze
end
end
If you need a public getter for a hash but you don't want the user to modify the hash –the instance-variable of your class–, you can do it with dup.
class MyClass
....
def my_hash
#my_hash.dup
end
end
Where the solution with freeze, as mentioned above, will freeze the hash even for your class, the .dup-solution will let you modify the hash from within your class but not from outside.

Convert string to keyword

We can easily convert a keyword into a string:
true.to_s
=> "true"
But how to convert a string into a keyword?
How many keywords do you have? What's your definition of a 'keyword'?
I would implement with a case-command. You may define a to_keyword method for String. My implementation detects true, false, nil (or NULL). The strings are detected, ignoring capitals (TRUE will also be true) Other strings will return a symbol (The string itself would be another reasonable result).
The example can be adapted for further 'keywords' or other results.
class String
#Return 'keyword'
#Detects:
#- true (independend of lower letters/capitals)
#- false (independend of lower letters/capitals)
#- nil/NULL (independend of lower letters/capitals)
def to_keyword
case self
when /\Atrue\Z/i; true
when /\Afalse\Z/i; false
when /\Anil\Z/i, /\ANULL\Z/; nil
else; self.to_sym #return symbol. Other posibility: self.
end
end
end
p 'true'.to_keyword #true
p 'TRUE'.to_keyword #true
p 'false'.to_keyword #false
p 'NULL'.to_keyword #nil (NULL is used in DB like nil)
p 'NULLc'.to_keyword #:NULLc not detected -> symbol
try this:
ruby-1.9.2-p136 :001 > true
=> true
ruby-1.9.2-p136 :002 > eval("true")
=> true
You could try yaml:
require "yaml"
p YAML.load('true')
p YAML.load('TRUE')
p YAML.load('false')
p YAML.load('nil')
p YAML.load('NULL') #nil
I like Knut's answers mostly. I don't think I would support "Null" and others though.
Here is this version which is a little more simple.
class String
def to_keyword
self == "true"
end
end
>> "true".to_keyword
=> true
>> "false".to_keyword
=> false
This problem is pretty straight forward though. In your tests you could simply
:correct => (true_string == "true")
Following your comment, you could do something like that :
true_string = "true"
:correct => !!true_string
# examples
!true_string #=> false
!!true_string #=> true
!!!true_string #=> false
...

Compare the Content, Not the Results, of Procs

Using Ruby 1.9.2
Problem
Compare the content, not the results, of two procs. I understand the results can't be tested because of the halting problem but that's OK; I don't want to test the results anyway.
For instance
proc {#x == "x"} == proc {#x == "x"} => false # doh!
That returns false because the objects inside the procs are not the same.
My clunky solution
I have a work around solution that kinda sorta does what I want but it doesn't really test that the proc is "equal" to what I put in it. In my specific case the format of my procs will always be boolean tests on instance variables like this:
{#x == "x" && #y != "y" || #z == String}
I wrote a method that builds classes dynamically and creates instance variables set to specified values:
def create_proc_tester(property_value_hash)
new_class = Class.new.new
new_class.class.class_eval do
define_method(:xql?) { |&block| instance_eval &block }
end
property_value_hash.each do |key, value|
new_class.instance_variable_set("##{key}", value)
end
new_class
end
Which could be used something like this:
class Foo
attr_accessor :block
end
foo = Foo.new
foo.block = proc {#x == "x" && #y != "y" || #z == String}
tester = create_proc_tester(:x => "x", :y => "y", :z => Fixnum)
puts "Test #1: #{tester.xql? &foo.block}"
tester = create_proc_tester(:x => "x", :y => "x", :z => String)
puts "Test #2: #{tester.xql? &foo.block}"
> Test #1: false
> Test #2: true
.
.
That's all great and wonderful but I want to know if there is a better, more meta, way to do this that actually tests the contents of the proc not just a work around that solves my specific problem; something that could be used to test any proc.
I was thinking there might be a way to use the Ruby parser to get something to compare but I have no idea how. I'm researching it now but thought I'd try to see if anyone here has done this before and knows how. That might be a dead-end though because of the dynamic nature of Ruby but that's where I'm looking now.
If you're using Ruby 1.9, you may be able to use the sourcify gem.
$ irb
> require 'sourcify'
=> true
> a = proc {#x == "x"}
=> #<Proc:0x9ba4240#(irb):2>
> b = proc {#x == %{x}}
=> #<Proc:0x9ba23f0#(irb):3>
> a == b
=> false
> a.to_source == b.to_source
=> true
> RUBY_VERSION
=> "1.9.2"
We also ran into the ParseTree/Ruby 1.9 incompatibility problem at my company.
$ sudo gem install ruby2ruby ParseTree
require 'parse_tree'
require 'ruby2ruby'
require 'parse_tree_extensions'
# All of these are the same:
proc { puts 'a' }.to_ruby # => "proc { puts(\"a\") }"
lambda { puts "a" }.to_ruby # => "proc { puts(\"a\") }"
Proc.new { puts %{a} }.to_ruby # => "proc { puts(\"a\") }"
# If you need to do this with classes:
class Bar; define_method(:foo) { 'a' }; end
puts Ruby2Ruby.new.process(Unifier.new.process(ParseTree.translate(Bar)))
# will print this:
# class Bar < Object
# def foo
# "a"
# end
# end

Ruby: How do we identify whether an object o has a class C as its ancestor in the class hierarchy?

In Ruby, is it possible to identify whether an object o has a class C as its ancestor in the class hierarchy using any method?
I've given an example below where I use a hypothetical method has_super_class? to accomplish it. How should I do this in reality?
o = Array.new
o[0] = 0.5
o[1] = 1
o[2] = "This is good"
o[3] = Hash.new
o.each do |value|
if (value.has_super_class? Numeric)
puts "Number"
elsif (value.has_super_class? String)
puts "String"
else
puts "Useless"
end
end
Expected Output:
Number
Number
String
Useless
Try obj.kind_of?(Klassname):
1.kind_of?(Fixnum) => true
1.kind_of?(Numeric) => true
....
1.kind_of?(Kernel) => true
The kind_of? method has also an identical alternative is_a?.
If you want to check only whether an object is (direct) instance of a class, use obj.instance_of?:
1.instance_of?(Fixnum) => true
1.instance_of?(Numeric) => false
....
1.instance_of?(Kernel) => false
You can also list all ancestors of an object by calling the ancestors method on its class. For instance 1.class.ancestors gives you [Fixnum, Integer, Precision, Numeric, Comparable, Object, PP::ObjectMixin, Kernel].
Just use .is_a?
o = [0.5, 1, "This is good", {}]
o.each do |value|
if (value.is_a? Numeric)
puts "Number"
elsif (value.is_a? String)
puts "String"
else
puts "Useless"
end
end
# =>
Number
Number
String
Useless
o.class.ancestors
using that list, we can implement has_super_class? like this (as singletone method):
def o.has_super_class?(sc)
self.class.ancestors.include? sc
end
The rad way:
1.class.ancestors => [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
1.class <= Fixnum => true
1.class <= Numeric => true
1.class >= Numeric => false
1.class <= Array => nil
If you want to be fancy with it, you could do something like this:
is_a = Proc.new do |obj, ancestor|
a = {
-1 => "#{ancestor.name} is an ancestor of #{obj}",
0 => "#{obj} is a #{ancestor.name}",
nil => "#{obj} is not a #{ancestor.name}",
}
a[obj.class<=>ancestor]
end
is_a.call(1, Numeric) => "Numeric is an ancestor of 1"
is_a.call(1, Array) => "1 is not a Array"
is_a.call(1, Fixnum) => "1 is a Fixnum"

Resources