nateware / redis-objects Goto Github PK
View Code? Open in Web Editor NEWMap Redis types directly to Ruby objects
License: Artistic License 2.0
Map Redis types directly to Ruby objects
License: Artistic License 2.0
expiration seems not working with value
what I need is to expire the value after 10 seconds but its not working
here is the code I am using
class User < ActiveRecord::Base
include Redis::Objects
value :online_status , :expiration => 10
end
With these models:
class Post < ActiveRecord::Base
has_many :post_images, :dependent => :destroy
end
class PostImage < ActiveRecord::Base
belongs_to :post, :counter_cache => true
end
Whenever you try to delete an instance of PostImage or delete any Post with PostImages, there is an exception:
ruby-1.8.7-p174 > p.destroy
Redis::Objects::UndefinedCounter: Undefined counter :post_images_count for class Post
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/redis-objects-0.4.1/lib/redis/objects/counters.rb:84:in `verify_counter_defined!'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/redis-objects-0.4.1/lib/redis/objects/counters.rb:67:in `decrement_counter'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/associations.rb:1368:in `belongs_to_counter_cache_before_destroy_for_post'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:178:in `send'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:178:in `evaluate_method'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:166:in `call'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:93:in `run'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:92:in `each'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:92:in `send'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:92:in `run'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:276:in `run_callbacks'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/callbacks.rb:344:in `callback'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/callbacks.rb:336:in `destroy_without_transactions'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/transactions.rb:229:in `send'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/transactions.rb:229:in `with_transaction_returning_status'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction_without_callback'
... 17 levels...
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:166:in `call'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:93:in `run'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:92:in `each'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:92:in `send'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:92:in `run'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activesupport-2.3.5/lib/active_support/callbacks.rb:276:in `run_callbacks'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/callbacks.rb:344:in `callback'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/callbacks.rb:336:in `destroy_without_transactions'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/transactions.rb:229:in `send'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/transactions.rb:229:in `with_transaction_returning_status'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction_without_callback'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/after_commit-1.0.8/lib/after_commit/connection_adapters.rb:12:in `transaction'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/transactions.rb:182:in `transaction'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/transactions.rb:228:in `with_transaction_returning_status'
from /home/insignia/.rvm/gems/ruby-1.8.7-p174@GSkrrb/gems/activerecord-2.3.5/lib/active_record/transactions.rb:192:in `destroy'
from (irb):54ruby-1.8.7-p174
We're using ruby 1.8.7-p174 and rails 2.3.5
When both Redis::Objects and Cache Money (https://github.com/nkallen/cache-money) are included, I get an error with the set
method. For my purposes, I've changed set
to redis_set
, but not sure it's the best solution as it seems a bit messy. I don't use set with Redis::Objects, so this doesn't bother me, but others may find it a nuisance
ArgumentError: wrong number of arguments (3 for 2) from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/index.rb:6:in `set' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/index.rb:6:in `__send__' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/index.rb:6:in `set' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/index.rb:110:in `add_object_to_primary_key_cache' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/index.rb:163:in `update_index_with_minimal_network_operations' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/index.rb:31:in `update' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/write_through.rb:60:in `update_caches' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/write_through.rb:60:in `each' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/write_through.rb:60:in `update_caches' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/write_through.rb:48:in `send' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/write_through.rb:48:in `unfold' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/write_through.rb:26:in `update_caches' from /projects/apps/bv/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `send' from /projects/apps/bv/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `evaluate_method' from /projects/apps/bv/vendor/rails/activesupport/lib/active_support/callbacks.rb:166:in `call' from /projects/apps/bv/vendor/rails/activesupport/lib/active_support/callbacks.rb:93:in `run' ... 11 levels... from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `send' from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/transactions.rb:229:in `with_transaction_returning_status' from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction' from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/transactions.rb:182:in `transaction_without_trace_ActiveRecord_self_name_transaction' from /projects/apps/bv/vendor/gems/newrelic_rpm-2.13.4/lib/new_relic/agent/method_tracer.rb:319:in `transaction_without_cache_transaction' from /projects/apps/bv/vendor/gems/newrelic_rpm-2.13.4/lib/new_relic/agent/method_tracer.rb:141:in `trace_execution_scoped' from /projects/apps/bv/vendor/gems/newrelic_rpm-2.13.4/lib/new_relic/agent/method_tracer.rb:314:in `transaction_without_cache_transaction' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cache_money.rb:56:in `transaction' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cash/transactional.rb:13:in `transaction' from /projects/apps/bv/vendor/gems/cache-money-0.2.10/lib/cache_money.rb:56:in `transaction' from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/transactions.rb:228:in `with_transaction_returning_status' from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save' from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/transactions.rb:208:in `rollback_active_record_state!' from /projects/apps/bv/vendor/rails/activerecord/lib/active_record/transactions.rb:196:in `save' from /projects/apps/bv/app/models/device.rb:84:in `reset_rate_limit!'
Hey there, I'm working on trying to use #pipelined
with redis-objects and I'm running into undefined method
to_i' for <Redis::Future [:incrby, "post:1004:view_count", 1]>:Redis::Future`.
This is from increment immediately turning the value/reply into an integer. I'm trying
def value_or_future(returned)
if returned.is_a?(Future)
returned.value
else
returned
end
end
but it isn't quite working. Am I missing something? Have any suggestions?
Thank you!
Given a class named ModuleName::ClassName in Rails, When a redis datatype is added as an attribute then the redis key should include the ModuleName.
Example:
module_name:class_name:id:attribute
in ruby program:
Redis.current = Redis.new(:host => 'localhost', :port => 6379)
@value = Redis::Value.new('test_key',:expiration => 15,:marshal => true)
@value.value = "test expire is work!"
execute the code above and i go to the shell via ./redis-cli
type:
redis> TTL test_key
(integer) -1
I expect the result is not -1. Can u plz tell me how to set expire time when the key type is 'list' or 'value' in redis-objects?
thx very much!
I have the following code in my after_create block in an ActiveRecord model named 'Message'
user.new_messages.increment
push_message['new_messages'] = user.new_messages
Resque.enqueue(MessagePusher, push_message)
The above lines of code simply blocks the thread and never returns.
My web server is nginx + unicorn on RedHat Linux.
If I comment out the first two lines of code, then resque does the queuing of the object albeit without the new_messages counter value.
I tried using the same redis connection as resque for redis-objects as also independent connections. No luck.
I've been reading the code and specs. It looks like expire is in the core methods but I can't seem to get it working within an ActiveRecord model.
class Bucket < ActiveRecord::Base
set :top_three_product_ids, expire: 25.seconds
end
bucket = Bucket.first
bucket.top_three_product_ids << Product.first.id
bucket.top_three_product_ids.members
>> ["1"]
bucket.top_three_product_ids.ttl
>> -1
It is shown in the documentation that the initialization can be done by this:
Redis::Objects.redis = Redis.new(:host => '127.0.0.1', :port => 6379)
However, it is not working. Actually, it should be like this:
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
Is this a documentation error? Or am I getting something wrong?
I would like to use a uid
instead of id
to generate the keys for Redis::Objects. As far as I can tell, the only way I could do that right now would be to alias id to uid in my ActiveRecord model, which obviously would break everything.
I was thinking it would be nice to have a way to customize the id field, like so:
class User
include Redis::Objects
redis_id_field :uid
counter :login_attempts # => user:#{uid}:login_attempts
end
What do you think?
It would be great to have the possibility to use :aggregate and :weight options with interstore and unionstore commands.
Hey! Really nice and useful gem here.
What I found is not actually a bug but I got stuck with this for a while, so here it comes.
I'm expanding a marshal serialization using Redis::List with the :marshal => true
flag set, and I got a weird behavior: on some of my apps the objects were loaded correctly and in others I got just the raw string from the serialization.
After some debugging, I realized that Redis::List was rescuing the failed load attempt and falling back to the string serialization: while this behavior is reasonable, it can be quite confusing to debug.
It would be nice to have Redis::Object raising a custom Exception upon failure to load the marshal serialization.
Good luck
When using Redis::Objects' very handy model attributes, the redis keys are not cleaned up upon model deletion.
I propose to add a cleanup method which will check Redis::Objects.redis
for any keys belonging to the current object and delete any found.
This can then be added as a before_delete hook to active record or similar hooks for other ORMs, keeping it flexible. If this is welcome I will start out by adding failing tests to displaying the current behavior and then implementing my solution as suggested above.
I would love your thoughts Nate.
When using redis-rb 3.0.0+, when commands such as SortedSet#increment and decrement I get
NoMethodError: undefined method
to_i' for #Redis::Future:0x007fdc94ceaa18`
because the sorted set implementation calls to_i on the returned value, which is a Future object if the call is performed inside a multi/pipelined block. This might be the case for other commands.
The solution might be to check if the returned object responds to #to_i, or check for the class of the object, but that's really ugly. In any rate specs need to be added to verify that all commands behave properly when inside these blocks.
expire is there, but ttl is missing. I've included it in the BaseObject for now.
class Redis::BaseObject
def ttl
@redis.ttl(@key).seconds
end
end
I'd like to have a Redis list that keeps the size of the list bounded. For example, I'd like to store the last 25 operations that someone did, and when the list grows to 25, start throwing out old values.
The LTRIM command seems perfect for this: http://code.google.com/p/redis/wiki/LtrimCommand
What I was thinking was that Redis::List could take a :max_size
option. If that option is set, then the push command will also issue an LTRIM. Quick code example:
def push(value)
redis.rpush(key, to_redis(value))
redis.ltrim(key, 0, options[:max_size]) if options[:max_size] and options[:max_size] > 0
end
Do you think this is a valid feature to add? If so, I'll make a branch and code it up w/ tests.
hi,
I'm on ActiveRecord 3.0.3
The short version is redis-objects breaks when used in a class with a counter_cache because it's versions of increment_counter and decrement_counter override the versions from ActiveRecord. It only happens in classes that mix Redis::Objects in.
Hey, just thought you should know. I tried using the ^ operation between two sorted-sets and it turns out that redis didn't (and doesn't plan to) support sorted-set difference operations.
Cheers,
Dan
Dears,
i was asking if i'd like to expire the Redis model object when the user Signout.
also how can i expire or clear some fields in some actions.
Thanks,
Shenouda Bertel
Like in the title. SortedSet#range and #revrange are grouping elements, so it's a bit inconsistent. SortedSet#revrangebyscore is not grouping elements as well, but it's not implemented by Redis yet, so it's not an issue for now
The docs claim that increment/decrement blocks are atomic, but as far as I can see this is not the case. Let me give a specific example:
Let's say I have a counter called total, which starts at 0. Somewhere in my model, I use the counter like so:
@object.total.increment(incr_by) do |val|
if val <= 5
# this is valid, so continue on with creation
else
nil # invalid, so rewind and reject
end
end
Now imagine we have two processes on separate machines running this code concurrently. Machine1 has incr_by set to 6 and Machine2 has incr_by set to 3. The expected behavior is that Machine2 will be valid since 0 + 3 <= 5 and Machine1 will be invalid since 0 + 6 > 5.
However, issues arise when incrementing the redis key. Imagine that Machine1 reaches line 54 of counter.rb and increments the redis value to 6. Next, BEFORE the rewind block is evaluated by Machine1, Machine2 reaches the same line and also increments the redis value. Now, Machine2 which is expected to have a valid value evaluates its rewind_block with a value of 6 + 3 = 9, thus resulting in the rewind of the value. Now instead of meeting the expected behavior, both changes are rejected.
I'm I missing something, or is this indeed a possibility?
In Rails, using Phusion Passenger or Unicorn, you fork your Rails process to spawn new workers. This will leave you in a state where you have multiple processes sharing a redis client, with disastrous results. The solution, the, is to reset your Redis client after forking. See, for example: http://www.modrails.com/documentation/Users%20guide%20Apache.html#_smart_spawning_gotcha_1_unintentional_file_descriptor_sharing
Although redis-objects lets you reset the redis client used for creating new objects, as far as I can tell, BaseObject does not provide any means for resetting the @redis attribute once it has been created. This means that if I have a class Foo, with counter :bar, the redis client used when I call foo.bar.value will always be the same even if I fork the process. So any redis objects that are added to classes cannot have their redis clients reset.
Am I correct about this or am I overlooking something? If so, do you have any guidance for what we should do?
ruby-1.9.1-p243 > lb = Redis::SortedSet.new('rank:overall:by_points')
=> #<Redis::SortedSet:0x000001010f20d0 @key="rank:overall:by_points", @options={}, @redis=#<Redis::Client:0x000001011f3e38 @host="127.0.0.1", @port=6379, @db=0, @timeout=5, @password=nil, @logger=nil, @thread_safe=true, @binary_keys=nil, @mutex=#<Mutex:0x000001011f3e00>, @sock=nil, @pubsub=false>>
ruby-1.9.1-p243 > lb.size
=> 10000
ruby-1.9.1-p243 > lb[0..10]
=> ["player_724", "player_2410", "player_8094", "player_9524", "player_4071", "player_5370", "player_2144", "player_383", "player_4300", "player_3758", "player_4391"]
ruby-1.9.1-p243 > players = %W{Matt James Pete Nate Luisa Manu Josh}
=> ["Matt", "James", "Pete", "Nate", "Luisa", "Manu", "Josh"]
ruby-1.9.1-p243 > lb.rank('Pete')
RuntimeError: -ERR unknown command 'zrank'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:539:in `format_error_reply'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:529:in `format_reply'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:474:in `read_reply'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:444:in `block in process_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:442:in `map'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:442:in `process_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:431:in `block in raw_call_command'
from <internal:prelude>:8:in `synchronize'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:450:in `maybe_lock'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:428:in `raw_call_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:332:in `call_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:381:in `method_missing'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-objects-0.2.4/lib/redis/sorted_set.rb:61:in `rank'
from (irb):11
from /Users/mattetti/.rvm/ruby-1.9.1-p243/bin/irb:15:in `<main>'
I have a rails app that already has $redis defined and I want to use Redis::HashKey in several places. However in each of these places it ends up not being DRY:
# config/initializers/redis.rb
$redis_objects = Redis::Namespace.new 'objects'
# in multiple places
Redis::HashKey.new(name, $redis_objects)
Would you take a patch that let's me set a redis handle once for Redis::BaseObject?:
# config/initializers/redis.rb
Redis::BaseObject.redis = Redis::Namespace.new 'objects'
# or
Redis::Objects.redis = Redis::Namespace.new 'objects'
# in multiple places
Redis::HashKey.new name
If you support this behavior for Redis::Objects, why not for Redis::BaseObject?
Hi,
Running the following in JRuby 1.7.2:
require 'redis'
require 'redis/objects'
class RedisObjectTest
include Redis::Objects
value :id
value :name
end
Redis.current = Redis.new
a = RedisObjectTest.new
a.id = 5
results in
Error: Your application used more stack memory than the safety cap of 2048K.
Specify -J-Xss####k to increase it (#### = cap size in KB).
Specify -w for full StackOverflowError stack trace
Any ideas as to what's going on?
Can you please add SPOP? Thanks
http://redis.io/commands/spop
When using the gem, I found myself wanting to add hooks to do something before/after/around what happens when you get/set a Redis object. I was hoping to be able to do something like this (probably not the most practical use case, but I think you'll get my point):
class Team
include Redis::Objects
value :at_bat
def at_bat
super.value || 'between innings'
end
def at_bat=(name)
player = super
announce(name)
player
end
end
As it is now, this isn't possible because the methods are defined directly on the class rather than including a module. If you like my idea, I'll give it a shot and send you a pull request.
The documentation reads:
@sorted_set['Newbie'] = 1
When testing here is what I get:
ruby-1.9.1-p243 > lb = Redis::SortedSet.new('rank:overall:by_points')
#<Redis::SortedSet:0x000001010f20d0 @key="rank:overall:by_points", @options={}, @redis=#<Redis::Client:0x000001011f3e38 @host="127.0.0.1", @PORT=6379, @db=0, @timeout=5, @password=nil, @logger=nil, @thread_safe=true, @binary_keys=nil, @mutex=#Mutex:0x000001011f3e00, @sock=nil, @PubSub=false>>
lb['pete']
RuntimeError: -ERR unknown command 'Pete'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:539:in `format_error_reply'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:529:in `format_reply'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:474:in `read_reply'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:444:in `block in process_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:442:in `map'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:442:in `process_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:431:in `block in raw_call_command'
from <internal:prelude>:8:in `synchronize'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:450:in `maybe_lock'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:428:in `raw_call_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:332:in `call_command'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-1.0.4/lib/redis/client.rb:381:in `method_missing'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-objects-0.2.4/lib/redis/sorted_set.rb:85:in `range'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-objects-0.2.4/lib/redis/sorted_set.rb:248:in `at'
from /Users/mattetti/.rvm/gems/ruby/1.9.1/gems/redis-objects-0.2.4/lib/redis/sorted_set.rb:45:in `[]'
from (irb):12
here's an example:
u.messages_count.value
=> 0
u.messages_count.decrement(5) { |v| v < 0 ? nil : v }
=> nil
u.messages_count.value
=> -4 # should be 0
final messages_count.value should be 0, but rewindable block doesn't know about the "by" argument, so it ends up decrementing by 5 and then incrementing by 1
In sorted_set.rb, this line is not needed:
group_set_with_scores(val)
in:
# Return a range of values from +start_index+ to +end_index+ in reverse order. Redis: ZREVRANGE
def revrange(start_index, end_index, options={})
if options[:withscores] || options[:with_scores]
val = from_redis redis.zrevrange(key, start_index, end_index, :with_scores => true)
group_set_with_scores(val)
else
from_redis redis.zrevrange(key, start_index, end_index)
end
end
I believe we might need more changes for this kind of things.
Thanks for taking care of it.
add:
config.gem "redis-objects"
in environment.rb
Get error when run ruby script/server :
no such file to load -- redis-objects
... ...
env:
ruby:1.8.7
rails:2.3.5
Dear,
is also couchdb model supported by Redis_Object, and is Redis_object in model is based on the model itself or a global based.
using ruby 1.9.2
chron_clicks = Redis::HashKey.new('chronological_clicks')
chron_click[Time.now.to_i] = amodel.id
works well in dev env
in production env I get an error RuntimeError: -ERR unknown command 'hset'
also if I try cron_click.all I get RuntimeError: -ERR unknown command 'hgetall'
The issue is present on Ubuntu 10.04, redis-server 2:1.2.0-1
and It's working well on redis-server 2:2.0.1-2
When including Redis::Objects
in a parent class, I would expect the redis-object class methods to be available in subclasses.
class Animal
include Redis::Objects
end
class Dog < Animal
value :legs, global: true
end
This fails in 1.9.3 with the following:
.../ruby-1.9.3-p125/gems/redis-objects-0.6.1/lib/redis/objects/values.rb:17:in `value': undefined method `[]=' for nil:NilClass (NoMethodError)
from subclasses.rb:18:in `<class:Dog>'
from subclasses.rb:17:in `<main>'
I presume this originates from the use of @redis_objects
as a class instance variable which will not be inherited without explicit or lazy initialization in subclasses.
Is this expected behavior?
This is as it should be. I'm preparing a patch to fix specs now.
When using marshal, I sometimes receive this error: Encoding::CompatibilityError (incompatible character encodings: UTF-8 and ASCII-8BIT).
Here's the same issue on redis-store: redis/redis-rb#128
How it got fixed: shingara/redis-store@113d6e6
I could prepare a pull request if you are interested.
I'll wait for your feedback.
Thanks
Seems like there would be some advantages in allowing for persistent locking/lock checking when no block is passed to #lock. Goal would be to support something like the following use case:
def edit
@object = SomeObject.find(params[:id])
lock = @object.lock
if lock
@object.update_attribute(:locked_by, current_user)
else
redirect_to(object_url(@object))
flash[:error] = "Object is currently unavailable for editing blah blah blah"
end
end
def update
@object = SomeObject.find(params[:id])
if @object.locked_by == current_user
params[:object][:locked_by] = nil
@object.update_attributes(params[:object])
@object.unlock
flash[:message] = "Object updated."
end
redirect_to(object_url(@object))
end
Hello! I'm trying to use this gem inside my rails app i'm creating.
I need to store data for just one model in redis store and keep the rest on the rails postgres database.
Following the instructions i tried to setup my config/initializer/redis.rb this way
Redis.current = Redis.new(:host => '127.0.0.1', :port => 6379)
and setup my "Notification" model like this, removing the corresponding table from my db
class Notification < ActiveRecord::Base
include Redis::Objects
value :alert
value :app_id
value :badge
value :hash_data
value :language
value :locale
value :token
value :kind
KINDS = %w[list locale language broadcast]
belongs_to :app
validates_presence_of :app, :message => 'need to specify a valid app'
validates :kind,
:presence => true,
:inclusion => {
:in => KINDS,
:message => 'Missing / Invalid notification type'
}
If I try to create a new notification it seems to look for the postgres/sqlite instead of redis
n = Notification.new
ActiveRecord::StatementInvalid: Could not find table 'notifications'
what's wrong? ๐
Hi,
On HashKey objects, there is a clear
method to delete the key, but there is none for the Set object.
Is it intentional or not ?
Jeremy
When I run bacon spec/*_spec.rb
, I get:
Bacon::Error: [["a", 0.0]].==([["a", 3], ["c", 4]]) failed
./spec/redis_objects_instance_spec.rb:489: Redis::SortedSet - should handle sets of simple values
./spec/redis_objects_instance_spec.rb:474
./spec/redis_objects_instance_spec.rb:462
Bacon::Error: nil.==([]) failed
./spec/redis_objects_model_spec.rb:84: Redis::Objects - should support custom key names
./spec/redis_objects_model_spec.rb:76
./spec/redis_objects_model_spec.rb:36
42 specifications (552 requirements), 2 failures, 0 errors
However, when I run rake test
, I get different output (and still a failure):
Bacon::Error: [["a", 0.0]].==([["a", 3], ["c", 4]]) failed
/Users/dbalatero/oss/redis-objects/spec/redis_objects_instance_spec.rb:489: Redis::SortedSet - should handle sets of simple values
/Users/dbalatero/oss/redis-objects/spec/redis_objects_instance_spec.rb:474
/Users/dbalatero/oss/redis-objects/spec/redis_objects_instance_spec.rb:462
19 specifications (223 requirements), 1 failures, 0 errors
I'm concerned about the output discrepancy (and the failures). Can you maybe check this out and see if it's valid?
My info:
dbalatero@lando /oss/redis-objects (master) % uname -a1/RELEASE_X86_64 x86_64 i386 MacBookPro5,5 Darwin
Darwin lando.local 10.4.0 Darwin Kernel Version 10.4.0: Fri Apr 23 18:27:12 PDT 2010; root:xnu-1504.7.4
dbalatero@lando ~/oss/redis-objects (master) % ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10.2.0]
Redis v1.2.2.
I'm thinking I'm likely just missing it in the docs, but I can't find any info on a public method for doing the following on an object with redis-objects included to delete all the fields stored for it.. looks like all the delete methods are defined on the BaseObject child classes.
def destroy
self.class.redis_objects.keys.map do |r|
redis.del(send(r).key)
end
end
Hey,
Something is wrong with the way modules are loaded or with the documentation :)
When I try to use it in plain IRB:
ree-1.8.7-2010.02 > require 'redis'
=> true
ree-1.8.7-2010.02 > require 'redis/objects'
=> true
ree-1.8.7-2010.02 > Redis::Set
NameError: uninitialized constant Redis::Set
from (irb):3
ree-1.8.7-2010.02 > Redis::Objects::Sets
=> Redis::Objects::Sets
ree-1.8.7-2010.02 > Redis::Set
=> Redis::Set
According to docs I should be able to access Redis::Set without loading Redis::Objects::Sets first.
It's even more tricky in Rails app:
ree-1.8.7-2010.02 > require 'redis/objects'
=> []
ree-1.8.7-2010.02 > Redis::Set
(irb):2: warning: toplevel constant Set referenced by Redis::Set
=> Set
ree-1.8.7-2010.02 > Redis::Objects::Sets
=> Redis::Objects::Sets
ree-1.8.7-2010.02 > Redis::Set
=> Redis::Set
I'm using REE 1.8.7 on OS X.
I realize its possible to initialize redis attributes using simple defaults, but right now I can't do something like this
Post < ActiveRecord::Base
include Redis::Objects
value :redis_comment_count, :default => comments.count
end
Would be exceedingly cool if this and/or passing in blocks to initialize values were allowed
So I am using redis Objects locally just fine. I have a counter on a model, like this:
class Performance < ActiveRecord::Base
include Redis::Objects
counter :tickets_sold, start: 0
end
Accessing this value from Heroku console is working great as well.
irb(main):002:0> Performance.last.tickets_sold.value
Performance Load (3.9ms) SELECT `performances`.* FROM `performances` ORDER BY `performances`.`id` DESC LIMIT 1
=> 0
I confirm that Redis.current is present:
irb(main):003:0> Redis.current
=> # Redis client v2.2.2 connected to redis://ray.redistogo.com:9023/0 (Redis v2.4.11)
However, accessing the same counter from a template on the website runs into a Errno::ECONNREFUSED error.
Connection refused - Unable to connect to Redis on 127.0.0.1:6379
Why is it trying to connect to the local Redis url? I don't know. Considering that this is working just fine on the console, I'm a little puzzled. I hope someone has an idea of what's going on here.
I updated to HEAD, and all tests in redis_objects_model_spec are failing. The first failures were failing on the total_players_online counter, which was fixed when I pulled in the counter_fix branch. However, it's now failing on the all_player_stats list, and looking at the code, I'm not sure why it wouldn't be failing for you as well.
The problem is the list is defined twice -- and the second time it's defined (custom keys), it is not made global. So, the all_player_stats.clear in the test setup fails because there is no saved Roster objects.
I'm not sure what the intention is -- is the redefined list supposed to merge the options?
Line 17 in lib/redis/objects/lists.rb shows the options hash for that list gets overwritten, not merged:
@redis_objects[name.to_sym] = options.merge(:type => :list)
So that this check in objects.rb fails, because the list is no longer global:
if id.nil? and !klass.redis_objects[name.to_sym][:global]
raise NilObjectId,
"Attempt to address redis-object :#{name} on class #{klass.name} with nil id (unsaved record?) [object_id=#{object_id}]"
end
Or should the test be using two separate lists?
The documentation implies that if I set Redis::Objects.redis
, I'm setting a global handle.
However, this fails:
Redis::Objects.redis = Redis.new(:host => 127.0.0.1, :port => 6379)
value = Redis::Value.new('mykey', :marshal => true)
value.value = 65
With:
NoMethodError: undefined method `set' for nil:NilClass
Inspecting the object:
#<Redis::Value:0x2ae30d68cf48 @redis=nil, @options={:marshal=>true}, @key="mykey">
Likely, it's trying to call @redis.set, which of course is nil
.
I have a fix, coming asap.
Got that when tried to create SortedSet object:
sorted = Redis::SortedSet.new "votes"
sorted["neg"] = 0
sorted["pos"] = 0
sorted.incr("pos") # 1
sorted.incr("pos") # 2
sorted.incr("neg") # 1
sorted.decr("neg") # 2
NoMethodError: undefined method -@' for "neg":String from /Users/someone/.rvm/gems/ruby-1.8.7-p334/gems/redis-objects-0.5.1/lib/redis/sorted_set.rb:172:in
decrement'
in sorted_set.rb line 172:
redis.zincrby(key, -by).to_i
but maybe you mean to:
redis.decrby(key, by).to_i
SortedSet is lacking a member? method. According to the docs, SortedSet#score should return nil if the key is not a member of the set, so I considered using that, but it actually returns 0.0 in this case.
Here's the implementation if you would like to include it:
class Redis::SortedSet
# Return a boolean indicating whether +value+ is a member.
def member?(value)
!redis.zscore(key, to_redis(value)).nil?
end
end
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.