2017-02-19 9 views
0

我正在编写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_jsonas_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_jsonas_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字段类型时呈现存储在数据库中的所有数据。

我想知道这里有没有人对此问题有任何意见,然后再继续提交错误报告。

回答

1

问题似乎是在你的代码:

class GroceryItem 
    include Mongoid::Document 
    field :name, type: String 
    field :expiry, type: Date 
end 

这里,到期日期具有的类型,因此它有望没有时间分量返回日期。我认为使用适当的类型将解决您的问题。

+0

我实际上在更多的实验后才发现这一点。我注意到,当我再次尝试创建一个应用程序并生成脚手架时('''rails g scaffold grocery_item name expiry:datetime''')它工作。这次我的模型的类型为'''Time''。我无法相信我没有接受,我觉得我第一次使用'''expiry:datetime'''。 我仍然很高兴它的默认工作。 :) – Welkie

+0

@Welkie哈哈,不用担心,会发生:)没那么快“提交bug报告”:D –

+0

这就是为什么我总是趁机首先在StackOverflow上受到羞辱。 :D稍微不令人尴尬。 – Welkie

相关问题