I am developing a Ruby on Rails 3 application and this is the first time I use MongoDB.
I have been thinking for couple of days on this problem, and I don't find a good solution. There are two problems I want to discuss.
- The model
- How to integrate this with Devise
The application is a School Courses manager. It manages many schools, which contains many students, courses, professors and tasks.
The structure of one school – there a many– is:
School
- Director
- Students
- Professors
- Courses
- Tasks
The Director is the admin of the school. He is the only one who can create professors, students and courses.
- There is exactly 1 Director.
- There can be (0 – many) courses.
- There can be (0 – many) students
- There can be (0 – many) professors
- Students may be in (0 – many) courses.
- Professors may be in (0 – many) courses.
- For every course, there can be (0–many) tasks associated with (0 – many) students. Yes, professor can send specific tasks to specific students.
I though for a couple of days on how to architecture this collection of models on MongoDB using Mongoid, and I reach a possible solution. Yet I come from a Relational Database world and maybe this is an awful solution and I am abusing of 'embed' :)
- Collection Schools
- School 1
- embed Director
- embed Users
- embed Courses
- embed Tasks
- School 2
- embed Director
- embed Users
- embed Courses
- embed Task
- School 1
Models:
class User
include Mongoid::Document
field :first_name
field :last_name
field :email
embedded_in :school, :inverse_of => :director
embedded_in :school, :inverse_of => :students
embedded_in :school, :inverse_of => :professors
end
class School
include Mongoid::Document
field :name
key :name
embeds_one :director, :class_name => "User"
embeds_many :students, :class_name => "User"
embeds_many :professors, :class_name => "User"
validates :name, :presence => true
end
class Task
include Mongoid::Document
field :name
references_one :student, :class => "User"
references_one :course
end
Also, I think I will use this class of wrap a collection a tasks. A professor creates a TaskCollection and assign students to it.
class TaskCollection
include Mongoid::Document
field :name
references_many :students, :stored_as => array, :class => "User"
references_one :task
end
So this is my first question. I need feedback. Is it the right way to use a document oriented database? Performance? Improvements? Errors?
And the second question. How can we integrate this in Devise?
My first try is this:
Routes.rb
devise_for :users, :path => 'schools/:school_id/users'
resources :schools do resources :documents, :only => [:index] resources :tasks, :only => [:index]
endBut when I do try do register and user I get an error.
http://localhost:3000/schools/pablo-de-olavide/users
Mongoid::Errors::InvalidCollection in Devise/registrationsController#create
A开发者_运维问答ccess to the collection for User is not allowed since it is an embedded document, please access a collection from the root document.
Thank you very much for your help.
I just started playing with Devise and Mongoid myself.
Your immediate need is to make User a root document (i.e. not embedded) this is how Devise is expecting to interact with the User model. I don't know if it can be overridden easily to do what you want it to. Personally, I don't think it would make a lot of sense even if you could.
As to your document design question you should take a look at this from Mongdb http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-Embedvs.Reference
From your example I would consider the User object to be a "First Class" object which would warrant its own collection.
Here is the link from the Devise wiki with information about embedding users to another model:
How-To:-Embed-users-in-your-account-model-with-Mongoid
精彩评论