ruby-on-rails – 为什么渲染json:返回NULL而不是boolean值
为什么在从API调用资源时,我为is_read获取null而不是true / false?
拒绝:可能与渲染json:internals有关? 这是我第一次看到这个巫术,所以请耐心等待.寻找好的答案:) $curl -X GET -H localhost:3000/api/v1/alerts/1/show | python -m json.tool { "body": "Deserunt laboriosam quod consequuntur est dolor cum molestias.","created_at": "2015-03-22T15:02:01.927Z","id": 1,"is_read": null,"subtitle": "Aspernatur non voluptatem minus qui laudantium molestiae.","title": "Et nemo magni autem similique consequuntur.","updated_at": "2015-03-22T15:02:01.927Z" } -一世 HTTP/1.1 200 OK X-Frame-Options: SAMEORIGIN X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Content-Type: application/json; charset=utf-8 Etag: "3232ec2058ffb13db1f9244366fe2ea8" Cache-Control: max-age=0,private,must-revalidate X-Request-Id: c520cabe-6334-4997-956b-d1f21724b80c X-Runtime: 0.016337 Server: WEBrick/1.3.1 (Ruby/2.1.2/2014-05-08) Date: Sun,22 Mar 2015 15:28:21 GMT Content-Length: 300 Connection: Keep-Alive Rails控制台: Alert.find(1) Alert Load (1.1ms) SELECT "alerts".* FROM "alerts" WHERE "alerts"."id" = $1 LIMIT 1 [["id",1]] => #<Alert id: 1,title: "Et nemo magni autem similique consequuntur.",subtitle: "Aspernatur non voluptatem minus qui laudantium mol...",body: "Deserunt laboriosam quod consequuntur est dolor cu...",is_read: false,created_at: "2015-03-22 15:02:01",updated_at: "2015-03-22 15:02:01"> 当我打电话给#to_json时会发生奇怪的事情 Alert.find(1).to_json Alert Load (4.1ms) SELECT "alerts".* FROM "alerts" WHERE "alerts"."id" = $1 LIMIT 1 [["id",1]] => "{"id":1,"title":"Et nemo magni autem similique consequuntur.","subtitle":"Aspernatur non voluptatem minus qui laudantium molestiae.","body":"Deserunt laboriosam quod consequuntur est dolor cum molestias.","is_read":null,"created_at":"2015-03-22T15:02:01.927Z","updated_at":"2015-03-22T15:02:01.927Z"}" 当is_read为true时,也会发生这种情况. 更多信息: Rails 4.1.7,Ruby 2.1.2,Postgresql 警报 create_table "alerts",force: true do |t| t.string "title" t.string "subtitle" t.text "body" t.boolean "is_read",default: false,null: false t.datetime "created_at" t.datetime "updated_at" end 用于填充db的脚本: Alert.populate 100 do |alert| alert.title = Faker::Lorem.sentence(3) alert.subtitle = Faker::Lorem.sentence(3) alert.body = Faker::Lorem.sentence(3) alert.is_read = false end 控制器: def show alert = Alert.find(params[:id]) render json: alert end 编辑2015年3月26日 irb(main):013:0> Alert.find(1) Alert Load (0.6ms) SELECT "alerts".* FROM "alerts" WHERE "alerts"."id" = $1 LIMIT 1 [["id",title: "Test",subtitle: "waaat?",body: "heeeelp",created_at: "2015-03-26 15:49:32",updated_at: "2015-03-26 15:56:51"> irb(main):014:0> a.body => "heeeelp" irb(main):015:0> a.title => "Test" irb(main):016:0> a.is_read => nil irb(main):017:0> a["is_read"] => false irb(main):018:0> a.update_attributes(is_read: true) (0.4ms) BEGIN SQL (0.5ms) UPDATE "alerts" SET "is_read" = $1,"updated_at" = $2 WHERE "alerts"."id" = 1 [["is_read","t"],["updated_at","2015-03-26 15:57:26.645210"]] (2.1ms) COMMIT => true irb(main):019:0> a["is_read"] => true 最后:因为模型中有attr_reader:is_read.删除它将导致正确的序列化.有人可以解释一下吗? 解决方法
ActiveRecord通过为每个属性创建一个getter方法,帮助将数据库字段映射到Ruby类的方法,从内部属性存储(变量)中提取值. 当你定义attr_reader:is_read时,它实际上是: # app/mode/alert.rb def is_read @is_read end 由ActiveRecord :: Base轻松提供的getter方法将被这个新定义的方法屏蔽.这可能是意料之外的,一开始看起来绝对像巫术. 行为:attr_reader(有点稀疏)记录在这里:
http://ruby-doc.org/core-1.9.3/Module.html#method-i-attr_reader
这个问题分为两部分. 首先,为什么价值不存在?上面给出了答案.你的模型掩盖了ActiveRecord getter方法is_read,该方法是在调用ActiveRecord的内部属性存储,其中一个指向实例变量@is_read.因为您没有在模型中指定@is_read,所以返回nil. 其次,为什么它是空的而不是零?正如你所暗示的,答案就是渲染:json.在JSON specification中,您具有以下允许值:
要生成有效的JSON响应,渲染:json替换Ruby的nil,JSON为null. 那么说你永远不想使用attr_reader,attr_accessor等是安全的.人.在你的模特?并不是的.这些可以用作虚拟或瞬态属性,一旦对象被销毁就会丢失.但是,应该记住与ActiveRecord的交互,以避免遇到看似晦涩的错误. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |