Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
abeff5e6
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,发现更多精彩内容 >>
提交
abeff5e6
编写于
10月 24, 2013
作者:
Y
Yves Senn
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #12490 from senny/store_accessor_hstore_bug
ActiveRecord Store works with PG `hstore` columns
上级
7160ffbe
0492ea6d
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
127 addition
and
14 deletion
+127
-14
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+11
-0
activerecord/lib/active_record/attribute_methods/serialization.rb
...cord/lib/active_record/attribute_methods/serialization.rb
+4
-0
activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
...d/lib/active_record/connection_adapters/postgresql/oid.rb
+8
-0
activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
...b/active_record/connection_adapters/postgresql_adapter.rb
+4
-0
activerecord/lib/active_record/store.rb
activerecord/lib/active_record/store.rb
+49
-14
activerecord/test/cases/adapters/postgresql/hstore_test.rb
activerecord/test/cases/adapters/postgresql/hstore_test.rb
+21
-0
activerecord/test/cases/adapters/postgresql/json_test.rb
activerecord/test/cases/adapters/postgresql/json_test.rb
+18
-0
activerecord/test/cases/store_test.rb
activerecord/test/cases/store_test.rb
+12
-0
未找到文件。
activerecord/CHANGELOG.md
浏览文件 @
abeff5e6
*
`ActiveRecord::Store`
works together with PG
`hstore`
columns.
Fixes #12452.
*Yves Senn*
*
Fix bug where
`ActiveRecord::Store`
used a global
`Hash`
to keep track of
all registered
`stored_attributes`
. Now every subclass of
`ActiveRecord::Base`
has it's own
`Hash`
.
*Yves Senn*
*
Save
`has_one`
association when primary key is manually set.
Fixes #12302.
...
...
activerecord/lib/active_record/attribute_methods/serialization.rb
浏览文件 @
abeff5e6
...
...
@@ -66,6 +66,10 @@ def type_cast(value)
def
type
@column
.
type
end
def
accessor
ActiveRecord
::
Store
::
IndifferentHashAccessor
end
end
class
Attribute
<
Struct
.
new
(
:coder
,
:value
,
:state
)
# :nodoc:
...
...
activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
浏览文件 @
abeff5e6
...
...
@@ -234,6 +234,10 @@ def type_cast(value)
ConnectionAdapters
::
PostgreSQLColumn
.
string_to_hstore
value
end
def
accessor
ActiveRecord
::
Store
::
StringKeyedHashAccessor
end
end
class
Cidr
<
Type
...
...
@@ -250,6 +254,10 @@ def type_cast(value)
ConnectionAdapters
::
PostgreSQLColumn
.
string_to_json
value
end
def
accessor
ActiveRecord
::
Store
::
StringKeyedHashAccessor
end
end
class
TypeMap
...
...
activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
浏览文件 @
abeff5e6
...
...
@@ -148,6 +148,10 @@ def type_cast(value)
@oid_type
.
type_cast
value
end
def
accessor
@oid_type
.
accessor
end
private
def
has_default_function?
(
default_value
,
default
)
...
...
activerecord/lib/active_record/store.rb
浏览文件 @
abeff5e6
...
...
@@ -86,6 +86,9 @@ def store_accessor(store_attribute, *keys)
end
end
# assign new store attribute and create new hash to ensure that each class in the hierarchy
# has its own hash of stored attributes.
self
.
stored_attributes
=
{}
if
self
.
stored_attributes
.
blank?
self
.
stored_attributes
[
store_attribute
]
||=
[]
self
.
stored_attributes
[
store_attribute
]
|=
keys
end
...
...
@@ -101,26 +104,58 @@ def _store_accessors_module
protected
def
read_store_attribute
(
store_attribute
,
key
)
a
ttribute
=
initialize_store_attribute
(
store_attribute
)
a
ttribute
[
key
]
a
ccessor
=
store_accessor_for
(
store_attribute
)
a
ccessor
.
read
(
self
,
store_attribute
,
key
)
end
def
write_store_attribute
(
store_attribute
,
key
,
value
)
attribute
=
initialize_store_attribute
(
store_attribute
)
if
value
!=
attribute
[
key
]
send
:"
#{
store_attribute
}
_will_change!"
attribute
[
key
]
=
value
end
accessor
=
store_accessor_for
(
store_attribute
)
accessor
.
write
(
self
,
store_attribute
,
key
,
value
)
end
private
def
initialize_store_attribute
(
store_attribute
)
attribute
=
send
(
store_attribute
)
unless
attribute
.
is_a?
(
ActiveSupport
::
HashWithIndifferentAccess
)
attribute
=
IndifferentCoder
.
as_indifferent_hash
(
attribute
)
send
:"
#{
store_attribute
}
="
,
attribute
def
store_accessor_for
(
store_attribute
)
@column_types
[
store_attribute
.
to_s
].
accessor
end
class
HashAccessor
def
self
.
read
(
object
,
attribute
,
key
)
prepare
(
object
,
attribute
)
object
.
public_send
(
attribute
)[
key
]
end
def
self
.
write
(
object
,
attribute
,
key
,
value
)
prepare
(
object
,
attribute
)
if
value
!=
read
(
object
,
attribute
,
key
)
object
.
public_send
:"
#{
attribute
}
_will_change!"
object
.
public_send
(
attribute
)[
key
]
=
value
end
end
def
self
.
prepare
(
object
,
attribute
)
object
.
public_send
:"
#{
attribute
}
="
,
{}
unless
object
.
send
(
attribute
)
end
end
class
StringKeyedHashAccessor
<
HashAccessor
def
self
.
read
(
object
,
attribute
,
key
)
super
object
,
attribute
,
key
.
to_s
end
def
self
.
write
(
object
,
attribute
,
key
,
value
)
super
object
,
attribute
,
key
.
to_s
,
value
end
end
class
IndifferentHashAccessor
<
ActiveRecord
::
Store
::
HashAccessor
def
self
.
prepare
(
object
,
store_attribute
)
attribute
=
object
.
send
(
store_attribute
)
unless
attribute
.
is_a?
(
ActiveSupport
::
HashWithIndifferentAccess
)
attribute
=
IndifferentCoder
.
as_indifferent_hash
(
attribute
)
object
.
send
:"
#{
store_attribute
}
="
,
attribute
end
attribute
end
attribute
end
class
IndifferentCoder
# :nodoc:
...
...
@@ -138,7 +173,7 @@ def dump(obj)
end
def
load
(
yaml
)
self
.
class
.
as_indifferent_hash
@coder
.
load
(
yaml
)
self
.
class
.
as_indifferent_hash
(
@coder
.
load
(
yaml
)
)
end
def
self
.
as_indifferent_hash
(
obj
)
...
...
activerecord/test/cases/adapters/postgresql/hstore_test.rb
浏览文件 @
abeff5e6
...
...
@@ -7,6 +7,8 @@
class
PostgresqlHstoreTest
<
ActiveRecord
::
TestCase
class
Hstore
<
ActiveRecord
::
Base
self
.
table_name
=
'hstores'
store_accessor
:settings
,
:language
,
:timezone
end
def
setup
...
...
@@ -26,6 +28,7 @@ def setup
@connection
.
transaction
do
@connection
.
create_table
(
'hstores'
)
do
|
t
|
t
.
hstore
'tags'
,
:default
=>
''
t
.
hstore
'settings'
end
end
@column
=
Hstore
.
columns
.
find
{
|
c
|
c
.
name
==
'tags'
}
...
...
@@ -90,6 +93,24 @@ def test_type_cast_hstore
assert_equal
({
'c'
=>
'}'
,
'"a"'
=>
'b "a b'
},
@column
.
type_cast
(
%q(c=>"}", "\"a\""=>"b \"a b")
))
end
def
test_with_store_accessors
x
=
Hstore
.
new
(
language:
"fr"
,
timezone:
"GMT"
)
assert_equal
"fr"
,
x
.
language
assert_equal
"GMT"
,
x
.
timezone
x
.
save!
x
=
Hstore
.
first
assert_equal
"fr"
,
x
.
language
assert_equal
"GMT"
,
x
.
timezone
x
.
language
=
"de"
x
.
save!
x
=
Hstore
.
first
assert_equal
"de"
,
x
.
language
assert_equal
"GMT"
,
x
.
timezone
end
def
test_gen1
assert_equal
(
%q(" "=>"")
,
@column
.
class
.
hstore_to_string
({
' '
=>
''
}))
end
...
...
activerecord/test/cases/adapters/postgresql/json_test.rb
浏览文件 @
abeff5e6
...
...
@@ -7,6 +7,8 @@
class
PostgresqlJSONTest
<
ActiveRecord
::
TestCase
class
JsonDataType
<
ActiveRecord
::
Base
self
.
table_name
=
'json_data_type'
store_accessor
:settings
,
:resolution
end
def
setup
...
...
@@ -15,6 +17,7 @@ def setup
@connection
.
transaction
do
@connection
.
create_table
(
'json_data_type'
)
do
|
t
|
t
.
json
'payload'
,
:default
=>
{}
t
.
json
'settings'
end
end
rescue
ActiveRecord
::
StatementInvalid
...
...
@@ -96,4 +99,19 @@ def test_rewrite_array_json_value
x
.
payload
=
[
'v1'
,
{
'k2'
=>
'v2'
},
'v3'
]
assert
x
.
save!
end
def
test_with_store_accessors
x
=
JsonDataType
.
new
(
resolution:
"320×480"
)
assert_equal
"320×480"
,
x
.
resolution
x
.
save!
x
=
JsonDataType
.
first
assert_equal
"320×480"
,
x
.
resolution
x
.
resolution
=
"640×1136"
x
.
save!
x
=
JsonDataType
.
first
assert_equal
"640×1136"
,
x
.
resolution
end
end
activerecord/test/cases/store_test.rb
浏览文件 @
abeff5e6
...
...
@@ -150,4 +150,16 @@ class StoreTest < ActiveRecord::TestCase
test
"all stored attributes are returned"
do
assert_equal
[
:color
,
:homepage
,
:favorite_food
],
Admin
::
User
.
stored_attributes
[
:settings
]
end
test
"stored_attributes are tracked per class"
do
first_model
=
Class
.
new
(
ActiveRecord
::
Base
)
do
store_accessor
:data
,
:color
end
second_model
=
Class
.
new
(
ActiveRecord
::
Base
)
do
store_accessor
:data
,
:width
,
:height
end
assert_equal
[
:color
],
first_model
.
stored_attributes
[
:data
]
assert_equal
[
:width
,
:height
],
second_model
.
stored_attributes
[
:data
]
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录