encoder 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ *~
7
+ *.gem
8
+ tmp
9
+ .yardoc
10
+ doc/*
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Jon Morton
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,44 @@
1
+ Encode
2
+ =========
3
+
4
+ Encode makes it easy to go from codes to meaningful strings.
5
+
6
+ Example
7
+ =======
8
+
9
+ Suppose you have a task in one of three possible states: pending, active, finished. When you store tasks, you'd like to have the state represented as P for pending, A for active, and F, for finished. However, you don't want to worry about the details of turning a state into a specific character.
10
+
11
+ t = Task.new('feed the cat')
12
+
13
+ # By default
14
+ t.status = Status::Pending
15
+ t.status # => 'P'
16
+ t.status.decode # => 'Pending'
17
+
18
+ # You'd probably encapsulate this in a method though wouldn't you?
19
+ t.finish!
20
+
21
+ # How should that be implemented though?
22
+ @status = 'f'
23
+ @status = 'finished'
24
+ @status = Task::Status::Finished
25
+
26
+ However, you want to store the state as a single character behind the scenes without having to define a bunch of custom getters or setters.
27
+
28
+ class Task
29
+ code :status do
30
+ Status::Pending = "P"
31
+ Status::Active = "A"
32
+ Status::Finished = "F"
33
+ end
34
+ end
35
+
36
+ To Do
37
+ =====
38
+
39
+ [ ] Auto-mixin on init
40
+ [ ] Make a proper gem
41
+ [ ] Choose a better name
42
+ [ ] Use shoulda or rspec (maybe)
43
+
44
+ Copyright (c) 2010 Jon Morton, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the encode plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the encode plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'Encode'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "encoder"
29
+ gemspec.summary = "Make magic numbers and letters meaningful."
30
+ gemspec.description = "Simplify turning abbreviations into descriptions and vice versa."
31
+ gemspec.email = "jon.morton@gmail.com "
32
+ gemspec.homepage = "http://github.com/jmorton/encoder"
33
+ gemspec.authors = ["Jon Morton"]
34
+ end
35
+ Jeweler::GemcutterTasks.new
36
+ rescue LoadError
37
+ puts "Jeweler not available. Install it with: gem install jeweler"
38
+ end
39
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
data/lib/encoder.rb ADDED
@@ -0,0 +1,92 @@
1
+ module Encoder
2
+
3
+ def self.included(base)
4
+ base.class_eval do
5
+ extend ClassMethods
6
+ end
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ #
12
+ # Creates getter and setter methods for an attribute. The getter
13
+ # returns a 'decodable' string that provides more meaning.
14
+ #
15
+ # Example:
16
+ #
17
+ # class Task
18
+ # include Encoder
19
+ # code :priority do
20
+ # Priority::Low = "L"
21
+ # end
22
+ # end
23
+ #
24
+ # t = Task.new
25
+ # t.priority = Priority::Low
26
+ # t.priority # => "L"
27
+ # t.priority.decode # => "Low"
28
+ #
29
+ def code(attribute_name, &block)
30
+
31
+ # Create a 'namespace' for constants
32
+ const_set(attribute_name.to_s.camelcase, Module.new)
33
+
34
+ # Expecting constants to be assigned values.
35
+ yield
36
+
37
+ # create setter for attribute
38
+ self.send(:define_method, "#{attribute_name}=") do |arg|
39
+
40
+ # At the end of this method, the underlying attribute will be set
41
+ # to the value of this variable.
42
+ encoded_value = nil
43
+
44
+ # Retrieve the module where the constants for this attribute are defined.
45
+ namespace = self.class.const_get(attribute_name.to_s.camelcase)
46
+
47
+ # Since the given value might not match the constant name exactly
48
+ # (because of case sensitivity or white space variations) we
49
+ # normalize it a bit.
50
+ normalized = arg && arg.gsub(/\s+/,'').downcase
51
+
52
+ # Now we look for a constant whose name or actual value match the
53
+ # normalized argument. We 'tap' whatever constant name is found
54
+ # and lookup the actual value.
55
+ namespace.constants.find do |const_name|
56
+ normalized == const_name.downcase ||
57
+ normalized == namespace.const_get(const_name).downcase
58
+ end.tap do |match|
59
+ encoded_value = namespace.const_get(match) if match
60
+ end
61
+
62
+ # Set the value to whatever we found, possibly nil
63
+ self.write_attribute(attribute_name, encoded_value)
64
+ end
65
+
66
+ # create getter for attribute
67
+ self.send(:define_method, attribute_name) do
68
+
69
+ encoded_attribute = self.read_attribute(attribute_name)
70
+
71
+ namespace = self.class.const_get(attribute_name.to_s.camelcase)
72
+
73
+ decoded_value = namespace.constants.select do |constant|
74
+ namespace.const_get(constant) == encoded_attribute
75
+ end.first
76
+
77
+ encoded_attribute.instance_variable_set(:@decoding, decoded_value)
78
+
79
+ class << encoded_attribute
80
+ def decode
81
+ @decoding && @decoding.underscore.titleize
82
+ end
83
+ end
84
+
85
+ return encoded_attribute
86
+ end # -- dynamic getter method
87
+
88
+ end # -- code()
89
+
90
+ end
91
+
92
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Include hook code here
2
+ require File.join(File.dirname(__FILE__), *%w[.. lib encoder])
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :encoder do
3
+ # # Task goes here
4
+ # end
data/test/database.rb ADDED
@@ -0,0 +1,36 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'active_record'
5
+ gem 'sqlite3-ruby'
6
+
7
+ require File.dirname(__FILE__) + '/../rails/init'
8
+
9
+ ActiveRecord::Base.logger = Logger.new('/tmp/encoder.log')
10
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => '/tmp/encoder.sqlite')
11
+ ActiveRecord::Migration.verbose = false
12
+ ActiveRecord::Base.default_timezone = :utc if Time.zone.nil?
13
+
14
+ ActiveRecord::Schema.define do
15
+ create_table :tasks, :force => true do |table|
16
+ table.string :status
17
+ table.string :priority
18
+ end
19
+ end
20
+
21
+ class Task < ActiveRecord::Base
22
+ include ::Encoder
23
+
24
+ code :status do
25
+ Status::New = "N"
26
+ Status::Pending = "P"
27
+ Status::Finished = "F"
28
+ Status::OverDue = "O"
29
+ end
30
+
31
+ code :priority do
32
+ Priority::High = "H"
33
+ Priority::Low = "L"
34
+ end
35
+
36
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../test_helper'))
2
+
3
+ class EncoderTest < ActiveSupport::TestCase
4
+
5
+ test "setting an attribute using a constant persists the encoding" do
6
+ task = ::Task.new
7
+ task.status = Task::Status::New
8
+ task.save
9
+
10
+ db_task = ::Task.first
11
+ assert db_task.status == 'N'
12
+ end
13
+
14
+ test "setting an attribute using a description persists the correct encoding" do
15
+ task = ::Task.new
16
+ task.status = 'New'
17
+ task.save
18
+
19
+ db_task = ::Task.first
20
+ assert db_task.status == 'N'
21
+ assert db_task.status.decode == 'New'
22
+ end
23
+
24
+ end
@@ -0,0 +1,13 @@
1
+ ENV['RAILS_ENV'] = 'test'
2
+ ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
3
+
4
+ require 'test/unit'
5
+ require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
6
+
7
+ require 'rubygems'
8
+ require 'active_support'
9
+ require 'active_support/test_case'
10
+ require 'test/unit'
11
+
12
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/encoder'))
13
+ require File.expand_path(File.join(File.dirname(__FILE__), 'database'))
@@ -0,0 +1,69 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../test_helper'))
2
+
3
+ class EncoderTest < ActiveSupport::TestCase
4
+
5
+ test "setting an attribute using a constant" do
6
+ task = ::Task.new
7
+ task.status = Task::Status::New
8
+ assert task.status == Task::Status::New
9
+ end
10
+
11
+ test "setting an attribute using a verbose value" do
12
+ task = ::Task.new
13
+ task.status = "New"
14
+ assert task.status == Task::Status::New
15
+ end
16
+
17
+ test "setting an attribute using a an invalid value overwrites a valid one" do
18
+ task = ::Task.new
19
+ task.status = "New"
20
+ task.status = "Invalid"
21
+ assert task.status == nil
22
+ end
23
+
24
+ test "decoding an attribute should match the constant name" do
25
+ task = ::Task.new
26
+ task.status = Task::Status::New
27
+ assert task.status.decode == 'New'
28
+ end
29
+
30
+ test "encoding a description ignores caps" do
31
+ task = ::Task.new
32
+ task.status = 'new'
33
+ assert task.status == Task::Status::New
34
+ task.status = 'NEW'
35
+ assert task.status == Task::Status::New
36
+ end
37
+
38
+ test "encoding a multiword description" do
39
+ task = ::Task.new
40
+ task.status = 'over due'
41
+ assert task.status == Task::Status::OverDue
42
+ end
43
+
44
+ test "decoding a multiword description" do
45
+ task = ::Task.new
46
+ task.status = Task::Status::OverDue
47
+ assert task.status.decode == 'Over Due'
48
+ end
49
+
50
+ test "setting an encoded attribute to nil" do
51
+ task = ::Task.new
52
+ task.status = nil
53
+ assert task.status == nil
54
+ end
55
+
56
+ test "a code's attribute name corresponds to a camelcased namespace" do
57
+ task = ::Task.new
58
+
59
+ class ::Task
60
+ code :foo_bar do
61
+ FooBar::Baz = 1
62
+ FooBar::Buzz = 2
63
+ end
64
+ end
65
+
66
+ assert Task.const_defined?(:FooBar)
67
+ end
68
+
69
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: encoder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jon Morton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-20 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Simplify turning abbreviations into descriptions and vice versa.
17
+ email: "jon.morton@gmail.com "
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - .gitignore
26
+ - MIT-LICENSE
27
+ - README
28
+ - Rakefile
29
+ - VERSION
30
+ - install.rb
31
+ - lib/encoder.rb
32
+ - rails/init.rb
33
+ - tasks/encoder_tasks.rake
34
+ - test/database.rb
35
+ - test/functional/encoder_test.rb
36
+ - test/test_helper.rb
37
+ - test/unit/encoder_test.rb
38
+ - uninstall.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/jmorton/encoder
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.5
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Make magic numbers and letters meaningful.
67
+ test_files:
68
+ - test/database.rb
69
+ - test/functional/encoder_test.rb
70
+ - test/test_helper.rb
71
+ - test/unit/encoder_test.rb