symbolize 3.3.0pre → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|