开发者

Mongoid: embedded one to one, with pure json input

开发者 https://www.devze.com 2023-03-17 15:57 出处:网络
I\'m trying embedded one to one mongoid model where the \"embedded child\" is a pure json input coming from an external API.

I'm trying embedded one to one mongoid model where the "embedded child" is a pure json input coming from an external API.

The parent document is defined like follow:

./app/models/user.rb

class User
  include Mongoid::Document

  field :nickname, :type => String

  embeds_one :watchlist

  def self.create_with_omniauth(auth)
    create! do |user|
      user.nickname = auth['user_info']['nickname']
    end
  end
end

the child is defined like follow (using a mix of "mongo ruby driver" & "mongoid ORM"):

./app/models/watchlist.rb

require 'mongo'
class Watchlist
  include Mongoid::Document

  embedded_in :user

  def self.watched(nickname)  
    conn = FaradayStack.build 'https://api.github.com'
    #resp = conn.get '/users/:nickname/watched'
    resp = conn.get '/users/lgs/watched'

    db   = Mongo::Connection.new.db('gitwatch_dev')
    coll = db.collection('watchlist')
    coll.insert(resp.body)
  end
end

The controllers look like this:

app/controllers/home_controller.rb

class HomeController < ApplicationController
  def index
    if current_user
      nickname = request.env["omniauth.auth"]
      @watched = Watchlist.watched(nickname)
    end
  end
end

app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  def create
    auth = request.env["omniauth.auth"]
    #user = User.find_by_provider_and_uid(auth["provider"], auth["uid"]) || User.create_with_omniauth(auth)
    user = User.where(:provider => auth['provider'], :uid => auth['uid']).first || User.create_with_omniauth(auth)
    session[:user_id] = user.id
    redirect_to root_url, :notice => "Signed in!"
  end
...
end

Now, what I get is a gitwatch_dev mongodb, with two UNRELATED "mongo models", in mongo cli they look like the follow:

> db.users.find()
{ "_id" : ObjectId("4e117b951d41c80b14000001"), "provider" : "github", "uid" : "1573", "name" : "Luca G. Soave", "email" : "luca.soave@gmail.com", "nickname" : "lgs", "token" : "a512434559b07feb0a98d199238764sde9876", "secret" : null, "user_hash" : "{\"plan\"=>{\"name\"=>\"free\", \"collaborators\"=>0, \"space\"=>307200, \"private_repos\"=>0}, \"gravatar_id\"=>\"9c7d80ebc20ab8xx994e57519ae\", \"company\"=>\"http://www.linkedin.com/in/lucasoave\", \"name\"=>\"Luca G. Soave\", \"created_at\"=>\"2008/02/28 05:26:40 -0800\", \"location\"=>\"Milan - Italy\", \"disk_usage\"=>113860, \"collaborators\"=>0, \"public_repo_count\"=>32, \"public_gist_count\"=>85, \"blog\"=>nil, \"following_count\"=>140, \"id\"=>1573, \"owned_private_repo_count\"=>0, \"private_gist_count\"=>2, \"type\"=>\"User\", \"permission\"=>nil, \"total_private_repo_count\"=>0, \"followers_count\"=>9, \"login\"=>\"lgs\", \"email\"=>\"luca.soave@gmail.com\"}" }

> db.watchlist.find()
{ "_id" : ObjectId("4e117bd31d41c80b14000002"), "open_issues" : 47, "url" : "https://api.github.com/repos/mojombo/grit", "watchers" : 997, "homepage" : "ht开发者_C百科tp://grit.rubyforge.org/", "master_branch" : null, "language" : "Ruby", "fork" : false, "pushed_at" : "Sat Jul 02 2011 01:02:45 GMT+0200 (CEST)", "created_at" : "Mon Oct 29 2007 15:37:16 GMT+0100 (CET)", "git_url" : "git://github.com/mojombo/grit.git", "html_url" : "https://github.com/mojombo/grit", "private" : false, "size" : 2482, "owner" : { "url" : "https://api.github.com/users/mojombo", "login" : "mojombo", "avatar_url" : "https://secure.gravatar.com/avatar/25c7c18223fb42a4c6ae1c8db6f50f9b?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png", "id" : 1 }, "description" : "Grit gives you object oriented read/write access to Git repositories via Ruby.", "name" : "grit", "svn_url" : "https://svn.github.com/mojombo/grit", "ssh_url" : "git@github.com:mojombo/grit.git", "clone_url" : "https://github.com/mojombo/grit.git", "forks" : 140 }
...
...

while I'd like to get a nested "child into parend" json, something like the embedded one to one mongoid model example:

{
  "_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
  "name" : {
    "_id" : ObjectId("4d3ed089fb60ab534684b7e0"),
    "vorname" : "Heinrich",
    "nachname" : "Heine"
  }
}

Than, I'm also looking for doing that in "pure mongoid" without mess of ruby drivers, but cannot find out the way ...

UPDATE jul 6 2011 - thanks to Rubish Gupta:

it finally works with

user.create_watchlist['dynamic_attribute'] = resp.body

in the User parent model: app/models/user.rb see the full code at http://www.pastie.org/2169671


The problem here is with these lines:

db   = Mongo::Connection.new.db('gitwatch_dev')
coll = db.collection('watchlist')
coll.insert(resp.body)

Here what you are doing is accessing the collection watchlist, which you do not want to create and want to embed the records in users collection.

Correct way to do would be to make a function watch(repo) like following in User:

def watch(repo)
  # obtain the resp
  self.create_watchlist(resp.body)
end

But you should enable dynamic attributes in mongoid.yml to do this.

In you controller you should do current_user.watch(repo) instead of the three lines noted above.

0

精彩评论

暂无评论...
验证码 换一张
取 消