2013-06-14 26 views
5

Tôi có một cái gì đó tuyến đường như:Rails đường Phạm vi mặc định dựa trên CURRENT_USER

scope ":department", department: /admin|english|math/, defaults: { department: 'admin' } 

Có thể làm cho các bộ phận mặc định cho tuyến đường này được dựa trên current_user.department.name?

Nếu điều này là không thể, một cách khác để giải quyết vấn đề của tôi là gì. Vấn đề là tôi muốn tất cả các liên kết mặc định đến phạm vi hiện tại trừ khi có ghi chú khác. Tôi hiện đang làm những điều sau đây ở nhiều nơi:

# links to /math/students 
link_to 'students', students_path(department: current_user.department.name.downcase) 
+2

số 'current_user', mà là một phương pháp của bộ điều khiển của bạn, không tồn tại cho đến khi định tuyến đã được thực hiện và một bộ điều khiển/hành động đã được chọn và một bộ điều khiển đã được khởi tạo. – meagar

+0

Nếu điều này là không thể, thì làm thế nào tôi có thể khắc phục vấn đề của mình. Tôi đã cập nhật câu hỏi của mình với các chi tiết khác. –

Trả lời

0

Bạn có thể sử dụng

link_to 'students', polymorphic_path([current_user.department.name.downcase, :students]) 

này sẽ gọi

math_students_path 

Vì vậy, để làm việc Tôi cho rằng bạn nên thêm vào tuyến đường của bạn

scope ':department', as: 'department' do 
    ... 

as then chốt tạo ra những người giúp đỡ có dạng: department_something_path

Như dòng đó là quá dài bạn có thể trích xuất rằng để một helper

# students path taking into account department 
def students_path!(other_params = {}, user = current_user) 
    polymorphic_path([user.department.name.downcase, :students], other_params) 

Sau đó, bạn sẽ sử dụng trong quan điểm của bạn

link_to 'students', students_path! 
+0

Tôi không truy cập vào '/ students? Department = any_department'. Tôi đã cập nhật câu hỏi của mình để chỉ ra URL. Ngoài ra, tôi không thích ý tưởng phải làm người trợ giúp cho mỗi tuyến đường của tôi. Điều này sẽ rất xấu xí, rất nhanh chóng –

+0

hmm ok, tôi hiểu rồi. Tôi sẽ chỉnh sửa. – juanpastas

+0

Tôi không hiểu làm thế nào điều này sẽ nhận được xấu xí. – juanpastas

6

Nếu tôi hiểu chính xác, những gì bạn muốn là có thể viết:

link_to 'students', students_path

và có tùy chọn bộ phận được đặt tự động dựa trên người dùng hiện tại.

Đây là giải pháp giống như một số giải pháp khác đã được cung cấp: xác định người trợ giúp cho mỗi tuyến đường yêu cầu một bộ phận. Tuy nhiên, chúng ta có thể làm điều này theo lập trình.

Ở đây chúng ta đi: app/helpers/url_helper.rb

module UrlHelper 

    Rails.application.routes.routes.named_routes.values. 
    select{ |route| route.parts.include?(:department) }.each do |route| 
     define_method :"department_#{route.name}_path" do |*args| 
     opts = args.extract_options! 
     if args.size > 0 
      keys = route.parts - [:department] 
      opts.merge!(Hash[*keys.zip(args).flatten]) 
     end 
     opts.reverse_merge!(department: current_user.department.name.downcase) 
     Rails.application.routes.url_helpers.send(:"#{route.name}_path", opts) 
     end 
    end 

end 

Bây giờ bạn có phương pháp helper như department_students_path cho mỗi tuyến đường mà có một phân khúc :department con đường. Chúng sẽ hoạt động giống như students_path - bạn có thể chuyển sang các opts, thậm chí bạn có thể đặt rõ ràng :department và nó sẽ ghi đè lên mặc định. Và họ luôn được cập nhật với những thay đổi đối với routes.rb của bạn mà không cần phải duy trì nó.

Bạn thậm chí có thể có thể để đặt tên họ giống như những người giúp đỡ ban đầu, tức là,

define_method :"#{route.name}_path"

mà không cần phải thêm tiền tố họ với department_ --Tôi không làm điều đó bởi vì tôi thà tránh va chạm đặt tên như thế. Tôi không chắc làm thế nào mà sẽ làm việc (mà phương pháp sẽ giành chiến thắng tra cứu phương pháp khi gọi nó từ một mẫu xem), nhưng bạn có thể nhìn vào nó.

Tất nhiên, bạn có thể lặp lại khối này cho các phương pháp trợ giúp _url, vì vậy bạn sẽ có những phương thức đó ngoài các số _path.

