Rails嵌套资源和设计

时间:2012-05-03 16:35:41

标签: ruby-on-rails mongodb reference mongoid relationship

假设我有一个名为“用户”的设计模型,其中包含:notes:notebooks以及每个:notebook has_many :notes

所以笔记会有两个外键:user_id:notebook_id,那么如何建立/找到一个音符呢?

current_user.notebooks.find(param).notes.new(params [:item])将仅为笔记本创建foreign_key,还是为DB中的笔记记录中的用户创建?

如果是第二种情况(只有笔记本的外键),我应该怎么写?

将MongoDB与MongoID和引用关系一起使用

2 个答案:

答案 0 :(得分:0)

我会用

class User
  has_many :notebooks
  has_many :notes, :through => :notebooks
end

http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

<强>更新

您可以手动设置user_id,如下所示(我假设param是您笔记本的ID?):

Notebook.find(param).notes.new(params[:item].merge(:user_id => current_user.id))

答案 1 :(得分:0)

Mongoid将为您管理文档引用和查询,只需确保为您需要的每个方向指定关联/关系(例如,User has_many:notes AND Note belongs_to:user)。与ActiveRecord一样,它似乎对这种关系“很聪明”。请不要手动操作引用,而是让您的ODM(Mongoid)为您工作。当您运行测试(或使用rails控制台)时,您可以使用tail -f log / test.log(或log / development.log)来查看Mongoid为您执行的MongoDB操作,您可以看到实际的对象文件更新后的参考文献。您可以看到关系如何使用特定的对象引用,如果您注意这一点,链接优化应该变得更加清晰。

以下型号和测试工作对我而言。可根据要求提供有关设置的详细信息。希望这会有所帮助。

模型

class User
  include Mongoid::Document
  field :name

  has_many :notebooks
  has_many :notes
end

class Note
  include Mongoid::Document
  field :text

  belongs_to :user
  belongs_to :notebook
end

class Notebook
  include Mongoid::Document

  belongs_to :user
  has_many :notes
end

测试

require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup
    User.delete_all
    Note.delete_all
    Notebook.delete_all
  end

  test "user" do
    user = User.create!(name: 'Charles Dickens')
    note = Note.create!(text: 'It was the best of times')
    notebook = Notebook.create!(title: 'Revolutionary France')
    user.notes << note
    assert_equal(1, user.notes.count)
    user.notebooks << notebook
    assert_equal(1, user.notebooks.count)
    notebook.notes << note
    assert_equal(1, notebook.notes.count)
    puts "user notes: " + user.notes.inspect
    puts "user notebooks: " + user.notebooks.inspect
    puts "user notebooks notes: " + user.notebooks.collect{|notebook|notebook.notes}.inspect
    puts "note user: " + note.user.inspect
    puts "note notebook: " + note.notebook.inspect
    puts "notebook user: " + notebook.user.inspect
  end

end

结果

Run options: --name=test_user

# Running tests:

user notes: [#<Note _id: 4fa430937f11ba65ce000002, _type: nil, text: "It was the best of times", user_id: BSON::ObjectId('4fa430937f11ba65ce000001'), notebook_id: BSON::ObjectId('4fa430937f11ba65ce000003')>]
user notebooks: [#<Notebook _id: 4fa430937f11ba65ce000003, _type: nil, user_id: BSON::ObjectId('4fa430937f11ba65ce000001'), title: "Revolutionary France">]
user notebooks notes: [[#<Note _id: 4fa430937f11ba65ce000002, _type: nil, text: "It was the best of times", user_id: BSON::ObjectId('4fa430937f11ba65ce000001'), notebook_id: BSON::ObjectId('4fa430937f11ba65ce000003')>]]
note user: #<User _id: 4fa430937f11ba65ce000001, _type: nil, name: "Charles Dickens">
note notebook: #<Notebook _id: 4fa430937f11ba65ce000003, _type: nil, user_id: BSON::ObjectId('4fa430937f11ba65ce000001'), title: "Revolutionary France">
notebook user: #<User _id: 4fa430937f11ba65ce000001, _type: nil, name: "Charles Dickens">
.

Finished tests in 0.018622s, 53.6999 tests/s, 161.0998 assertions/s.

1 tests, 3 assertions, 0 failures, 0 errors, 0 skips