attribute_mapper 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.kick +6 -0
- data/HISTORY.rdoc +8 -0
- data/LICENSE +1 -1
- data/VERSION.yml +2 -2
- data/attribute_mapper.gemspec +7 -29
- data/lib/attribute_mapper.rb +89 -57
- data/test/attribute_mapper_test.rb +27 -0
- data/test/test_helper.rb +1 -0
- metadata +4 -2
data/.kick
ADDED
data/HISTORY.rdoc
ADDED
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2007-
|
1
|
+
Copyright (c) 2007-2010 Marcel Molina, Jr., Bruce Williams, Adam Keys
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
4
|
this software and associated documentation files (the "Software"), to deal in
|
data/VERSION.yml
CHANGED
data/attribute_mapper.gemspec
CHANGED
@@ -1,46 +1,25 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
5
2
|
|
6
3
|
Gem::Specification.new do |s|
|
7
4
|
s.name = %q{attribute_mapper}
|
8
|
-
s.version = "
|
5
|
+
s.version = "0.9.1"
|
9
6
|
|
10
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
8
|
s.authors = ["Marcel Molina Jr.", "Bruce Williams", "Adam Keys"]
|
12
|
-
s.date = %q{
|
9
|
+
s.date = %q{2009-03-10}
|
13
10
|
s.description = %q{Provides a transparent interface for mapping symbolic representations to a column in the database of a more primitive type.}
|
14
11
|
s.email = %q{adamkkeys@gmail.com}
|
15
|
-
s.
|
16
|
-
|
17
|
-
"README.md"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
".gitignore",
|
21
|
-
"LICENSE",
|
22
|
-
"README.md",
|
23
|
-
"Rakefile",
|
24
|
-
"VERSION.yml",
|
25
|
-
"attribute_mapper.gemspec",
|
26
|
-
"init.rb",
|
27
|
-
"lib/attribute_mapper.rb",
|
28
|
-
"test/attribute_mapper_test.rb",
|
29
|
-
"test/test_helper.rb"
|
30
|
-
]
|
12
|
+
s.files = ["README.md", "VERSION.yml", "lib/attribute_mapper.rb", "test/attribute_mapper_test.rb"]
|
13
|
+
s.has_rdoc = true
|
31
14
|
s.homepage = %q{http://github.com/therealadam/attribute_mapper}
|
32
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
15
|
+
s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
33
16
|
s.require_paths = ["lib"]
|
34
|
-
s.rubygems_version = %q{1.3.
|
17
|
+
s.rubygems_version = %q{1.3.1}
|
35
18
|
s.summary = %q{Map symbolic types to primitive types and stash them in a column.}
|
36
|
-
s.test_files = [
|
37
|
-
"test/attribute_mapper_test.rb",
|
38
|
-
"test/test_helper.rb"
|
39
|
-
]
|
40
19
|
|
41
20
|
if s.respond_to? :specification_version then
|
42
21
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
-
s.specification_version =
|
22
|
+
s.specification_version = 2
|
44
23
|
|
45
24
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
46
25
|
else
|
@@ -48,4 +27,3 @@ Gem::Specification.new do |s|
|
|
48
27
|
else
|
49
28
|
end
|
50
29
|
end
|
51
|
-
|
data/lib/attribute_mapper.rb
CHANGED
@@ -7,89 +7,121 @@ module AttributeMapper
|
|
7
7
|
|
8
8
|
module ClassMethods # @private
|
9
9
|
|
10
|
-
# Map a column in your table to a human-friendly attribute on your
|
11
|
-
#
|
12
|
-
# the attribute is updated, the value
|
13
|
-
# database.
|
10
|
+
# Map a column in your table to a human-friendly attribute on your
|
11
|
+
# model. When +attribute+ is accessed, it will return the key
|
12
|
+
# from the mapping hash. When the attribute is updated, the value
|
13
|
+
# from the mapping hash is written to the database.
|
14
14
|
#
|
15
15
|
# A class method is also added providing access to the mapping
|
16
|
-
# hash, i.e. defining an attribute
|
17
|
-
#
|
18
|
-
#
|
16
|
+
# hash, i.e. defining an attribute +status+ will add a
|
17
|
+
# +statuses+ class method that returns the hash passed to the
|
18
|
+
# +:to+ option.
|
19
19
|
#
|
20
|
-
# Predicates are also added to each object for each attribute. If
|
21
|
-
#
|
22
|
-
# returns true if the attribute value is
|
20
|
+
# Predicates are also added to each object for each attribute. If
|
21
|
+
# you have a key +open+ in your mapping, your objects will have
|
22
|
+
# an +open?+ method that returns true if the attribute value is
|
23
|
+
# +:open+
|
23
24
|
#
|
24
|
-
#
|
25
|
+
# Each attribute you map generates an options method, suitable for
|
26
|
+
# use in form helpers. If you define an attribute +status+,
|
27
|
+
# instances of your model will have a +status_options+ method
|
28
|
+
# that returns a sorted array of arrays containing
|
29
|
+
# humanized-option-name/value pairs. By default this array is
|
30
|
+
# sorted by the option name (closed/open/etc.) If you'd rather
|
31
|
+
# sort by value, pass +false+ to the options method. This method
|
32
|
+
# also will set the selected option for records where the
|
33
|
+
# attribute is already set.
|
34
|
+
#
|
35
|
+
# @example Define a Ticket model with a status column:
|
25
36
|
# map_attribute :status, :to => {:open => 1, :closed => 2}
|
26
37
|
#
|
27
38
|
# @param [String] attribute the column to map on
|
28
39
|
# @param [Hash] options the options for this attribute
|
29
|
-
# @option options [Hash] :to The enumeration to use for this
|
40
|
+
# @option options [Hash] :to The enumeration to use for this
|
41
|
+
# attribute. See example above.
|
30
42
|
def map_attribute(attribute, options)
|
31
43
|
mapping = options[:to]
|
32
44
|
verify_existence_of attribute
|
33
45
|
add_accessor_for attribute, mapping
|
34
46
|
add_predicates_for attribute, mapping.keys
|
35
47
|
override attribute
|
48
|
+
add_options_helper_for attribute, mapping
|
36
49
|
end
|
37
50
|
|
38
51
|
private
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
52
|
+
|
53
|
+
def add_accessor_for(attribute, mapping)
|
54
|
+
class_eval(<<-EVAL)
|
55
|
+
class << self
|
56
|
+
def #{attribute.to_s.pluralize}
|
57
|
+
#{mapping.inspect}
|
45
58
|
end
|
46
|
-
EVAL
|
47
59
|
end
|
60
|
+
EVAL
|
61
|
+
end
|
48
62
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
RUBY
|
63
|
+
def add_predicates_for(attribute, names)
|
64
|
+
names.each do |name|
|
65
|
+
class_eval(<<-RUBY)
|
66
|
+
def #{name}?
|
67
|
+
self.#{attribute} == :#{name}
|
56
68
|
end
|
69
|
+
RUBY
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_options_helper_for(attribute, mapping)
|
74
|
+
class_eval(<<-EVAL, __FILE__, __LINE__)
|
75
|
+
def #{attribute}_options(sort_by_keys=true)
|
76
|
+
options = self.class.#{attribute.to_s.pluralize}.sort { |l, r|
|
77
|
+
sort_by_keys ? l.first.to_s <=> r.first.to_s : l.last <=> r.last
|
78
|
+
}.map { |f|
|
79
|
+
[f[0].to_s.humanize, f[0]]
|
80
|
+
}
|
81
|
+
self.#{attribute}.present? ? [options, {:selected => self.#{attribute}}] : [options]
|
57
82
|
end
|
83
|
+
EVAL
|
84
|
+
end
|
85
|
+
|
86
|
+
def override(*args)
|
87
|
+
override_getters *args
|
88
|
+
override_setters *args
|
89
|
+
end
|
90
|
+
|
91
|
+
def override_getters(attribute)
|
92
|
+
class_eval(<<-EVAL)
|
93
|
+
def #{attribute}
|
94
|
+
self.class.#{attribute.to_s.pluralize}.invert[read_attribute(:#{attribute})]
|
95
|
+
end
|
96
|
+
EVAL
|
97
|
+
end
|
98
|
+
|
99
|
+
def override_setters(attribute)
|
100
|
+
class_eval(<<-EVAL)
|
101
|
+
def #{attribute}=(raw_value)
|
102
|
+
value = resolve_value_of :#{attribute}, raw_value
|
103
|
+
write_attribute(:#{attribute}, value)
|
104
|
+
end
|
105
|
+
EVAL
|
106
|
+
end
|
107
|
+
|
108
|
+
def verify_existence_of(attribute)
|
109
|
+
raise ArgumentError, "`#{attribute}' is not an attribute of `#{self}'" unless column_names.include?(attribute.to_s)
|
110
|
+
end
|
58
111
|
|
59
|
-
def override(*args)
|
60
|
-
override_getters *args
|
61
|
-
override_setters *args
|
62
|
-
end
|
63
|
-
|
64
|
-
def override_getters(attribute)
|
65
|
-
class_eval(<<-EVAL)
|
66
|
-
def #{attribute}
|
67
|
-
self.class.#{attribute.to_s.pluralize}.invert[read_attribute(:#{attribute})]
|
68
|
-
end
|
69
|
-
EVAL
|
70
|
-
end
|
71
|
-
|
72
|
-
def override_setters(attribute)
|
73
|
-
class_eval(<<-EVAL)
|
74
|
-
def #{attribute}=(raw_value)
|
75
|
-
value = resolve_value_of :#{attribute}, raw_value
|
76
|
-
write_attribute(:#{attribute}, value)
|
77
|
-
end
|
78
|
-
EVAL
|
79
|
-
end
|
80
|
-
|
81
|
-
def verify_existence_of(attribute)
|
82
|
-
raise ArgumentError, "`#{attribute}' is not an attribute of `#{self}'" unless column_names.include?(attribute.to_s)
|
83
|
-
end
|
84
112
|
end
|
85
113
|
|
86
114
|
module InstanceMethods
|
115
|
+
|
87
116
|
private
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
117
|
+
|
118
|
+
def resolve_value_of(attribute, raw_value)
|
119
|
+
check_value = raw_value.is_a?(String) ? raw_value.to_sym : raw_value
|
120
|
+
mapping = self.class.send(attribute.to_s.pluralize)
|
121
|
+
raise ArgumentError, "`#{check_value}' not present in attribute mapping `#{mapping.inspect}'" unless mapping.to_a.flatten.include? check_value
|
122
|
+
mapping[check_value] || check_value
|
123
|
+
end
|
124
|
+
|
94
125
|
end
|
126
|
+
|
95
127
|
end
|
@@ -68,7 +68,34 @@ class AttributeMapperTest < Test::Unit::TestCase
|
|
68
68
|
ticket.status = 500
|
69
69
|
end
|
70
70
|
end
|
71
|
+
|
72
|
+
should "work with mass assignment" do
|
73
|
+
ticket.update_attributes(:status => :open, :name => 'Red is too red')
|
74
|
+
end
|
75
|
+
|
76
|
+
should "work with attr_accessible" do
|
77
|
+
new_ticket = Class.new(ActiveRecord::Base) do
|
78
|
+
set_table_name "tickets"
|
71
79
|
|
80
|
+
include AttributeMapper
|
81
|
+
map_attribute :status, :to => {:open => 1, :closed => 2}
|
82
|
+
|
83
|
+
attr_accessible :status
|
84
|
+
end
|
85
|
+
|
86
|
+
t = new_ticket.new
|
87
|
+
t.status = :open
|
88
|
+
|
89
|
+
assert_equal :open, t.status
|
90
|
+
end
|
91
|
+
|
92
|
+
should "provide a helper for forms" do
|
93
|
+
assert_equal [[["Closed", :closed], ["Open", :open]]], ticket.status_options
|
94
|
+
assert_equal [[["Open", :open], ["Closed", :closed]]], ticket.status_options(false)
|
95
|
+
ticket.status = :open
|
96
|
+
assert_equal [[["Open", :open], ["Closed", :closed]], {:selected => :open}], ticket.status_options(false)
|
97
|
+
end
|
98
|
+
|
72
99
|
end
|
73
100
|
|
74
101
|
#######
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attribute_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcel Molina Jr.
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2010-
|
14
|
+
date: 2010-02-23 00:00:00 -06:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|
@@ -26,6 +26,8 @@ extra_rdoc_files:
|
|
26
26
|
- README.md
|
27
27
|
files:
|
28
28
|
- .gitignore
|
29
|
+
- .kick
|
30
|
+
- HISTORY.rdoc
|
29
31
|
- LICENSE
|
30
32
|
- README.md
|
31
33
|
- Rakefile
|