attribute_mapper 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ coverage
2
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2007-2009 Marcel Molina, Jr., Bruce Williams, Adam Keys
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # AttributeMapper
2
+
3
+ AttributeMapper provides a transparent interface for mapping
4
+ symbolic representations to a column in the database of a more primitive type.
5
+ For example, rather than hardcoding values like 1 or 2 to represent that a
6
+ Ticket model's status column is "open" or "closed" you would create the
7
+ following mapping:
8
+
9
+ class Ticket < ActiveRecord::Base
10
+ map_attribute :status, :to => {:open => 1, :closed => 2}
11
+ end
12
+
13
+ You can now get and set the status column symbolically:
14
+
15
+ ticket.status = :open
16
+ ticket.status # => :open
17
+
18
+ Internally, the integer 1 will be stored in the database.
19
+
20
+ An authoritative list of the mapping is available as a class method which is the pluralized version of the attribute:
21
+
22
+ Ticket.statuses # => {:open => 1, :closed => 2}
23
+
24
+ The primitive values of the mapping can always be used to assign the column,
25
+ though the getter for the attribute will always return the higher level
26
+ symbolic representation.
27
+
28
+ ticket.status = 1
29
+ ticket.status # => :open
30
+
31
+ ## Authors
32
+
33
+ Marcel Molina, Jr., Bruce Williams and Adam Keys
34
+
35
+ Released under the MIT License (see LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require 'rake/testtask'
2
+ require 'rcov/rcovtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.test_files = FileList['test/*_test.rb']
8
+ t.ruby_opts = ['-rubygems']
9
+ end
10
+
11
+ Rcov::RcovTask.new do |t|
12
+ t.test_files = FileList['test/*_test.rb']
13
+ end
14
+
15
+ begin
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |s|
18
+ s.name = 'attribute_mapper'
19
+ s.summary = 'Map symbolic types to primitive types and stash them in a column.'
20
+ s.email = 'adamkkeys@gmail.com'
21
+ s.homepage = 'http://github.com/therealadam/attribute_mapper'
22
+ s.description = 'Provides a transparent interface for mapping symbolic representations to a column in the database of a more primitive type.'
23
+ s.authors = ['Marcel Molina Jr.', 'Bruce Williams', 'Adam Keys']
24
+ end
25
+ rescue LoadError
26
+ puts "Jeweler not available. Install it with: gem install technicalpickles-jeweler -s http://gems.github.com"
27
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 9
3
+ :patch: 1
4
+ :major: 0
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{attribute_mapper}
5
+ s.version = "0.9.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Marcel Molina Jr.", "Bruce Williams", "Adam Keys"]
9
+ s.date = %q{2009-03-10}
10
+ s.description = %q{Provides a transparent interface for mapping symbolic representations to a column in the database of a more primitive type.}
11
+ s.email = %q{adamkkeys@gmail.com}
12
+ s.files = ["README.md", "VERSION.yml", "lib/attribute_mapper.rb", "test/attribute_mapper_test.rb"]
13
+ s.has_rdoc = true
14
+ s.homepage = %q{http://github.com/therealadam/attribute_mapper}
15
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
16
+ s.require_paths = ["lib"]
17
+ s.rubygems_version = %q{1.3.1}
18
+ s.summary = %q{Map symbolic types to primitive types and stash them in a column.}
19
+
20
+ if s.respond_to? :specification_version then
21
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
22
+ s.specification_version = 2
23
+
24
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
25
+ else
26
+ end
27
+ else
28
+ end
29
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) << "/lib/attribute_mapper"
2
+ AttributeMapper.load
@@ -0,0 +1,71 @@
1
+ module AttributeMapper
2
+
3
+ class << self
4
+
5
+ def included(model)
6
+ model.extend ClassMethods
7
+ model.send(:include, InstanceMethods)
8
+ end
9
+
10
+ def load
11
+ ActiveRecord::Base.send(:include, AttributeMapper)
12
+ end
13
+
14
+ end
15
+
16
+ module ClassMethods
17
+ def map_attribute(attribute, options)
18
+ mapping = options[:to]
19
+ verify_existence_of attribute
20
+ add_accessor_for attribute, mapping
21
+ override attribute
22
+ end
23
+
24
+ private
25
+ def add_accessor_for(attribute, mapping)
26
+ class_eval(<<-EVAL)
27
+ class << self
28
+ def #{attribute.to_s.pluralize}
29
+ #{mapping.inspect}
30
+ end
31
+ end
32
+ EVAL
33
+ end
34
+
35
+ def override(*args)
36
+ override_getters *args
37
+ override_setters *args
38
+ end
39
+
40
+ def override_getters(attribute)
41
+ class_eval(<<-EVAL)
42
+ def #{attribute}
43
+ self.class.#{attribute.to_s.pluralize}.invert[read_attribute(:#{attribute})]
44
+ end
45
+ EVAL
46
+ end
47
+
48
+ def override_setters(attribute)
49
+ class_eval(<<-EVAL)
50
+ def #{attribute}=(raw_value)
51
+ value = resolve_value_of :#{attribute}, raw_value
52
+ write_attribute(:#{attribute}, value)
53
+ end
54
+ EVAL
55
+ end
56
+
57
+ def verify_existence_of(attribute)
58
+ raise ArgumentError, "`#{attribute}' is not an attribute of `#{self}'" unless column_names.include?(attribute.to_s)
59
+ end
60
+ end
61
+
62
+ module InstanceMethods
63
+ private
64
+ def resolve_value_of(attribute, raw_value)
65
+ check_value = raw_value.is_a?(String) ? raw_value.to_sym : raw_value
66
+ mapping = self.class.send(attribute.to_s.pluralize)
67
+ raise ArgumentError, "`#{check_value}' not present in attribute mapping `#{mapping.inspect}'" unless mapping.to_a.flatten.include? check_value
68
+ mapping[check_value] || check_value
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,102 @@
1
+ require 'test/unit'
2
+ require 'shoulda'
3
+ require 'active_record'
4
+
5
+ require 'attribute_mapper'
6
+
7
+ AttributeMapper.load
8
+
9
+ ActiveRecord::Base.establish_connection(
10
+ :adapter => 'sqlite3',
11
+ :database => ':memory:'
12
+ )
13
+
14
+ ActiveRecord::Schema.define do
15
+ create_table :tickets do |table|
16
+ table.column :status, :integer
17
+ end
18
+ end
19
+
20
+ # Pseudo model for testing purposes
21
+ class Ticket < ActiveRecord::Base
22
+ end
23
+
24
+ class AttributeMapperTest < Test::Unit::TestCase
25
+
26
+ context "Attribute Mapper" do
27
+ setup do
28
+ Ticket.map_attribute :status, :to => mapping
29
+ end
30
+
31
+ should "set mapping for each attribute" do
32
+ assert_equal mapping[:open], Ticket.statuses[:open]
33
+ assert_equal mapping[:closed], Ticket.statuses[:closed]
34
+ end
35
+
36
+ should "override getters and setters" do
37
+ assert_nil ticket.status
38
+ assert_nothing_raised do
39
+ ticket.status = :open
40
+ end
41
+ assert_equal :open, ticket.status
42
+ assert_equal mapping[:open], ticket[:status]
43
+
44
+ assert_nothing_raised do
45
+ ticket.status = :closed
46
+ end
47
+
48
+ assert_equal :closed, ticket.status
49
+ assert_equal mapping[:closed], ticket[:status]
50
+ end
51
+
52
+ should "allow indifferent access to setters" do
53
+ assert_nothing_raised do
54
+ ticket.status = :open
55
+ end
56
+ assert_equal :open, ticket.status
57
+ assert_nothing_raised do
58
+ ticket.status = 'open'
59
+ end
60
+ assert_equal :open, ticket.status
61
+ end
62
+
63
+ should "raise an exception when trying to map to a non-existent column" do
64
+ assert_raises(ArgumentError) do
65
+ Ticket.map_attribute :this_column_does_not_exist, :to => {:i_will_fail => 1}
66
+ end
67
+ end
68
+
69
+ should "raise an exception when setting an invalid value" do
70
+ assert_raises(ArgumentError) do
71
+ ticket.status = :non_existent_value
72
+ end
73
+ end
74
+
75
+ should "allow setting a primitive value directly if the value is present in the mapping" do
76
+ ticket = Ticket.new
77
+ assert_nothing_raised do
78
+ ticket.status = mapping[:open]
79
+ end
80
+
81
+ assert_equal :open, ticket.status
82
+
83
+ assert_raises(ArgumentError) do
84
+ ticket.status = 500
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ #######
91
+ private
92
+ #######
93
+
94
+ def mapping(options = {})
95
+ {:open => 1, :closed => 2}.merge(options)
96
+ end
97
+
98
+ def ticket
99
+ @ticket ||= Ticket.new
100
+ end
101
+
102
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: attribute_mapper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ platform: ruby
6
+ authors:
7
+ - Marcel Molina Jr.
8
+ - Bruce Williams
9
+ - Adam Keys
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+
14
+ date: 2009-10-26 00:00:00 -05:00
15
+ default_executable:
16
+ dependencies: []
17
+
18
+ description: Provides a transparent interface for mapping symbolic representations to a column in the database of a more primitive type.
19
+ email: adamkkeys@gmail.com
20
+ executables: []
21
+
22
+ extensions: []
23
+
24
+ extra_rdoc_files:
25
+ - LICENSE
26
+ - README.md
27
+ files:
28
+ - .gitignore
29
+ - LICENSE
30
+ - README.md
31
+ - Rakefile
32
+ - VERSION.yml
33
+ - attribute_mapper.gemspec
34
+ - init.rb
35
+ - lib/attribute_mapper.rb
36
+ - test/attribute_mapper_test.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/therealadam/attribute_mapper
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.5
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Map symbolic types to primitive types and stash them in a column.
65
+ test_files:
66
+ - test/attribute_mapper_test.rb