Coder Social home page Coder Social logo

nest's Introduction

Nest

Object Oriented Keys for Redis.

Description

If you are familiar with databases like Redis and libraries like Ohm you already know how important it is to craft the keys that will hold the data.

>> redis = Redic.new
>> redis.call("HSET", "Event:3", "name", "Redis Meetup")
>> redis.call("HGET", "Event:3", "name")
=> ["Redis Meetup"]

It is a design pattern in key-value databases to use the key to simulate structure, and you can read more about this in the case study for a Twitter clone.

Nest helps you generate those keys by providing chainable namespaces that are already connected to Redis:

>> event = Nest.new("Event")
>> event[3].call("HSET", "name", "Redis Meetup")
>> event[3].call("HGET", "name")
=> ["Redis Meetup"]

Alternatively, you can send the Redis commands as messages to Nest, and if the method definition is missing it will forward the command to Redis:

>> event = Nest.new("Event")
>> event[3].hset("name", "Redis Meetup")
>> event[3].hget("name")
=> ["Redis Meetup"]

Usage

To create a new namespace:

>> ns = Nest.new("foo")
=> "foo"

>> ns["bar"]
=> "foo:bar"

>> ns["bar"]["baz"]["qux"]
=> "foo:bar:baz:qux"

And you can use any object as a key, not only strings:

>> ns[:bar][42]
=> "foo:bar:42"

In a more realistic tone, lets assume you are working with Redis and dealing with events:

>> event = Nest.new("Event")
=> "Event"

>> id = event[:id].incr
=> 1

>> event[id].hset("name", "Redis Meetup")
=> 1

>> meetup = event[id]
=> "Event:1"

>> meetup.hget("name")
=> ["Redis Meetup"]

API

call: Receives a Redis command and its arguments, and returns the reply from the Redis server. If the reply from Redis is an error, an instance of RuntimeError is returned.

call!: Similar to call, but instead of returning an instance of RuntimeError when the command fails, the error is raised.

queue: Receives the same kind of arguments as call, but enqueues the command in a transaction.

commit: Commits the transaction and returns the reply from Redis.

Any call to a missing method will result in Nest converting the method name to a Redis command and applying the arguments in an invocation to call.

For example:

ns = Nest.new("foo")
ns.append("hello,")
ns.append(" world")
ns.get

Is equivalent to:

ns = Nest.new("foo")
ns.call("APPEND", "hello,")
ns.call("APPEND", " world")
ns.call("GET")

Supplying your existing Redis instance

You can supply a Redic instance as a second parameter. If you don't, a default instance is created for you:

>> redis = Redic.new("redis://localhost:6379")
=> #<Redic:0x007fa640845f10 ...>

>> event = Nest.new("Event", redis)
=> "Event"

>> event[:id].call("TYPE")
=> "string"

Nest objects respond to redis and return a Redic instance. It is automatically reused when you create a new namespace, and you can reuse it when creating a new instance of Nest:

>> event = Nest.new("Event", meetup.redis)
=> "Event"

Nest allows you to execute all the Redis commands that expect a key as the first parameter. If you use any other command, the result can be unexpected.

Differences with redis-namespace

redis-namespace wraps Redis and translates the keys back and forth transparently.

Use redis-namespace when you want all your application keys to live in a different scope.

Use Nest when you want to use the keys to represent structure.

Tip: instead of using redis-namespace, it is recommended that you run a different instance of redis-server. Translating keys back and forth is not only delicate, but unnecessary and counterproductive.

Differences with Ohm

Ohm lets you map Ruby objects to Redis with little effort. It not only alleviates you from the pain of generating keys for each object, but also helps you when dealing with references between objects.

Use Ohm when you want to use Redis as your database.

Use Nest when mapping objects with Ohm is not possible or overkill.

Tip: Ohm uses Nest internally to deal with keys. Having a good knowledge of Nest will let you extend Ohm to suit your needs.

Installation

$ gem install nest

nest's People

Contributors

bsedin avatar djanowski avatar soveran avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nest's Issues

nest is returning interfered result in thin

nest.get is returning result of different redis query (like a redis set, or of different key) when running in thin.

When I switch from nest to the regular redis-rb, the issue go away.

Issues when running with Activesupport

Activesupport overrides Object#to_json so that it calls Object#as_json. The latter however looks for to_hash method and if not found just grabs all the instance variables. This leads to Nest.initialize('foo').to_json returning a ton of garbage instead of a key, because it also appends @rc

The issue can be solved by adding Nest#to_json explicitly so that it does to_s.to_json for example

UPD: this won't work. The solutions are to add Nest#to_hash or Nest#as_json to return @ns, both of which being kinda meh since it's not really a hash...

This is ok for a monkeypatch workaround though =)

Add some extensions

I'm not sure where did I copy these extensions from, perhaps redis-ruby. These extensions let nest use hash directly. I find them very useful. Do you think we can add them to the gem?

Nest.class_eval do
  def mapped_hmget(*fields)
    Hash[**hmget(*fields)]
  end

  def mapped_hgetall
    Hash[*hgetall]
  end

  def mapped_hmset(values)
    hmset(*values.to_a.flatten)
  end
end

addition of method_missing without to_ary breaks ohm

A test app with ohm 3.1.1 and nest 3.1.0 (ruby 2.3.1p112) fails on Ohm::Model#find:

TypeError: can't convert Nest to Array (Nest#to_ary gives RuntimeError)
	ohm-3.1.1/lib/ohm.rb:1480:in `flatten'

This may be related to an interaction between method_missing and flatten discussed here. I did not write tests, but cargo-culting the solution applied to bundler there also appeared to solve the problem for nest:

private
def to_ary
  nil
end

Thanks!

Passing blocks to Redis and 1.8.6

I've just run into the issue on Ruby 1.8.6 where define_method doesn't recognize block arguments. You can read more here

I've tried every combo I can think of to patch this up and nothing really seems to work well. class_eval results in stack level too deep and I'm not sure how far down the rabbit hole I want to go on this one.

If you guys have any idea, I'd love to hear it. Obviously "use 1.8.7 or higher" is a valid answer ;)

Use method missing instead of just call?

I think the old interface is what make nest great. Instead of sterilze this to only "call" I think we'd better use method missing instead. The syntax error still propagate through RuntimeError exception What do you say?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.