Cassandra and creating an int column name from Ruby client - ruby-on-rails

I am attempting to create dynamic columns with a comparator/validator that is a 32 bit signed integer. This obviously will save on storage space amongst other advantages. Currently, this works great if I have a UTF8Type validator (Using Twitter's cassandra client for Ruby):
db.insert(:foo, 'mykey', {'mycol' => 'myval'})
This is where the problem occurs:
db.insert(:foo, 'mykey', {5 => 'myval'})
I think this is more of a Ruby issue than Cassandra issue. Using Rails console, I get the following thrown out at me:
TypeError: no implicit conversion of Fixnum into String
Further clarification, I can't simply do:
db.insert(:foo, 'mykey', {'5' => 'myval'})
This will trigger a validation fail which is expecting an integer for the column and not a string.
Is there a way to make this reasonably work in Ruby so that I don't have to use UTF8Type column names and can stick to int based ones for my Cassandra 1.2 based app?

The twitter Cassandra library leaves it to you the developer to serialize/deserialize all values. It requires everything that you give it to be in binary string representation. So if you want to use ints as your comparator you need to pack them before inserting and unpack them when fetching them out of Cassandra. Your insert needs to look like this:
db.insert(:foo, 'mykey', {[5].pack('N*') => 'myval'})

#MrYoshiji
Fixnum CAN be declared as key in Ruby Hashes.
Just use correct syntax. You're in Ruby, not Python !!!
irb(main):010:0> { 1 => 'bonjour', 2 => "okay" }
=> {1=>"bonjour", 2=>"okay"}
irb(main):012:0> { 1 => 'bonjour', 2 => "okay" }.keys.map(&:class)
=> [Fixnum, Fixnum]

Related

Active record querying with store_accesors

I have a database where I need to do a search on specific record that has a certain output. What is making this tricky for me is that these values are found in a 'store_accessor' and therefore they aren't always there.
For instance if I run Team.last.team_configuration, I get this value below, and what I need are only teams that have a specific setting.
<TeamConfiguration:0x00007123456987> {
:id => 8,
:owner_id => 6,
:team_type => "football",
:settings => {
"disable_coach_add" => false,
"delink_players_at_18" => true
},
:type => "TeamConfiguration"
}
My thoughts have been something around these lines, but i keep getting undefined method 'settings' for team_configuration:Symbol
Team.where(:team_configuration.settings['delink_players_at_18'])
Would anyone know what I am doing wrong in this instance? I think because there are two separations from the main source it has been causing me some issues. Thanks in advance!
The problem is way store_accesors works, look what documentation says:
Store gives you a thin wrapper around serialize for the purpose of
storing hashes in a single column. It's like a simple key/value store
baked into your record when you don't care about being able to query
that store outside the context of a single record.
https://api.rubyonrails.org/classes/ActiveRecord/Store.html
So a posible solution could be to search by that column, converting a previously hash of what you want to string.
Team.where(team_configuration: data.to_s)
If you're using a postgres database and the TeamConfiguration#settings column is serialized as jsonb column you can get at this with postgres json operators:
Team.joins(:team_configurations)
.where("team_configurations.settings #> '{\"delink_players_at_18\": true}'")

How to covert a string to a SHA512 hash

I am working on remote authentication for a rails 4 application. The password hash was written using a cold fusion hash library and I need to try and match what the end result in Rails to allow the user into the application.
I did see that the Digest library has something for coverting strings into SHA512 hexadecimal. But that doesn't seem to be what I need. An example snippet of a hash looks like: ü\rÀÚ힎
Is there a hashing library in Ruby that will allow me to hash a string in SHA512. Does such a thing exist or is there an external gem I could leverage?
Thanks in advance.
Sounds like you're looking for Digest::SHA2#digest.
[3] pry(main)> Digest::SHA2.new(512).digest("test")
=> "\xEE&\xB0\xDDJ\xF7\xE7I\xAA\x1A\x8E\xE3\xC1\n\xE9\x92?a\x89\x80w.G?\x88\x19\xA5\xD4\x94\x0E\r\xB2z\xC1\x85\xF8\xA0\xE1\xD5\xF8O\x88\xBC\x88\x7F\xD6{\x1472\xC3\x04\xCC_\xA9\xAD\x8EoW\xF5\x00(\xA8\xFF"
In contrast to the hexdigest function, which will return a formatted string:
[9] pry(main)> Digest::SHA2.new(512).hexdigest("test")
=> "ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"
See Digest Instance Methods.

In Rails, how can I take a GET string and parse it into an object?

I’m positive this is a dupe, but I couldn’t find the original.
Given a GET-style string like foo=bar&x[0]=baz, how can I decode this into a params-like array in a Rails app?
Updated to add: Note that CGI.parse seems to do much less than whatever magic Rails does:
1.9.3p194 :006 > CGI::parse 'foo=bar&x[foo][bar]=baz'
=> {"foo"=>["bar"], "x[foo][bar]"=>["baz"]}
CGI.parse didn’t unpack the nested objects into a mult-level hash. In Rails, at some level, this is actually examined.
For nested queries, Rails uses Racks' parameter parser Rack::Utils.parse_nested_query:
Rack::Utils.parse_nested_query 'foo=bar&x[foo][bar]=baz'
=> {"foo"=>"bar", "x"=>{"foo"=>{"bar"=>"baz"}}}

MongoMapper new records contain old record's data

In our Rails app environment (ruby 1.8.7 / rails 2.3.12) I can run the following code:
class MongoTester
include MongoMapper::Document
key :test_arr, Array, :default => []
end
mt = MongoTester.new
mt.test_arr << 24
mt2 = MongoTester.new
The output of mt2.inspect is:
#<MongoTester test_arr: [24], _id: BSON::ObjectId('4e5c089f3beaacad00000002')>
I'm not sure how this is possible. object_id and _id for both records are different. Neither one is saved. We haven't modified MongoMapper in our application (mongomapper 0.8.6). Yet a completely new record contains the data of a previously created different record.
I can't reproduce this in MongoMapper's test suite.
Any information on how this effect is possible or how I can get rid of it would be awesome. Thanks!
That is a bug: file it at https://github.com/jnunemaker/mongomapper/issues/new This bug is fixed in newer versions of MongoMapper
Here's a workaround:
key :test_arr, Array, :default => lambda { [] }
It's because arrays in Ruby are mutable, so your default array object is getting added to each time with <<. The object_id's of your docs will be different, but the object_id's of the arrays will be the same.

MongoMapper, increment and update other attributes at the same time?

How do I do the following in one operation:
Find or create object by some key:value pairs
Increment properties on the object.
I am doing this now:
Model.find_or_create_by_this_and_that(this, that).increment("a" => 1, "b" => 1)
What's the correct way to do that?
From javascript you should be able to do something like
db.model.update({"_id" : "xyz"}, {$inc : {"a":1,"b":1} })
It looks like the MongoMapper equivalent is
Model.collection.update({"_id" => self._id}, {"$inc" => {"a" => 1,"b" => 1}})
MongoMapper also seems to support an increment feature, but I'm unfamiliar with the syntax. In either case that second command looks very similar to the javascript version (and the php version), so that's probably what you're looking for.

Resources