【问题标题】:Rails nested resources and deviseRails 嵌套资源和设计
【发布时间】:2012-05-03 16:35:41
【问题描述】:

假设我有一个名为“User”的设计模型,它拥有 :notes:notebooks 以及每个 :notebook has_many :notes

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    Mongoid 将为您管理文档引用和查询,只需确保为您需要的每个方向指定关联/关系(例如,用户 has_many :notes 和 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
    

    【讨论】:

      【解决方案2】:

      我会用

      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))
      

      【讨论】:

      • mongoid (odm for mongodb) 不支持通过
      • 啊,对不起。没有看到关于Mongo的那一点。那么请忽略。
      猜你喜欢
      • 2012-02-02
      • 2012-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-30
      • 2015-02-27
      • 2017-07-11
      相关资源
      最近更新 更多