【问题标题】:Ember-data and MongoDB, how to handle _idEmber-data 和 MongoDB,如何处理 _id
【发布时间】:2012-07-19 06:47:51
【问题描述】:

我正在使用带有 rails 和 MongoDB 的 ember-data,并且在 _id 字段中存储 ID 的方式存在问题。

Ember-data 将使用 id 作为 ID 的默认字段,因此我尝试像这样覆盖它:

App.User = DS.Model.extend
    primaryKey: "_id"
    name: DS.attr "string"
    image: DS.attr "string"

这似乎在大多数情况下都有效,但在某些情况下,我会从 ember 中得到例外:

未捕获的错误:断言失败:您的服务器返回了一个带有 key _id 但你没有映射

我怀疑这可能是 ember-data 中的一个错误,因为它仍在大量开发中,但我试图找到一种方法来将 _id 映射到 Rails 中服务器端的 id?我正在使用 mongoid 进行 mongo 映射。

【问题讨论】:

  • Mongoid 一般为你把 id 别名为 _id ......当你只是作为 id 离开时你有什么问题?
  • 它映射到我遇到问题的 ember-data。我从服务器得到一个实体,json 是 {_id:5008b66d330eb996c100000f} 而不是 {id:5008b66d330eb996c100000f}。然后我从 ember-data 收到映射错误。
  • 我发现我的问题实际上是用于检索实体的 JSON 响应的格式。就像 {_id: 5008b66d330eb996c100000f} 应该是 {entity: {_id: 5008b66d330eb996c100000f}}

标签: ruby-on-rails mongodb mongoid ember.js ember-data


【解决方案1】:

啊,您可以制作 JSON 以使用 id 方法而不是 _id 属性,而不是在 JSON 中包含 _id。方式:

您可以使用rabl,JSON 可以是:

object @user 
attributes :id, :email
node(:full_name) {|user| "#{user.first_name} #{user.last_name}"}

你也可以制作 as_json 方法

class User
  def as_json(args={})
    super args.merge(:only => [:email], :methods => [:id, :full_name])
  end
end

【讨论】:

【解决方案2】:

另一种方法是使用(如果可能的话)ActiveModel::Serializer。 (我认为应该接近 rabl (?))

来自 ember-data gihtub:https://github.com/emberjs/data
对遵循 active_model_serializers gem 约定的 Rails 应用程序的开箱即用支持

当我们开始使用 ember-data 时,我们正在制作 as_json(),但使用 gem 肯定更好:)

【讨论】:

  • 在 Rails/Ember 应用程序中绝对是最好的序列化方法...
  • @sly7_7 我遇到了同样的问题,但我使用的是 .NET 后端而不是 RoR。我能够以 Ember-Data 期望的格式生成 json,但我仍然收到映射错误消息。我的 json 是这样的{ "genres": [{"id":1, "name":"Action"}, {"id":2, "name":"Drama"}]} 你愿意看看my question
【解决方案3】:

我在使用带有 ember-resource 和 couchdb 的 ember.js 时遇到了类似的问题,它的 ID 也存储为 _id

作为该问题的解决方案,我为我的所有模型类定义了一个超类,其中包含一个计算属性,以便将 _id 复制到 id 中,如下所示:

// get over the fact that couchdb uses _id, ember-resource uses id
id: function(key, value) {
    // map _id (couchdb) to id (ember)
    if (arguments.length === 1) {
        return this.get('_id');
    }
    else {
        this.set('_id', value);
        return value;
    }
}.property('_id').cacheable()

也许这也能解决您的问题?

【讨论】:

    【解决方案4】:

    如果你使用 Mongoid3,这里的猴子补丁可能对你有用。

    https://gist.github.com/4700909

    【讨论】:

      【解决方案5】:

      最好的方法是使用ActiveModel::Serializers。由于我们使用的是 Mongoid,因此您需要添加这样的包含语句(参见 benedikt 的 gist):

      # config/initializers/active_model_serializers.rb
      Mongoid::Document.send(:include, ActiveModel::SerializerSupport)
      Mongoid::Criteria.delegate(:active_model_serializer, :to => :to_a)
      

      然后包含您的序列化程序。类似的东西:

      # app/serializers/user_serializer.rb
      class UserSerializer < ActiveModel::Serializer
        attributes :id, :name, :email
        def id
          object._id
        end 
      end
      

      这解决了_id 问题

      【讨论】:

        【解决方案6】:

        joscas 回答的第二部分为我解决了 Rails4/Ruby2 的 id 问题,但我必须 .to_s _id。

        class UserSerializer < ActiveModel::Serializer
          attributes :id, :name, :email
          def id
            object._id.to_s
          end
        end
        

        【讨论】:

          【解决方案7】:

          如果您使用的是 Mongoid,这里有一个解决方案,因此您不必为每个序列化程序添加方法 def id; object._id.to_s; end

          添加以下 Rails 初始化程序

          Mongoid 3.x

          module Moped
            module BSON
              class ObjectId
                alias :to_json :to_s
                alias :as_json :to_s
              end
            end
          end
          

          Mongoid 4

          module BSON
            class ObjectId
              alias :to_json :to_s
              alias :as_json :to_s
            end
          end
          

          Building 的活动模型序列化器

          class BuildingSerializer < ActiveModel::Serializer
            attributes :id, :name
          end
          

          生成的 JSON

          {
            "buildings": [
              {"id":"5338f70741727450f8000000","name":"City Hall"},    
              {"id":"5338f70741727450f8010000","name":"Firestation"}
            ]
          }
          

          这是 brentkirby 建议的猴子补丁,arthurnn 为 Mongoid 4 更新

          【讨论】:

            【解决方案8】:

            我不知道它是什么时候添加的,但你可以告诉 Ember-Data 主键是 _id:

            DS.RESTAdapter.extend({
              serializer: DS.RESTSerializer.extend({
                primaryKey: '_id'
              })
            });
            

            【讨论】:

              【解决方案9】:

              虽然这个问题很老了,但我仍然认为我的回答可以帮助其他人:

              如果您使用的是 ActiveModelSerializer,那么您只需要这样做:

              class UserSerializer < ActiveModel::Serializer
                   attributes :id , :name
              end
              

              一切正常。顺便说一句,我在前端使用 emberjs。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-11-30
                • 1970-01-01
                • 2023-03-16
                • 2013-03-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多