Permalink
Browse files

Added actual code

  • Loading branch information...
1 parent 6a824fd commit 7a16ade293304f1cf3608f0f239558ad25de6521 @beerlington beerlington committed Sep 22, 2010
Showing with 258 additions and 12 deletions.
  1. +3 −3 Rakefile
  2. +55 −0 classy_enum.gemspec
  3. +2 −0 init.rb
  4. +105 −0 lib/classy_enum.rb
  5. +89 −3 spec/classy_enum_spec.rb
  6. +4 −6 spec/spec_helper.rb
View
@@ -5,9 +5,9 @@ begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "classy_enum"
- gem.summary = %Q{TODO: one-line summary of your gem}
- gem.description = %Q{TODO: longer description of your gem}
- gem.email = "pete@lette.us"
+ gem.summary = %Q{A class based enumerator utility for Ruby on Rails}
+ gem.description = %Q{A utility that adds class based enum functionaltiy to ActiveRecord attributes}
+ gem.email = "github@lette.us"
gem.homepage = "http://github.com/beerlington/classy_enum"
gem.authors = ["Peter Brown"]
gem.add_development_dependency "rspec", ">= 1.2.9"
View
@@ -0,0 +1,55 @@
+# Generated by jeweler
+# DO NOT EDIT THIS FILE DIRECTLY
+# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{classy_enum}
+ s.version = "0.0.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Peter Brown"]
+ s.date = %q{2010-09-21}
+ s.description = %q{A utility that adds class based enum functionaltiy to ActiveRecord attributes}
+ s.email = %q{github@lette.us}
+ s.extra_rdoc_files = [
+ "LICENSE",
+ "README.rdoc"
+ ]
+ s.files = [
+ ".document",
+ ".gitignore",
+ "LICENSE",
+ "README.rdoc",
+ "Rakefile",
+ "VERSION",
+ "classy_enum.gemspec",
+ "lib/classy_enum.rb",
+ "spec/classy_enum_spec.rb",
+ "spec/spec.opts",
+ "spec/spec_helper.rb"
+ ]
+ s.homepage = %q{http://github.com/beerlington/classy_enum}
+ s.rdoc_options = ["--charset=UTF-8"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.3.7}
+ s.summary = %q{A class based enumerator utility for Ruby on Rails}
+ s.test_files = [
+ "spec/classy_enum_spec.rb",
+ "spec/spec_helper.rb"
+ ]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
+ else
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
+ end
+ else
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
+ end
+end
+
View
@@ -0,0 +1,2 @@
+# Adds active_set_helper method to all active record classes
+require 'classy_enum'
View
@@ -0,0 +1,105 @@
+class ClassyEnumValue < Object
+
+ attr_reader :to_s, :index
+
+ def initialize(option, index)
+ @to_s = option.to_s.downcase
+ @index = index + 1
+ end
+
+ def name
+ to_s.titleize
+ end
+
+ def <=> other
+ @index <=> other.index
+ end
+
+end
+
+module ClassyEnum
+
+ module ClassMethods
+
+ def new(option)
+ self::OPTION_HASH[option] || TypeError.new("Valid #{self} options are #{self.valid_options}")
+ end
+
+ def all
+ self::OPTIONS.map {|e| self.new(e) }
+ end
+
+ # Uses the name field for select options
+ def all_with_name
+ self.all.map {|e| [e.name, e.to_s] }
+ end
+
+ def valid_options
+ self::OPTIONS.map(&:to_s).join(', ')
+ end
+
+ # Alias of new
+ def find(option)
+ new(option)
+ end
+
+ end
+
+ def self.included(other)
+ other.extend ClassMethods
+
+ other.const_set("OPTION_HASH", Hash.new)
+
+ other::OPTIONS.each do |option|
+ klass = Class.new(ClassyEnumValue) {
+ include other::Defaults if other.const_defined?("Defaults")
+ }
+
+ Object.const_set("#{other}#{option.to_s.camelize}", klass)
+
+ instance = klass.new(option, other::OPTIONS.index(option))
+
+ other::OPTION_HASH[option] = other::OPTION_HASH[option.to_s.downcase] = instance
+
+ ClassyEnum.const_set(option.to_s.upcase, instance)
+ end
+
+ end
+
+end
+
+module ClassyEnumAttributes
+ module ClassMethods
+ def classy_enum_attr(klass, method=nil)
+
+ method ||= klass
+
+ klass = klass.to_s.camelize.constantize
+
+ # Add ActiveRecord validation to ensure it won't be saved unless it's an option
+ self.send(:validates_inclusion_of, method, :in => klass.all)
+
+ self.instance_eval do
+
+ # Define getter method
+ define_method method do
+ klass.new(super)
+ end
+
+ # Define setter method
+ define_method "#{method}=" do |value|
+ super value.to_s
+ end
+
+ end
+
+ end
+ end
+
+ def self.included(other)
+ other.extend ClassMethods
+ end
+
+end
+
+ActiveRecord::Base.send :include, ClassyEnumAttributes
@@ -1,7 +1,93 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
-describe "ClassyEnum" do
- it "fails" do
- fail "hey buddy, you should probably rename this file and start specing for real"
+module TestEnum
+ OPTIONS = [:one, :two, :three]
+
+ module Defaults
+ def do_something?
+ false
+ end
+ end
+
+ include ClassyEnum
+end
+
+class TestEnumTwo
+ def do_something?
+ true
end
end
+
+describe ClassyEnum do
+
+ TestEnum::OPTIONS.each do |option|
+ it "should define a TestEnum#{option.to_s.capitalize} class" do
+ Object.const_defined?("TestEnum#{option.to_s.capitalize}").should be_true
+ end
+ end
+
+ it "should return an array of enums" do
+ TestEnum.all.should == TestEnum::OPTIONS.map {|o| TestEnum.new(o) }
+ end
+
+ it "should return an array of enums for a select tag" do
+ TestEnum.all_with_name.should == TestEnum::OPTIONS.map {|o| [TestEnum.new(o).name, TestEnum.new(o).to_s] }
+ end
+
+ it "should return a type error when adding an invalid option" do
+ TestEnum.new(:invalid_option).class.should == TypeError
+ end
+
+ context "with a collection of enums" do
+ before(:each) do
+ @one = TestEnum.new(:one)
+ @two = TestEnum.new(:two)
+ @three = TestEnum.new(:three)
+
+ @unordered = [@one, @three, @two]
+ end
+
+ it "should sort the enums" do
+ @unordered.sort.should == [@one, @two, @three]
+ end
+
+ it "should find the max enum based on its order" do
+ @unordered.max.should == @three
+ end
+ end
+
+ it "should find an enum by symbol" do
+ TestEnum.find(:one).class.should == TestEnumOne
+ end
+
+ it "should find an enum by string" do
+ TestEnum.find("one").class.should == TestEnumOne
+ end
+
+end
+
+describe "An ClassyEnumValue" do
+ before(:each) { @enum = TestEnum.new(:one) }
+
+ it "should have a name" do
+ @enum.name.should == "One"
+ end
+
+ it "should inherit the Default methods" do
+ @enum.do_something?.should be_false
+ end
+
+ it "should create the same instance with a string or symbol" do
+ @enum_string = TestEnum.new("one")
+
+ @enum.should == @enum_string
+ end
+end
+
+describe "An ClassyEnumValue" do
+ before(:each) { @enum = TestEnum.new(:two) }
+
+ it "should override the Default methods" do
+ @enum.do_something?.should be_true
+ end
+end
View
@@ -1,9 +1,7 @@
$LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
-require 'classy_enum'
-require 'spec'
-require 'spec/autorun'
-Spec::Runner.configure do |config|
-
-end
+require 'rubygems'
+require 'active_record'
+require 'classy_enum'
+require 'spec'

0 comments on commit 7a16ade

Please sign in to comment.