I am building a web app which has multiple projects. The general data model is such that 开发者_C百科each project has many resources such as documents, registers, etc.Something along the lines of:
class Project < ActiveRecord::Base
has_many :documents, :registers, :employments
has_many :users, :through => :employments
class User < ActiveRecord::Base
has_many :employments
has_many :projects, :through => :employments
class Document < ActiveRecord::Base
belongs_to :project
class Register < ActiveRecord::Base
belongs_to : project
The difficulty comes with routing!! Any C UD actions to projects will be done through a namespace. However, when a user is viewing a project, i want the project_id in the routes such that:
'0.0.0.0:3000/:project_id/documents/
OR
'0.0.0.0:3000/:project_id/register/1/new
I thought about something like:
match '/:project_id/:controller/:id'
I presume I am to store the project_id in a session? If i forgo these routes for something simplier such as just:
"0.0.0.0:3000/documents"
How do I then bind any CRUD actions to documents or registers to the current project?? Surely I don't have to hard wire this into every controller?
HELP!
I guess what you need are nested resources.
resources :projects do
resources :documents
resources :registers
end
Now you'll get routing like this:
/projects/:project_id/documents
/projects/:project_id/registers
You'll be able to call params[:project_id]
inside the DocumentsController and RegistersController. You won't need a session to store the project_id. This will be available to you inside the url. You should avoid sessions as much as possible when creating a RESTful application.
The only extra thing you need to do is setting the relationship inside the create action of both Controllers:
def create
@document = Document.new(params[:document])
@document.project_id = params[:project_id]
# Now you save the document.
end
What I like to do is creating a helper method inside the ApplicationController that gets the current project.
class ApplicationController < ActionController::Base
helper_method :current_project
private
def current_project
@current_project ||= Project.find(params[:project_id]) if params[:project_id].present?
end
end
Now you can do the following inside the create action:
def create
@document = Document.new(params[:document])
@document.project = current_project
# Now you save the document.
end
You'll also be able to call current_project
inside your views for registers and documents. Hope that helps you out!
Check the Ruby on Rails guide for some more information on nested resources: http://edgeguides.rubyonrails.org/routing.html#nested-resources
精彩评论