开发者

What's the best practice for these kinds of routes?

开发者 https://www.devze.com 2023-03-06 04:03 出处:网络
I have a Job model that belongs_to three users (customer, employee, and qa). The customer is set to current_user when the job is created, but the employee and qa users pick their jobs from the pool of

I have a Job model that belongs_to three users (customer, employee, and qa). The customer is set to current_user when the job is created, but the employee and qa users pick their jobs from the pool of u开发者_Go百科nclaimed jobs.

The way I have this implemented currently is as follows: match 'jobs/:id/assign/:type/:user_id' => 'jobs#assign' with an assign method with a case statement on params[:type]. So, for example, jobs/1/assign/qa/1 assigns user 1 as the qa for job 1.

This works, but it seems sloppy and I'd like to replace it with something cleaner. Is there a common convention for situations like this?

Edit: Users can have both employee and qa roles simultaneously. That's what's making me feel forcing into such a complex route.

class User < ActiveRecord::Base
  has_many :submitted_jobs,  :class_name => 'Job', :foreign_key => 'customer_id'
  has_many :assigned_jobs,   :class_name => 'Job', :foreign_key => 'employee_id'
  has_many :reviewed_jobs,   :class_name => 'Job', :foreign_key => 'qa_id'

class Job < ActiveRecord::Base
  belongs_to :customer, :class_name => 'User', :foreign_key => 'customer_id'
  belongs_to :employee, :class_name => 'User', :foreign_key => 'employee_id'
  belongs_to :qa,       :class_name => 'User', :foreign_key => 'qa_id'


You might consider a more RESTful approach to your problem. Two of the things RESTful Best Practices cites as "classic beginner's mistakes" is to "strongly mirror your ActiveRecord data model to choose your resources" and to "add custom methods if the standard ones don't fit."

Nouns are the new verbs

  • Change your way of explaining the scenario, an action
    • Use a noun to describe the action
    • The noun given to your scenario is the resource you're looking for
  • A user subscribes to a group -> A subscription is created
  • The project is validated by its owner -> A project validation is created
  • The user deactivates his account -> A user account activation is deleted

You could easily create a "Job Assignment" resource (not necessarily a separate model) and, for example, create one with the right parameters. In rough pseudo-Rails:

# routes
resources :job_assignments, :only => [:create, :delete] # or whatever you need

# job_assignments_controller
class JobAssignmentsController < ApplicationController
  def create
    user = User.find(params[:user_id])
    job  = Job.find(params[:job_id])
    user.assign(job, params[:job_type]) # handle model logic
  end

  def destroy
    user = User.find(params[:user_id])
    job  = Job.find(params[:job_id])
    user.unassign(job, params[:job_type]) # handle model logic
  end
end

There are some good examples in the presentation (starting on slide 32).


I think a great way about solving this is design your routes first which is what you're doing.

Your current routing is great if the "Job" and the assignee are well known in advance. In my opinion if you stuff the the job AND the assignee type information in the route you're doing too much.

Do the employees/qa also login and pick their own jobs? If they do, then their own information will be available on the server side in "current_user".

In that case, the route should ideally be "/job/:id/pick" going to "JobsController#pick" action with a POST request for example. In your controller action you would get the eemployee/qa user info in the current_user.

config/routes.rb

resource :jobs do
  member do
    post :pick
  end
end

in app/controller/jobs_controller.rb

def pick
  job = Job.find(params[:id])
  current_user.jobs << job # User has_many :jobs
  # or
  job.user = current_user
  ...
end

Please do let me know if employees/qa do NOT login and i'll update solution accordingly with another solution.

0

精彩评论

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

关注公众号