NoBrainerORM / nobrainer

Ruby ORM for RethinkDB
http://nobrainer.io/
Other
387 stars 49 forks source link

Enum Support #153

Closed robertjpayne closed 9 years ago

robertjpayne commented 9 years ago

First off wanted to say amazing work on this library, using it in two projects now and absolutely loving it.

I looked through the docs and didn't see anything, so thought I may ask if Enum's are supported currently and if not is it worth while implementing something like ActiveRecord::Enum?

I'd prefer not to have enums stored as integers only because it's to easy to add an extra value at the front of an array and have your data get mucked but overall an enum would be pretty useful.

I think I could probably manage this with a custom type right now, but seems a tiny bit dodgy.

nviennot commented 9 years ago

Hi Robert,

You're welcome :)

So it seems that you want to do something like this:

class Job
  VALID_STATUS = [:pending, :processing, :success, :fail]
  field :status, :type => Symbol, :in => VALID_STATUS, :default => VALID_STATUS.first
end
robertjpayne commented 9 years ago

Little bit late reply, the only addition that ActiveRecord does is automatically stub a few methods like:

pending? pending! etc… it's pretty minimal and I didn't missed that NoBrainer supports symbols so I'm pretty happy already! Thanks again for all the hard work!

ajselvig commented 9 years ago

This is pretty easy with a few lines in a concern:

class_methods do
  # defines a symbol field that only accepts a fixed set of possible values
  def enum_field(name, values)
    field name, type: Symbol, in: values, default: values.first

    # create helper methods for name_value? and name_value!
    values.each do |value|
      define_method("#{name}_#{value}?") { self.send(name) == value }
      define_method("#{name}_#{value}!") { self.send("#{name}=", value) }
    end
  end
end

I actually didn't realize NoBrainer supports symbols either. Is there really any benefit to using them over strings, though?

nviennot commented 9 years ago

I'll add a new type Enum that would do exactly what your concern does :)

As for working with Symbols, it's just more idiomatic to work with them for these sort of things. But it has no difference really.

nviennot commented 9 years ago

I've added the Enum type. Here's how you can use it:

class Job
  VALID_STATUS = [:pending, :processing, :success, :fail]
  field :status, :type => Enum, :in => VALID_STATUS, :default => VALID_STATUS.first
end

It has the same behavior as ActiveRecord (you get 2 instance methods, and 1 class method per value). You can also specify :prefix and :suffix in the options to provide different method names.

robertjpayne commented 9 years ago

@nviennot just getting around to updating my models to take advantage of this. Unsure if there's a conflict or not but this is firing an error saying Enum is an uninitialized constant:

class Job
    include NoBrainer::Document
    field :status, type: Enum, in: [:pending, :accepted], default: :pending
end

This is mostly in a rails app with Job.rb inside of models. What I can't figure out is why things like Binary/Geo::Point etc… all work fine.

I'm also not loading ActiveRecord.

nviennot commented 9 years ago

1) Make sure you are working with the latest NoBrainer: Gem.loaded_specs['nobrainer'].git_version should give you something matching the master commit 2) If it still doesn't work, try to use NoBrainer::Enum instead.

robertjpayne commented 9 years ago

Gah really sorry I double checked I was on the latest version but didn't realise these were only in Master. There was a 0.28.0 release on the same day you implemented this so I figured it was the same!

Ignore me now, shamefully going to ensure it's pointing at git master!

nviennot commented 9 years ago

No worries!

btw, you can keep track of what features get into which version here: http://nobrainer.io/docs/changelog/

cantonic commented 8 years ago

The enum type is not listed in http://nobrainer.io/docs/types/ yet

nviennot commented 8 years ago

Done!