Để giúp người trợ giúp có mặt trên bộ điều khiển cũng như chế độ xem, chỉ cần include UrlHelper trong số ApplicationController của bạn.

Vì vậy, tôi nghĩ rằng đây đáp ứng tiêu chí của bạn:

  1. Bạn có thể gọi một phương thức helper cho các đường scoped để :department đó sẽ mặc định các bộ phận của current_user, do đó bạn không cần phải xác định rõ ràng này mỗi lần.
  2. Người trợ giúp được tạo thông qua lập trình meta dựa trên các tuyến đường được xác định thực sự có phân đoạn :department, do đó bạn không phải duy trì chúng.
  3. Giống như url_helpers đường ray tích hợp, những kẻ này có thể lấy arg vị trí cho các đoạn đường dẫn khác, như, department_student_path(@student). Tuy nhiên, một hạn chế là nếu bạn muốn ghi đè lên bộ phận, bạn cần phải làm như vậy trong băm opts cuối cùng (department_student_path(@student, department: 'math')). Sau đó, một lần nữa, trong trường hợp đó bạn luôn có thể làm student_path('math', @student), vì vậy tôi không nghĩ rằng đó là một giới hạn.
+0

Điều này sẽ làm việc nhưng điều này sẽ không thêm đối số 'department' vào các tuyến đường mà thậm chí không chấp nhận thuộc tính này? Vì vậy, ví dụ nếu tôi liên kết đến 'about_path' (mà là ở cấp cơ sở và không phải trong một bộ phận) tôi sẽ nhận được'/về? Bộ phận = math' –

+0

Vâng, đó là chính xác. Đó là những gì tôi có ý nghĩa về bạn có thể muốn xác định điều này chỉ trên một tập con của bộ điều khiển hoặc thêm một số logic khác. Nếu các liên kết duy nhất bạn quan tâm về việc thêm điều này vào tự động là các tuyến cho 'StudentsController', ví dụ, bạn có thể xác định điều này trên bộ điều khiển thay vì' ApplicationController' – gregates

+0

Liên kết đến trang giới thiệu trên trang __every__ trong ứng dụng của tôi trong chân trang. Điều này làm cho nó không thể thực hiện giải pháp của bạn mà không có tác dụng phụ mà tôi đã đề cập ở trên. –

0

Điều gì về việc sử dụng các tuyến lồng nhau? Bạn có thể thực hiện điều này với:

resources :departments do 
    resources :students 
end 

Nếu bạn muốn sử dụng một url thân thiện (như "toán học" thay vì một id), bạn có thể thêm dòng sau vào mô hình bộ phận:

# in models/department.rb 
    def to_param 
    name.downcase 
    end 

Ghi tên phải là duy nhất cho mỗi bộ phận. Ryan B đã thực hiện một số railscast về việc này. Bạn cũng có thể sử dụng đá quý như friendly id.

Bây giờ bạn có thể thêm dòng sau vào quan điểm của bạn:

# links to /math/students 
link_to 'students', department_students_path(current_user.department) 

Nếu bạn sử dụng này thường xuyên, sau đó tạo ra một helper:

# helpers/student_helpers.rb 
def students_path_for_current_user 
    department_students_path(current_user.department) 
end 

# in view 
link_to 'students', students_path_for_current_user 
+0

Tôi muốn _không vượt qua bộ phận người dùng hiện tại trên toàn bộ địa điểm. Ngoài ra, tôi sẽ cần phải thực hiện một helper cho * mọi * tuyến đường mà tôi có –

+0

Xin lỗi, nhưng ít nhất đó là một cách ngắn hơn nhiều để viết nó (không có người giúp đỡ). Không có cách "tốt" để làm những gì bạn muốn, nhưng tôi đã đăng một bản hack có thể có ích. – jokklan

1

Route contraints có thể chấp nhận một proc, vì vậy bạn có thể giải quyết vấn đề này với "hack" sau đây:

concern :student_routes do 
    # all your routes where you want this functionality 
end 

# repeat this for all departments 
scope ":department", constraints: lambda{|req| req.session[:user_id] && User.find(req.session[:user_id]).department.name.downcase == "english"}, defaults: { department: 'english' } do 
    concerns :student_routes 
end 

Mối quan tâm về tuyến đường là một tính năng của đường ray 4. Nếu bạn không Không sử dụng đường ray 4, bạn có thể nhận được các tính năng với đá quý này: https://github.com/rails/routing_concerns.

Bạn cũng có thể sao chép tất cả các tuyến đường cho sinh viên đến tất cả các phạm vi.

0

tôi đã kết thúc xác định nó trong ApplicationController với:

def default_url_options(options={}) 
    {department: current_user.department.name} 
end 

Các người giúp đỡ con đường sẽ điền vào các thông số đã :department điền tự động thì ...

Các vấn đề liên quan