Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
0728d3b5
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0728d3b5
编写于
6月 16, 2014
作者:
R
Rafael Mendonça França
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #15760 from sgrif/sg-decorate-matching
Promote time zone aware attributes to a first class type decorator
上级
88714deb
74af9f7f
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
57 addition
and
32 deletion
+57
-32
activerecord/lib/active_record/attribute_decorators.rb
activerecord/lib/active_record/attribute_decorators.rb
+26
-10
activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
...b/active_record/attribute_methods/time_zone_conversion.rb
+6
-1
activerecord/lib/active_record/base.rb
activerecord/lib/active_record/base.rb
+2
-2
activerecord/lib/active_record/model_schema.rb
activerecord/lib/active_record/model_schema.rb
+1
-19
activerecord/test/cases/attribute_decorators_test.rb
activerecord/test/cases/attribute_decorators_test.rb
+21
-0
activerecord/test/cases/attribute_methods/read_test.rb
activerecord/test/cases/attribute_methods/read_test.rb
+1
-0
未找到文件。
activerecord/lib/active_record/attribute_decorators.rb
浏览文件 @
0728d3b5
...
...
@@ -9,18 +9,24 @@ module AttributeDecorators # :nodoc:
module
ClassMethods
def
decorate_attribute_type
(
column_name
,
decorator_name
,
&
block
)
matcher
=
->
(
name
,
_
)
{
name
==
column_name
.
to_s
}
key
=
"_
#{
column_name
}
_
#{
decorator_name
}
"
decorate_matching_attribute_types
(
matcher
,
key
,
&
block
)
end
def
decorate_matching_attribute_types
(
matcher
,
decorator_name
,
&
block
)
clear_caches_calculated_from_columns
column_name
=
column
_name
.
to_s
decorator_name
=
decorator
_name
.
to_s
# Create new hashes so we don't modify parent classes
self
.
attribute_type_decorations
=
attribute_type_decorations
.
merge
(
column_name
,
decorator_name
,
block
)
self
.
attribute_type_decorations
=
attribute_type_decorations
.
merge
(
decorator_name
=>
[
matcher
,
block
]
)
end
private
def
add_user_provided_columns
(
*
)
super
.
map
do
|
column
|
decorated_type
=
attribute_type_decorations
.
apply
(
column
.
name
,
column
.
cast_type
)
decorated_type
=
attribute_type_decorations
.
apply
(
self
,
column
.
name
,
column
.
cast_type
)
column
.
with_type
(
decorated_type
)
end
end
...
...
@@ -29,22 +35,32 @@ def add_user_provided_columns(*)
class
TypeDecorator
delegate
:clear
,
to: :@decorations
def
initialize
(
decorations
=
Hash
.
new
({})
)
def
initialize
(
decorations
=
{}
)
@decorations
=
decorations
end
def
merge
(
attribute_name
,
decorator_name
,
block
)
decorations_for_attribute
=
@decorations
[
attribute_name
]
new_decorations
=
decorations_for_attribute
.
merge
(
decorator_name
.
to_s
=>
block
)
TypeDecorator
.
new
(
@decorations
.
merge
(
attribute_name
=>
new_decorations
))
def
merge
(
*
args
)
TypeDecorator
.
new
(
@decorations
.
merge
(
*
args
))
end
def
apply
(
attribute_
name
,
type
)
decorations
=
@decorations
[
attribute_name
].
values
def
apply
(
context
,
name
,
type
)
decorations
=
decorators_for
(
context
,
name
,
type
)
decorations
.
inject
(
type
)
do
|
new_type
,
block
|
block
.
call
(
new_type
)
end
end
private
def
decorators_for
(
context
,
name
,
type
)
matching
(
context
,
name
,
type
).
map
(
&
:last
)
end
def
matching
(
context
,
name
,
type
)
@decorations
.
values
.
select
do
|
(
matcher
,
_
)
|
context
.
instance_exec
(
name
,
type
,
&
matcher
)
end
end
end
end
end
activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
浏览文件 @
0728d3b5
module
ActiveRecord
module
AttributeMethods
module
TimeZoneConversion
class
T
ype
<
SimpleDelegator
# :nodoc:
class
T
imeZoneConverter
<
SimpleDelegator
# :nodoc:
def
type_cast_from_database
(
value
)
convert_time_to_time_zone
(
super
)
end
...
...
@@ -33,6 +33,11 @@ def convert_time_to_time_zone(value)
class_attribute
:skip_time_zone_conversion_for_attributes
,
instance_writer:
false
self
.
skip_time_zone_conversion_for_attributes
=
[]
matcher
=
->
(
name
,
type
)
{
create_time_zone_conversion_attribute?
(
name
,
type
)
}
decorate_matching_attribute_types
(
matcher
,
:_time_zone_conversion
)
do
|
type
|
TimeZoneConverter
.
new
(
type
)
end
end
module
ClassMethods
...
...
activerecord/lib/active_record/base.rb
浏览文件 @
0728d3b5
...
...
@@ -310,6 +310,8 @@ class Base
include
CounterCache
include
Locking
::
Optimistic
include
Locking
::
Pessimistic
include
Attributes
include
AttributeDecorators
include
AttributeMethods
include
Callbacks
include
Timestamp
...
...
@@ -323,8 +325,6 @@ class Base
include
Reflection
include
Serialization
include
Store
include
Attributes
include
AttributeDecorators
end
ActiveSupport
.
run_load_hooks
(
:active_record
,
Base
)
...
...
activerecord/lib/active_record/model_schema.rb
浏览文件 @
0728d3b5
...
...
@@ -220,27 +220,13 @@ def table_exists?
end
def
column_types
# :nodoc:
@column_types
||=
decorate_types
(
build_types_hash
)
@column_types
||=
Hash
[
columns
.
map
{
|
column
|
[
column
.
name
,
column
.
cast_type
]
}]
end
def
type_for_attribute
(
attr_name
)
# :nodoc:
column_types
.
fetch
(
attr_name
)
{
Type
::
Value
.
new
}
end
def
decorate_types
(
types
)
# :nodoc:
return
if
types
.
empty?
@time_zone_column_names
||=
self
.
columns_hash
.
find_all
do
|
name
,
col
|
create_time_zone_conversion_attribute?
(
name
,
col
)
end
.
map!
(
&
:first
)
@time_zone_column_names
.
each
do
|
name
|
types
[
name
]
=
AttributeMethods
::
TimeZoneConversion
::
Type
.
new
(
types
[
name
])
end
types
end
# Returns a hash where the keys are column names and the values are
# default values when instantiating the AR object for this table.
def
column_defaults
...
...
@@ -335,10 +321,6 @@ def compute_table_name
base
.
table_name
end
end
def
build_types_hash
Hash
[
columns
.
map
{
|
column
|
[
column
.
name
,
column
.
cast_type
]
}]
end
end
end
end
activerecord/test/cases/attribute_decorators_test.rb
浏览文件 @
0728d3b5
...
...
@@ -110,5 +110,26 @@ def type_cast_from_user(value)
assert_equal
'whatever decorated!'
,
column
.
default
end
class
Multiplier
<
SimpleDelegator
def
type_cast_from_user
(
value
)
return
if
value
.
nil?
value
*
2
end
alias
type_cast_from_database
type_cast_from_user
end
test
"decorating with a proc"
do
Model
.
attribute
:an_int
,
Type
::
Integer
.
new
type_is_integer
=
proc
{
|
_
,
type
|
type
.
type
==
:integer
}
Model
.
decorate_matching_attribute_types
type_is_integer
,
:multiplier
do
|
type
|
Multiplier
.
new
(
type
)
end
model
=
Model
.
new
(
a_string:
'whatever'
,
an_int:
1
)
assert_equal
'whatever'
,
model
.
a_string
assert_equal
2
,
model
.
an_int
end
end
end
activerecord/test/cases/attribute_methods/read_test.rb
浏览文件 @
0728d3b5
...
...
@@ -12,6 +12,7 @@ def setup
@klass
=
Class
.
new
do
def
self
.
superclass
;
Base
;
end
def
self
.
base_class
;
self
;
end
def
self
.
decorate_matching_attribute_types
(
*
);
end
include
ActiveRecord
::
AttributeMethods
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录