Rails Ember 强参数说明
Rails Ember strong parameters clarification
如果我有一个 Book
实体和一个 Chapter
实体,我的 chapters_controller
的强参数应该是什么?
注:我用的是JSONAPI.
在我的chapters_controller
中,我的强参数应该是:
:title, :order, :content, :published, :book, :picture
或者应该是:
:title, :order, :content, :published, :book_id, :picture
如果我使用:book
而不是:book_id
,那么在我的Ember应用程序中,当我去创建一个新章节时,我能够创建它并关联这个章节到父书,但是,我的测试失败了:
def setup
@book = books(:one)
@new_chapter = {
title: "Cooked Wolf Dinner",
order: 4,
published: false,
content: "The bad wolf was very mad. He was determined to eat the little pig so he climbed down the chimney.",
book: @book
}
end
def format_jsonapi(params)
params = {
data: {
type: "books",
attributes: params
}
}
return params
end
...
test "chapter create - should create new chapter assigned to an existing book" do
assert_difference "Chapter.count", +1 do
post chapters_path, params: format_jsonapi(@new_chapter), headers: user_authenticated_header(@jim)
assert_response :created
json = JSON.parse(response.body)
attributes = json['data']['attributes']
assert_equal "Cooked Wolf Dinner", attributes['title']
assert_equal 4, attributes['order']
assert_equal false, attributes['published']
assert_equal @book.title, attributes['book']['title']
end
end
我的控制台出现错误,提示关联类型不匹配。
也许我的台词是:
book: @book
是它的原因吗?
不管怎样,直觉告诉我应该在 chapters_controller
强参数中使用 :book
。
只是我的测试没有通过,我不确定如何编写参数散列以使我的测试通过。
经过几个小时的努力并查看 JSON API 文档:
http://jsonapi.org/format/#crud-creating
我注意到了,为了使用 JSON API 设置与实体的 belongsTo 关系,我们需要这样做:
POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "photos",
"attributes": {
"title": "Ember Hamster",
"src": "http://example.com/images/productivity.png"
},
"relationships": {
"photographer": {
"data": { "type": "people", "id": "9" }
}
}
}
}
这也让我解决了另一个我过去无法解决的问题。可以创建多种类型的书籍。
JSON API 结构,用于将 Genre
的数组分配给 Book
实体,我们在关系部分用数据数组替换数据哈希,如这个:
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
另外,在我的控制器中,任何像这样的强参数:
:title, :content, genre_ids: []
变成
:title, :content, :genres
遵守JSONAPI.
所以对于我的新测试样本数据,我现在有:
def setup
...
@new_chapter = {
title: "Cooked Wolf Dinner",
order: 4,
published: false,
content: "The bad wolf was very mad. He was determined to eat the little pig so he climbed down the chimney.",
}
...
end
def format_jsonapi(params, book_id = nil)
params = {
data: {
type: "chapters",
attributes: params
}
}
if book_id != nil
params[:data][:relationships] = {
book: {
data: {
type: "books",
id: book_id
}
}
}
end
return params
end
关于关系设置的特别说明-只有在有关系的情况下才将relationships
添加到params
,否则,将其设置为nil就是告诉JSON API到删除该关系,而不是忽略它。
然后我可以像这样调用我的测试:
test "chapter create - should create new chapter assigned to an existing book" do
assert_difference "Chapter.count", +1 do
post chapters_path, params: format_jsonapi(@new_chapter, @book.id), headers: user_authenticated_header(@jim)
assert_response :created
json = JSON.parse(response.body)
attributes = json['data']['attributes']
assert_equal "Cooked Wolf Dinner", attributes['title']
assert_equal 4, attributes['order']
assert_equal false, attributes['published']
assert_equal @book.id, json['data']['relationships']['book']['data']['id'].to_i
end
如果我有一个 Book
实体和一个 Chapter
实体,我的 chapters_controller
的强参数应该是什么?
注:我用的是JSONAPI.
在我的chapters_controller
中,我的强参数应该是:
:title, :order, :content, :published, :book, :picture
或者应该是:
:title, :order, :content, :published, :book_id, :picture
如果我使用:book
而不是:book_id
,那么在我的Ember应用程序中,当我去创建一个新章节时,我能够创建它并关联这个章节到父书,但是,我的测试失败了:
def setup
@book = books(:one)
@new_chapter = {
title: "Cooked Wolf Dinner",
order: 4,
published: false,
content: "The bad wolf was very mad. He was determined to eat the little pig so he climbed down the chimney.",
book: @book
}
end
def format_jsonapi(params)
params = {
data: {
type: "books",
attributes: params
}
}
return params
end
...
test "chapter create - should create new chapter assigned to an existing book" do
assert_difference "Chapter.count", +1 do
post chapters_path, params: format_jsonapi(@new_chapter), headers: user_authenticated_header(@jim)
assert_response :created
json = JSON.parse(response.body)
attributes = json['data']['attributes']
assert_equal "Cooked Wolf Dinner", attributes['title']
assert_equal 4, attributes['order']
assert_equal false, attributes['published']
assert_equal @book.title, attributes['book']['title']
end
end
我的控制台出现错误,提示关联类型不匹配。
也许我的台词是:
book: @book
是它的原因吗?
不管怎样,直觉告诉我应该在 chapters_controller
强参数中使用 :book
。
只是我的测试没有通过,我不确定如何编写参数散列以使我的测试通过。
经过几个小时的努力并查看 JSON API 文档:
http://jsonapi.org/format/#crud-creating
我注意到了,为了使用 JSON API 设置与实体的 belongsTo 关系,我们需要这样做:
POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "photos",
"attributes": {
"title": "Ember Hamster",
"src": "http://example.com/images/productivity.png"
},
"relationships": {
"photographer": {
"data": { "type": "people", "id": "9" }
}
}
}
}
这也让我解决了另一个我过去无法解决的问题。可以创建多种类型的书籍。
JSON API 结构,用于将 Genre
的数组分配给 Book
实体,我们在关系部分用数据数组替换数据哈希,如这个:
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
另外,在我的控制器中,任何像这样的强参数:
:title, :content, genre_ids: []
变成
:title, :content, :genres
遵守JSONAPI.
所以对于我的新测试样本数据,我现在有:
def setup
...
@new_chapter = {
title: "Cooked Wolf Dinner",
order: 4,
published: false,
content: "The bad wolf was very mad. He was determined to eat the little pig so he climbed down the chimney.",
}
...
end
def format_jsonapi(params, book_id = nil)
params = {
data: {
type: "chapters",
attributes: params
}
}
if book_id != nil
params[:data][:relationships] = {
book: {
data: {
type: "books",
id: book_id
}
}
}
end
return params
end
关于关系设置的特别说明-只有在有关系的情况下才将relationships
添加到params
,否则,将其设置为nil就是告诉JSON API到删除该关系,而不是忽略它。
然后我可以像这样调用我的测试:
test "chapter create - should create new chapter assigned to an existing book" do
assert_difference "Chapter.count", +1 do
post chapters_path, params: format_jsonapi(@new_chapter, @book.id), headers: user_authenticated_header(@jim)
assert_response :created
json = JSON.parse(response.body)
attributes = json['data']['attributes']
assert_equal "Cooked Wolf Dinner", attributes['title']
assert_equal 4, attributes['order']
assert_equal false, attributes['published']
assert_equal @book.id, json['data']['relationships']['book']['data']['id'].to_i
end