我正在编写Rails应用程序以充当仅用于移动应用程序的Web服务。我使用--api
和--skip-active-record
开关创建了它。我的模型有一个DateTime字段。Mongoid - 在JSON API响应中序列化DateTime字段时获取日期而不是时间
这是我的模型和我在我的控制器中调用的方法的代码。因为我使用--api
,没有查看代码:
class GroceryItem
include Mongoid::Document
field :name, type: String
field :expiry, type: Date
end
# grocery_items_controller.rb
# GET /grocery_items/1
def show
render json: @grocery_item
end
在数据库中,我可以看到,被存储在现场的时间部分:
db.grocery_items.find()
{ "_id" : ObjectId("58a9298da1c1d12e7cee02d9"), "name" : "Chocolate", "expiry" : ISODate("2017-02-19T05:13:49.253Z") }
我也可以看到这在Rails的控制台:
irb(main):003:0> GroceryItem.first
=> #<GroceryItem _id: 58a9298da1c1d12e7cee02d9, name: "Chocolate", expiry: 2017-02-19 05:13:49 UTC>
然而,当我尝试访问我的GroceryItem模型类利用该方法届满时,我得到一个Date对象。我只得到数据的日期部分,没有时间部分:
irb(main):004:0> GroceryItem.first.expiry
=> Sun, 19 Feb 2017
irb(main):005:0> GroceryItem.first.expiry.class
=> Date
irb(main):006:0> GroceryItem.first.expiry.to_s
=> "2017-02-19"
呼吁实例to_json
和as_json
还省略了数据:
irb(main):008:0> GroceryItem.first.to_json
=> "{\"_id\":{\"$oid\":\"58a9298da1c1d12e7cee02d9\"},\"expiry\":\"2017-02-19\",\"name\":\"Chocolate\"}"
irb(main):009:0> GroceryItem.first.as_json
=> {"_id"=>BSON::ObjectId('58a9298da1c1d12e7cee02d9'), "expiry"=>Sun, 19 Feb 2017, "name"=>"Chocolate"}
导致我的JSON响应omiting数据。我假设在控制器渲染过程中使用任何to_json
或as_json
做渲染:
{
"_id": {
"$oid": "58a9298da1c1d12e7cee02d9"
},
"expiry": "2017-02-19",
"name": "Chocolate"
}
我终于能够找出如何通过调用下面来访问这些数据。你可以看到,我终于得到了时间Ruby类:
irb(main):010:0> GroceryItem.first.attributes[:expiry]
=> 2017-02-19 05:13:49 UTC
irb(main):011:0> GroceryItem.first.attributes[:expiry].class
=> Time
,让我终于有了与ISO8601规范与存储在MongoDB中的数据不兼容的方式串行化数据的方法:
irb(main):012:0> GroceryItem.first.attributes[:expiry].utc.iso8601
=> "2017-02-19T05:13:49Z"
当然,这种行为是不正确的。当开发人员为某个字段选择DataTime类型时,他们必须希望时间部分通过。否则,他们会改用日期类型。我现在明白我可以通过创建视图来以我认为合适的方式呈现JSON来覆盖默认的Rails API和Mongoid配对行为,但是我正在考虑提交bug报告,因为我觉得应该将默认行为更改为自动在开发人员选择DateTime字段类型时呈现存储在数据库中的所有数据。
我想知道这里有没有人对此问题有任何意见,然后再继续提交错误报告。
我实际上在更多的实验后才发现这一点。我注意到,当我再次尝试创建一个应用程序并生成脚手架时('''rails g scaffold grocery_item name expiry:datetime''')它工作。这次我的模型的类型为'''Time''。我无法相信我没有接受,我觉得我第一次使用'''expiry:datetime'''。 我仍然很高兴它的默认工作。 :) – Welkie
@Welkie哈哈,不用担心,会发生:)没那么快“提交bug报告”:D –
这就是为什么我总是趁机首先在StackOverflow上受到羞辱。 :D稍微不令人尴尬。 – Welkie