README.rdoc in enumerate_it-0.7.3 vs README.rdoc in enumerate_it-0.7.4
- old
+ new
@@ -4,45 +4,45 @@
== Description
Ok, I know there are a lot of different solutions to this problem. But none of them solved my problem,
so here's EnumerateIt. I needed to build a Rails application around a legacy database and this database was
-filled with those small, unchangeable tables used to create foreign key constraints everywhere.
+filled with those small, unchangeable tables used to create foreign key constraints everywhere.
=== For example:
- Table "public.relationshipstatus"
- Column | Type | Modifiers
- -------------+---------------+-----------
- code | character(1) | not null
- description | character(11) |
- Indexes:
- "relationshipstatus_pkey" PRIMARY KEY, btree (code)
+ Table "public.relationshipstatus"
+ Column | Type | Modifiers
+ -------------+---------------+-----------
+ code | character(1) | not null
+ description | character(11) |
+ Indexes:
+ "relationshipstatus_pkey" PRIMARY KEY, btree (code)
- select * from relationshipstatus;
- code | description
- -------+--------------
- 1 | Single
- 2 | Married
- 3 | Widow
- 4 | Divorced
+ select * from relationshipstatus;
+ code | description
+ -------+--------------
+ 1 | Single
+ 2 | Married
+ 3 | Widow
+ 4 | Divorced
-And then I had things like a people table with a 'relationship_status' column with a foreign key
+And then I had things like a people table with a 'relationship_status' column with a foreign key
pointing to the relationshipstatus table.
While this is a good thing from the database normalization perspective, managing this values in
-my tests was very hard. Doing database joins just to get the description of some value was absurd.
-And, more than this, referencing them in my code using magic numbers was terrible and meaningless:
+my tests was very hard. Doing database joins just to get the description of some value was absurd.
+And, more than this, referencing them in my code using magic numbers was terrible and meaningless:
What does it mean when we say that someone or something is '2'?
Enter EnumerateIt.
== Creating enumerations
-Enumerations are created as models, but you can put then anywhere in your application. In Rails
-applications, you can put them inside models/.
+Enumerations are created as models, but you can put then anywhere in your application. In Rails
+applications, you can put them inside models/.
class RelationshipStatus < EnumerateIt::Base
associate_values(
:single => [1, 'Single'],
:married => [2, 'Married'],
@@ -64,11 +64,11 @@
* You can get an array of options, ready to use with the 'select', 'select_tag', etc family of Rails helpers.
RelationshipStatus.to_a # [["Divorced", 4],["Married", 2],["Single", 1],["Widow", 3]]
-* You can retrieve a list with values for a group of enumeration constants.
+* You can retrieve a list with values for a group of enumeration constants.
RelationshipStatus.values_for %w(MARRIED SINGLE) # [2, 1]
* You can manipulate the hash used to create the enumeration:
@@ -84,13 +84,13 @@
attr_accessor :relationship_status
has_enumeration_for :relationship_status, :with => RelationshipStatus
end
-The :with option is not required. If you ommit it, EnumerateIt will try to load an enumeration class based on the camelized attribute name.
+The :with option is not required. If you ommit it, EnumerateIt will try to load an enumeration class based on the camelized attribute name.
-This will create:
+This will create:
* A humanized description for the values of the enumerated attribute:
p = Person.new
p.relationship_status = RelationshipStatus::DIVORCED
@@ -100,17 +100,21 @@
class RelationshipStatus < EnumerateIt::Base
associate_values(
:married => 1,
:single => 2
- )
+ )
end
p = Person.new
p.relationship_status = RelationshipStatus::MARRIED
p.relationship_status_humanize # => 'Married'
+* The associated enumerations can be retrieved with the 'enumerations' class method.
+
+ Person.enumerations[:relationship_status] # => RelationshipStatus
+
* If you pass the :create_helpers option as 'true', it will create a helper method for each enumeration option (this option defaults to false):
class Person < ActiveRecord::Base
has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => true
end
@@ -118,10 +122,21 @@
p = Person.new
p.relationship_status = RelationshipStatus::MARRIED
p.married? #=> true
p.divorced? #=> false
+* The :create_helpers also creates some mutator helper methods, that can be used to change the attribute's value.
+
+ class Person < ActiveRecord::Base
+ has_enumeration_for :relationship_status, :with => RelationshipStatus, :create_helpers => true
+ end
+
+ p = Person.new
+ p.married!
+ p.married? #=> true
+ p.divorced? #=> false
+
* If your class can manage validations and responds to :validates_inclusion_of, it will create this validation:
class Person < ActiveRecord::Base
has_enumeration_for :relationship_status, :with => RelationshipStatus
end
@@ -139,11 +154,11 @@
p = Person.new :relationship_status => nil
p.valid? # => false
p.errors[:relationship_status] # => "can't be blank"
-Remember that in Rails 3 you can add validations to any kind of class and not only to those derived from
+Remember that in Rails 3 you can add validations to any kind of class and not only to those derived from
ActiveRecord::Base.
== I18n
I18n lookup is provided on both '_humanized' and 'Enumeration#to_a' methods, given the hash key is a Symbol. The I18n strings are
@@ -160,20 +175,20 @@
# your locale file
pt:
enumerations:
relationship_status:
married: Casado
-
+
p = Person.new
p.relationship_status = RelationshipStatus::MARRIED
- p.relationship_status_humanize # => 'Casado'
-
+ p.relationship_status_humanize # => 'Casado'
+
p.relationship_status = RelationshipStatus::SINGLE
- p.relationship_status_humanize # => 'Single' => nonexistent key
-
+ p.relationship_status_humanize # => 'Single' => nonexistent key
+
p.relationship_status = RelationshipStatus::DIVORCED
- p.relationship_status_humanize # => 'He's divorced' => uses the provided string
+ p.relationship_status_humanize # => 'He's divorced' => uses the provided string
You can also translate specific values:
RelationshipStatis.t(1) # => 'Casado'
@@ -183,11 +198,11 @@
== Using with Rails
* Create an initializer with the following code:
- ActiveRecord::Base.send :include, EnumerateIt
+ ActiveRecord::Base.send :include, EnumerateIt
* Add the 'enumerate_it' gem as a dependency in your environment.rb (Rails 2.3.x) or Gemfile (if you're using Bundler)
An interesting approach to use it in Rails apps is to create an app/models/enumerations folder and add it to your autoload path in config/application.rb:
@@ -199,23 +214,36 @@
== Ruby 1.9
EnumerateIt is fully compatible with Ruby 1.9.1 and 1.9.2 (all tests pass)
+* Note: on ruby 1.9.2, if you are using the enumerations in a separate folder like app/models/enumerations, and have to use the :with parameter, you have to clear the enum class namespace to a global scope by using ::EnumClass instead of EnumClass:
+
+ # 1.8.7
+ class Person < ActiveRecord::Base
+ has_enumeration_for :relationship_status, :with => EnumClass
+ end
+
+ # 1.9.2
+ class Person < ActiveRecord::Base
+ has_enumeration_for :relationship_status, :with => ::EnumClass
+ end
+
+
== Why did you reinvent the wheel?
There are other similar solutions to the problem out there, but I could not find one that
-worked both with strings and integers as the enumerations' codes. I had both situations in
-my legacy database.
+worked both with strings and integers as the enumerations' codes. I had both situations in
+my legacy database.
== Why defining enumerations outside the class that use it?
* I think it's cleaner.
* You can add behaviour to the enumeration class.
* You can reuse the enumeration inside other classes.
== Note on Patches/Pull Requests
-
+
* Fork the project.
* Make your feature addition or bug fix.
* Add tests for it. This is important so I don't break it in a
future version unintentionally.
* Commit, do not mess with rakefile, version, or history.