symbolize 3.3.0pre → 4.0.1
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/README.rdoc +51 -35
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/lib/symbolize/active_record.rb +194 -0
- data/lib/symbolize/mongoid.rb +172 -0
- data/lib/symbolize/railtie.rb +11 -10
- data/lib/symbolize.rb +3 -190
- data/spec/locales/pt.yml +15 -0
- data/spec/spec_helper.rb +0 -13
- data/spec/spec_helper_ar.rb +17 -0
- data/spec/spec_helper_mongoid.rb +9 -0
- data/spec/symbolize/active_record_spec.rb +440 -0
- data/spec/symbolize/mongoid_spec.rb +350 -0
- data/spec/symbolize_spec.rb +0 -430
- data/symbolize.gemspec +10 -6
- metadata +14 -10
- data/init.rb +0 -1
- data/rails/init.rb +0 -2
data/lib/symbolize.rb
CHANGED
@@ -1,193 +1,6 @@
|
|
1
1
|
module Symbolize
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
# Require a specific adapter
|
3
|
+
# symbolize/mongoid
|
4
|
+
# symbolize/active_record
|
5
5
|
|
6
|
-
# Symbolize ActiveRecord attributes. Add
|
7
|
-
# symbolize :attr_name
|
8
|
-
# to your model class, to make an attribute return symbols instead of
|
9
|
-
# string values. Setting such an attribute will accept symbols as well
|
10
|
-
# as strings. In the database, the symbolized attribute should have
|
11
|
-
# the column-type :string.
|
12
|
-
#
|
13
|
-
# Example:
|
14
|
-
# class User < ActiveRecord::Base
|
15
|
-
# symbolize :gender, :in => [:female, :male]
|
16
|
-
# symbolize :so, :in => {
|
17
|
-
# :linux => "Linux",
|
18
|
-
# :mac => "Mac OS X"
|
19
|
-
# }
|
20
|
-
# symbolize :gui, , :in => [:gnome, :kde, :xfce], :allow_blank => true
|
21
|
-
# symbolize :browser, :in => [:firefox, :opera], :i18n => false
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# It will automattically lookup for i18n:
|
25
|
-
#
|
26
|
-
# activerecord:
|
27
|
-
# attributes:
|
28
|
-
# user:
|
29
|
-
# enums:
|
30
|
-
# gender:
|
31
|
-
# female: Girl
|
32
|
-
# male: Boy
|
33
|
-
#
|
34
|
-
# You can skip i18n lookup with :i18n => false
|
35
|
-
# symbolize :gender, :in => [:female, :male], :i18n => false
|
36
|
-
#
|
37
|
-
# Its possible to use boolean fields also.
|
38
|
-
# symbolize :switch, :in => [true, false]
|
39
|
-
#
|
40
|
-
# ...
|
41
|
-
# switch:
|
42
|
-
# "true": On
|
43
|
-
# "false": Off
|
44
|
-
# "nil": Unknown
|
45
|
-
#
|
46
|
-
module ClassMethods
|
47
|
-
# Specifies that values of the given attributes should be returned
|
48
|
-
# as symbols. The table column should be created of type string.
|
49
|
-
|
50
|
-
def symbolize *attr_names
|
51
|
-
configuration = {}
|
52
|
-
configuration.update(attr_names.extract_options!)
|
53
|
-
|
54
|
-
enum = configuration[:in] || configuration[:within]
|
55
|
-
i18n = configuration.delete(:i18n).nil? && !enum.instance_of?(Hash) && enum ? true : configuration[:i18n]
|
56
|
-
scopes = configuration.delete :scopes
|
57
|
-
methods = configuration.delete :methods
|
58
|
-
capitalize = configuration.delete :capitalize
|
59
|
-
validation = configuration.delete(:validation) != false
|
60
|
-
default_option = configuration.delete :default
|
61
|
-
|
62
|
-
unless enum.nil?
|
63
|
-
# Little monkeypatching, <1.8 Hashes aren't ordered.
|
64
|
-
hsh = RUBY_VERSION > '1.9' || !defined?("ActiveSupport") ? Hash : ActiveSupport::OrderedHash
|
65
|
-
|
66
|
-
attr_names.each do |attr_name|
|
67
|
-
attr_name = attr_name.to_s
|
68
|
-
const = "#{attr_name}_values"
|
69
|
-
if enum.is_a?(Hash)
|
70
|
-
values = enum
|
71
|
-
else
|
72
|
-
values = hsh.new
|
73
|
-
enum.map do |val|
|
74
|
-
key = val.respond_to?(:to_sym) ? val.to_sym : val
|
75
|
-
values[key] = capitalize ? val.to_s.capitalize : val.to_s
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# Get the values of :in
|
80
|
-
const_set const.upcase, values unless const_defined? const.upcase
|
81
|
-
ev = if i18n
|
82
|
-
# This one is a dropdown helper
|
83
|
-
code = "#{const.upcase}.map { |k,v| [I18n.translate(\"activerecord.attributes.\#{ActiveSupport::Inflector.underscore(self)}.enums.#{attr_name}.\#{k}\"), k] }" #.to_sym rescue nila
|
84
|
-
"def self.get_#{const}; #{code}; end;"
|
85
|
-
else
|
86
|
-
"def self.get_#{const}; #{const.upcase}.map(&:reverse); end"
|
87
|
-
end
|
88
|
-
class_eval(ev)
|
89
|
-
|
90
|
-
if methods
|
91
|
-
values.each do |value|
|
92
|
-
define_method("#{value[0]}?") do
|
93
|
-
self.send(attr_name) == value[0]
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
if scopes
|
99
|
-
scope_comm = lambda { |*args| ActiveRecord::VERSION::MAJOR >= 3 ? scope(*args) : named_scope(*args)}
|
100
|
-
values.each do |value|
|
101
|
-
if value[0].respond_to?(:to_sym)
|
102
|
-
scope_comm.call value[0].to_sym, :conditions => { attr_name => value[0].to_sym }
|
103
|
-
elsif ActiveRecord::VERSION::STRING <= "3.0"
|
104
|
-
if value[0] == true || value[0] == false
|
105
|
-
scope_comm.call "with_#{attr_name}".to_sym, :conditions => { attr_name => '1' }
|
106
|
-
scope_comm.call "without_#{attr_name}".to_sym, :conditions => { attr_name => '0' }
|
107
|
-
|
108
|
-
scope_comm.call attr_name.to_sym, :conditions => { attr_name => '1' }
|
109
|
-
scope_comm.call "not_#{attr_name}".to_sym, :conditions => { attr_name => '0' }
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
if validation
|
117
|
-
class_eval "validates_inclusion_of :#{attr_names.join(', :')}, #{configuration.inspect}"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
attr_names.each do |attr_name|
|
122
|
-
|
123
|
-
if default_option
|
124
|
-
class_eval("def #{attr_name}; read_and_symbolize_attribute('#{attr_name}') || :#{default_option}; end")
|
125
|
-
class_eval("def #{attr_name}= (value); write_symbolized_attribute('#{attr_name}', value); end")
|
126
|
-
class_eval("def set_default_for_attr_#{attr_name}; self[:#{attr_name}] ||= :#{default_option}; end")
|
127
|
-
class_eval("before_save :set_default_for_attr_#{attr_name}")
|
128
|
-
else
|
129
|
-
class_eval("def #{attr_name}; read_and_symbolize_attribute('#{attr_name}'); end")
|
130
|
-
class_eval("def #{attr_name}= (value); write_symbolized_attribute('#{attr_name}', value); end")
|
131
|
-
end
|
132
|
-
if i18n
|
133
|
-
class_eval("def #{attr_name}_text; read_i18n_attribute('#{attr_name}'); end")
|
134
|
-
elsif enum
|
135
|
-
class_eval("def #{attr_name}_text; #{attr_name.to_s.upcase}_VALUES[#{attr_name}]; end")
|
136
|
-
else
|
137
|
-
class_eval("def #{attr_name}_text; #{attr_name}.to_s; end")
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
# String becomes symbol, booleans string and nil nil.
|
144
|
-
def symbolize_attribute attr
|
145
|
-
case attr
|
146
|
-
when String then attr.empty? ? nil : attr.to_sym
|
147
|
-
when Symbol, TrueClass, FalseClass, Numeric then attr
|
148
|
-
else nil
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
# Return an attribute's value as a symbol or nil
|
153
|
-
def read_and_symbolize_attribute attr_name
|
154
|
-
symbolize_attribute self[attr_name]
|
155
|
-
end
|
156
|
-
|
157
|
-
# Return an attribute's i18n
|
158
|
-
def read_i18n_attribute attr_name
|
159
|
-
return nil unless attr = read_attribute(attr_name)
|
160
|
-
I18n.translate("activerecord.attributes.#{ActiveSupport::Inflector.underscore(self.class)}.enums.#{attr_name}.#{attr}") #.to_sym rescue nila
|
161
|
-
end
|
162
|
-
|
163
|
-
# Write a symbolized value. Watch out for booleans.
|
164
|
-
def write_symbolized_attribute attr_name, value
|
165
|
-
val = { "true" => true, "false" => false }[value]
|
166
|
-
val = symbolize_attribute(value) if val.nil?
|
167
|
-
|
168
|
-
self[attr_name] = val #.to_s # rails 3.1 fix
|
169
|
-
end
|
170
6
|
end
|
171
|
-
|
172
|
-
# The Symbol class is extended by method quoted_id which returns a string.
|
173
|
-
# The idea behind this is, that symbols are converted to plain strings
|
174
|
-
# when being quoted by ActiveRecord::ConnectionAdapters::Quoting#quote.
|
175
|
-
# This makes it possible to work with symbolized attibutes in sql conditions.
|
176
|
-
# E.g. validates_uniqueness_of could not use :scope with a symbolized
|
177
|
-
# attribute, because AR quotes it to YAML:
|
178
|
-
# "... AND status = '--- :active\n'"
|
179
|
-
# Having support for quoted_id in Symbol, makes AR quoting symbols correctly:
|
180
|
-
# "... AND status = 'active'"
|
181
|
-
# NOTE: Normally quoted_id should be implemented as a singleton method
|
182
|
-
# only used on symbols returned by read_and_symbolize_attribute,
|
183
|
-
# but unfortunately this is not possible since Symbol is an immediate
|
184
|
-
# value and therefore does not support singleton methods.
|
185
|
-
# class Symbol
|
186
|
-
# def quoted_id
|
187
|
-
# # A symbol can contain almost every character (even a backslash or an
|
188
|
-
# # apostrophe), so make sure to properly quote the string value here.
|
189
|
-
# "'#{ActiveRecord::Base.connection.quote_string(self.to_s)}'"
|
190
|
-
# end
|
191
|
-
# end
|
192
|
-
|
193
|
-
ActiveRecord::Base.send(:include, Symbolize) if ActiveRecord::VERSION::MAJOR >= 3
|
data/spec/locales/pt.yml
CHANGED
@@ -14,3 +14,18 @@ pt:
|
|
14
14
|
kind:
|
15
15
|
magic: Mágica
|
16
16
|
agility: Agilidade
|
17
|
+
models:
|
18
|
+
attributes:
|
19
|
+
user:
|
20
|
+
enums:
|
21
|
+
language:
|
22
|
+
pt: Português
|
23
|
+
en: Inglês
|
24
|
+
sex:
|
25
|
+
"true": Feminino
|
26
|
+
"false": Masculino
|
27
|
+
user_skill:
|
28
|
+
enums:
|
29
|
+
kind:
|
30
|
+
magic: Mágica
|
31
|
+
agility: Agilidade
|
data/spec/spec_helper.rb
CHANGED
@@ -8,23 +8,10 @@ require 'pry'
|
|
8
8
|
|
9
9
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
10
10
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
11
|
-
require 'active_record'
|
12
11
|
require 'action_controller'
|
13
12
|
require 'action_view'
|
14
|
-
require 'symbolize'
|
15
|
-
require File.join(File.dirname(__FILE__), '..', 'init')
|
16
|
-
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") #'postgresql', :database => 'symbolize_test', :username => 'postgres')
|
17
13
|
|
18
|
-
if ActiveRecord::VERSION::STRING >= "3.1"
|
19
|
-
ActiveRecord::Migrator.migrate("spec/db")
|
20
|
-
else
|
21
|
-
require "db/001_create_testing_structure"
|
22
|
-
CreateTestingStructure.migrate(:up)
|
23
|
-
end
|
24
14
|
|
25
15
|
I18n.load_path += Dir[File.join(File.dirname(__FILE__), "locales", "*.{rb,yml}")]
|
26
16
|
I18n.default_locale = "pt"
|
27
17
|
|
28
|
-
puts "Running AR #{ActiveRecord::VERSION::STRING}"
|
29
|
-
# Spec::Runner.configure do |config|
|
30
|
-
# end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
require 'symbolize/active_record'
|
5
|
+
|
6
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") #'postgresql', :database => 'symbolize_test', :username => 'postgres')
|
7
|
+
|
8
|
+
if ActiveRecord::VERSION::STRING >= "3.1"
|
9
|
+
ActiveRecord::Migrator.migrate("spec/db")
|
10
|
+
else
|
11
|
+
require "db/001_create_testing_structure"
|
12
|
+
CreateTestingStructure.migrate(:up)
|
13
|
+
end
|
14
|
+
|
15
|
+
puts "Running AR #{ActiveRecord::VERSION::STRING}"
|
16
|
+
# Spec::Runner.configure do |config|
|
17
|
+
# end
|