Rails + Mongoid - не возвращать значения nil в JSON - PullRequest
5 голосов
/ 04 января 2012

У меня много дополнительных полей в Mongoid, например:

  field :key, type: String             
  field :element, type: String         
  field :rect, type: Array             

Если я верну json этой модели с заполненным только одним из них, я получу значения null во всех других полях. Как я могу удалить эти поля?

Моя модель имеет вложенные атрибуты, что означает, что нулевые значения могут находиться на нескольких уровнях.

Разъяснения:

Мне нужен способ удалить пустые поля из json-представления модели, включая пустые поля во всех вложенных атрибутах.

Пример кода :

1.9.3-p0 :005 > u=Muse.new(:key=>'ram').to_json
 => "{\"_id\":\"4f1ced749c2ee4219d000003\",\"element\":null,\"key\":\"ram\",\"rect\":null}" 

Ответы [ 4 ]

6 голосов
/ 22 января 2012

По умолчанию mongoid имеет возможность удалять пустые поля.Если вы оставите некоторые поля пустыми, mongoid удалит их при вставке.

в приведенном ниже примере я пропустил элемент fields & rect

class User
  include Mongoid::Document

    field :key, type: String             
    field :element, type: String         
    field :rect, type: Array       

    embeds_one :home  
end
>> u=User.new(:key=>'ram').to_json
=> "{"_id":"4f1c3722b356f82e4a000001","_type":"key":"ram"}"

, и он отлично работает.Но если вы положите значение nil в поле

>> u=User.new(:key=>'ram',:element=>nil).to_json
=> "{"_id":"4f1c3722b356f82e4a000001","_type":"User","key":"ram","element":null}"

, оно будет вставлено.Я предполагаю, что это именно та проблема в вашем коде.Таким образом, вы можете обойти это путем преобразования хэш-представления JSON с использованием as_json и удаления полей nil

x=u.as_json.reject! {|k,v| v.nil?}
=> "{"_id":"4f1c3722b356f82e4a000001","_type":"User","key":"ram"}"

Но для перехода на внутренние уровни вы не можете использовать as_json.проверьте приведенный ниже код

  >>h=Home.new(:address=>'xxxx',:dummy=>nil)
  >>u.home = h 
  >>x=u.as_json.reject! {|k,v| v.nil?}
  =>{"_id"=>BSON::ObjectId('4f1c39b4b356f82e4a000003'), "_type"=>"User","key":"ram","home"=>#<Home _id: 4f1c3c5db356f82e4a000004,address:'xxxx' , dummy: nil >}

Теперь вы видите, что манекен внутри встроенного дома документов все еще с нулем.поэтому мой лучший совет: Не ставьте значения ноль в дБ вообще .Для этого добавьте в ваши модели before_save обратный вызов (также встроенный) и удалите пустые поля.

Также я покажу вам, как удалить нулевые поля из вложенных объектов.Используйте его, если нет другого способа

Мы можем использовать attributes модели mongoid для получения хеш-представления объекта, включая вложенные уровни

x=u.attributes
=> {"_id"=>BSON::ObjectId4f1c39b4b356f82e4a000003,"key"=>"ram","element"=>nil,"home"=>{"address"=>"xxxx", "_id"=>BSON::ObjectId4f1c3c5db356f82e4a000004,"dummy"=>nil}}

, и вы должны найти этотам есть хеш внутри mongoid объекта, если он есть, мы должны использовать reject! {|k,v| v.nil?} на этом хеше тоже

, чтобы собрать все

def to_json(obj)
     obj.reject! {|k,v| v.nil?}
     obj.find_all {|x| x[1].class==BSON::OrderedHash}.each do |arr| 
           obj[arr[0]] = to_json(arr[1])    
     end
     obj     
end

и вызвать это с атрибутами модели

 >> to_json u.attributes
 => {"_id"=>BSON::ObjectId4f1c39b4b356f82e4a000003,"key"=>"ram","home"=>{"address"=>"xxxx", "_id"=>BSON::ObjectId4f1c3c5db356f82e4a000004}}

Вот и все.Надеюсь, это поможет

2 голосов
/ 01 октября 2012

Если вы просто пытаетесь удалить ключи полей со значениями nil из результатов запроса перед отправкой JSON, скажем, в браузер, вы можете просто сделать это (работает в моем случае):

doc = Model.all.entries.map {|d| d.as_document}
respond_width(doc)
1 голос
/ 23 января 2012

Насколько я знаю, в Монгоиде нет такой возможности.Тогда я бы предложил использовать один из генераторов API:

http://fabrik42.github.com/acts_as_api/

https://github.com/nesquena/rabl

или

https://github.com/rails/jbuilder

0 голосов
/ 13 мая 2014

Это легко сделать, если вы используете active_model_serializers (ознакомьтесь с этим Railscast для быстрого ознакомления).

Для вашего случая использования вы можете написать muse_serializer.rb, который выглядит следующим образом:

class MuseSerializer < ActiveModel::Serializer
  def attributes
    muse = super
    object.attributes.each do |attr|
      muse[attr[0]] = attr[1]
    end
    muse.delete('_id') #in case you want to exclude the _id field
    muse
  end
end

Это вернет все непустые поля, присутствующие в текущем объекте Muse.

...