2010-12-07 30 views
9

Vấn đề phạm vi Noob, tôi tưởng tượng. : \đường ray: làm thế nào để tôi truy cập một phương pháp trong bộ điều khiển ứng dụng của tôi?

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    @locations = get_locations 

    def get_locations 
    Location.where(:active => true).order('name').all 
    end 

end 

Lỗi:

undefined local variable or method `get_locations' for ApplicationController:Class 

Hai câu hỏi: 1) Có gì với lỗi? Tôi có gọi phương thức không chính xác không? 2) Làm cách nào để truy cập phương thức này từ bộ điều khiển phụ?

Trả lời

9

Bạn đang gọi get_locations trong phạm vi lớp học, nhưng phương pháp là phương pháp thể hiện chứ không phải phương thức lớp. Nếu ví dụ bạn đã sử dụng def self.get_locations thì bạn sẽ cung cấp một phương thức lớp, một trong số đó bạn có thể sử dụng trong phạm vi lớp (sau khi bạn đã xác định nó, không phải trước khi bạn đang làm).

Vấn đề ở đây là logic, phương pháp này là gì? Bạn định sử dụng @locations để làm gì? Nếu nó nằm trong khung nhìn ứng dụng của bạn, thì bạn nên đặt phương thức này vào mô-đun ApplicationHelper và gọi nó từ bên trong hành động có liên quan. Nếu bạn muốn nó trong một cái nhìn trên bộ điều khiển khác và bạn muốn sử dụng @locations bên trong phương pháp locations của bạn, có lẽ thiết lập của bạn có thể trông như thế này:

PagesController

class PagesController < ActionController::Base 
    def locations 
    @locations = Location.where(:active => true).order('name').all 
    end 
end 

địa điểm .html.erb

<% @locations.each do |location| %> 
    <%= # do something with 'location' %> 
<% end %> 

Nếu bạn muốn sử dụng bên trong này của bạn application.html.erb bạn có thể si mplify nó khá một số ..

ApplicationController

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    def locations 
    Location.where(:active => true).order('name').all 
    end 
end 

application.html.erb

<% locations.each do |location| %> 
    <%= # do something with location %> 
<% end %> 

Câu trả lời nắm để logic, và để thực sự tìm ra chính xác những gì bạn đang tìm kiếm, biết thêm chi tiết có lẽ sẽ được yêu cầu.

+0

Tôi cần @locations có sẵn để bố trí ứng dụng của tôi, nhưng cũng để điều khiển khác. Nơi tốt nhất để đặt này? – jmccartie

+0

Nếu bạn cần truy cập nó trong bố cục ứng dụng của bạn thì bộ điều khiển ứng dụng của bạn có lẽ là nơi tốt nhất để đặt nó vì nó sẽ có sẵn trên các bộ điều khiển của bạn. Yêu cầu trình điều khiển gọi 'before_filter' trên phương thức' get_locations' để điền biến '@ locations' instance –

1

Tôi tưởng tượng rằng dòng này:

@locations = get_locations 

... đang cố gắng truy cập vào các phương pháp trình độ lớp get_locations và không phải là phương pháp dụ.

Đầu mối ở đây là thông báo lỗi cho thấy rằng nó không thể tìm thấy nó trên lớp chính nó (ApplicationController: Class) và không phải là một thể hiện của lớp đó. Điều đó có nghĩa rằng bạn đang ở trong phạm vi lớp, không phải phạm vi cá thể.

này sẽ sửa chữa nó:

def self.get_locations 
    Location.where(:active => true).order('name').all 
    end 
+0

@@ địa điểm là gần như chắc chắn không phải những gì bạn muốn. Một biến lớp thực sự của nó, mà trong Ruby được chia sẻ giữa tất cả các cá thể của lớp, * bao gồm các lớp con * và có thể có một số hậu quả thực sự kỳ lạ. – karmajunkie

+0

Woops, ghi chú (và chỉnh sửa). Cảm ơn. – markquezada

3

Bạn đang gọi nó từ phạm vi lớp học, chứ không phải từ một phạm vi dụ. nhiều khả năng những gì bạn muốn là như sau:

class ApplicationController < ActionController::Base 
    protect_from_forgery 
    before_filter :setup_locations 


    private 
    def setup_locations 
    @locations = Location.where(:active => true).order('name').all 
    end 

end 

Để làm cho công việc ví dụ ban đầu của bạn, bạn sẽ cần phải thực hiện #get_locations xác định trên bản thân (mà chỉ vào lớp tại định nghĩa), như vậy:

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    @locations = get_locations 

    def self.get_locations 
    Location.where(:active => true).order('name').all 
    end 

end 

Vấn đề với mã đó là @locations sẽ chỉ có sẵn từ cấp lớp dưới dạng biến mẫu lớp, có thể so sánh với biến tĩnh ở hầu hết các ngôn ngữ khác và có thể không phải là thứ bạn muốn.

+0

Rất kỳ quặc, ví dụ thứ hai tạo ra cùng một lỗi chính xác. Ví dụ đầu tiên dường như hoạt động tốt - nhưng điều này sẽ hạn chế khả năng gọi phương thức này từ một bộ điều khiển khác, đúng không? (nhờ sự giúp đỡ của bạn!) – jmccartie

+0

Nó sẽ, nhưng nếu bạn muốn sử dụng cùng một phương pháp từ bộ điều khiển khác, bạn đặt nó trong bộ điều khiển ứng dụng của bạn, mà nên là lớp cơ sở cho bộ điều khiển của bạn anyway (ApplicationController subclasses ActionController :: Base thường) – karmajunkie

1

Ngay cả những câu hỏi là khá cũ, bạn cũng có thể gọi hành động điều khiển của bạn ở bất cứ đâu chỉ bằng cách gọi:

ApplicationController.new.get_locations 
Các vấn đề liên quan