2010-07-10 32 views
12

Tôi đang xác định động một phương thức trong một mô-đun và tôi muốn kiểm tra xem khi phương thức được ràng buộc với một cá thể lớp mà nội dung của phương thức là thứ tôi ' m mong đợi. Có cách nào để xuất (như văn bản) của cơ thể của một phương pháp?Lập trình meta: phần thân phương thức xuất dưới dạng văn bản

Mô-đun controller_mixins.rb:

module ControllerMixin 

    instance_eval "def search_by_vendor (*args) \n" \ 
    " @#{self.class.name.sub(/Controller/, '').tableize} = #{self.class.name.sub(/Controller/, '')}.find_all_by_vendor_id(params[:vendor_id]) \n"\ 
    "respond_to do |format| \n" \ 
    " format.html { render :template=>'/#{self.class.name.sub(/Controller/, '').tableize}/index', :layout=>'vendor_info'} \n" \ 
    " format.xml { render :xml => @#{self.class.name.sub(/Controller/, '').tableize} } \n" \ 
    "end \n"\ 
    "end \n" 

end 

lớp được trộn với:

class VendorOrdersController < ApplicationController 
    # GET /vendor_orders 
    # GET /vendor_orders.xml 
    require 'controller_mixins' 
    include ControllerMixin 
<rest of class> 

Vì vậy, tôi muốn xem thi hành mixin khi áp dụng cho VendorOrdersController lẽ qua script/console cho thuận tiện.

CẬP NHẬT: Mỗi @ ~/Tôi đã lưu chuỗi vào biến và puts 'd. Điều đó làm việc hoàn hảo. Điều này mang lại một lỗi trong mã của tôi (lý do tôi muốn xem mã ở vị trí đầu tiên). Mã dưới đây là tốt hơn nhiều, và hoạt động như mong đợi.

module ControllerMixin 

    def self.included(mod) 
    method_body = "def search_by_vendor \n" \ 
     " @#{mod.name.sub(/Controller/, '').tableize} = #{mod.name.sub(/Controller/, '')}.find_all_by_vendor_id(params[:vendor_id]) \n"\ 
     "respond_to do |format| \n" \ 
     " format.html { render :template=>'/#{mod.name.sub(/Controller/, '').tableize}/index', :layout=>'vendor_info'} \n" \ 
     " format.xml { render :xml => @#{mod.name.sub(/Controller/, '').tableize} } \n" \ 
     "end \n"\ 
    "end \n" 

    puts method_body 
    mod.class_eval(method_body) 
    end 

end 
+0

define_method là bạn của bạn – shingara

+0

Có thể bạn sẽ muốn sử dụng 'tài liệu tại đây' ('CODE << - ... CODE') thay vì chuỗi được ghép nối. Định dạng đẹp hơn nhiều. – Chubas

+0

Tại sao tôi không nghe nói về các tài liệu này ở đây Đây là một gửi GOD. Cảm ơn bạn. Giải thích tốt (trên blog của người khác): http://blog.commonthread.com/2007/12/20/tip-ruby-here-document – SooDesuNe

Trả lời

5

Không, bạn không thể lấy mã nguồn đằng sau phương thức.

Điều tốt nhất bạn có thể làm là lấy đối tượng Method đại diện cho phương pháp sử dụng Object#method. Ví dụ:

m = VendorOrdersController.method(:search_by_vendor) 

Nhưng bạn sẽ thấy rằng không có nhiều hơn một Method#name, Method#arity, Method#source_location vv

Trong trường hợp của bạn tuy nhiên, tại sao không chỉ đơn giản là lưu trữ các chuỗi trong một biến, in trước khi sử dụng instance_eval?

Bất kể, instance_eval của bạn sẽ được thực hiện tại thời điểm khai báo mô-đun. Bạn có thể muốn bọc nó trong một cuộc gọi lại included để nó được thực hiện tại thời điểm đưa vào.

module ControllerMixin 
    def self.included(mod) 
    mod.instance_eval([...]) 
    end 
end 
+0

Xin lỗi Shtééf, chỉ cần nhận thấy bạn đã thực hiện cùng một điểm ở giữa câu trả lời của bạn . Tôi sẽ rời bỏ tôi vào lúc này vì một người khác có thể bỏ lỡ nó như tôi đã làm. – Joc

+1

Bạn không thể chạy '.method (: search_by_vendor) .source'? – tekknolagi

2

Cách tốt nhất để đảm bảo bạn nhận được kết quả mong muốn của bạn là kết quả ... là viết một bài kiểm tra.

Ngoài ra - tôi không chấp nhận việc sử dụng instance_eval như thế. Nếu bạn PHẢI lập trình meta như vậy, hãy sử dụng define_method hoặc bạn có thể thoát khỏi mà không thực hiện bất kỳ điều gì bằng cách chuyển một tham số từ các tuyến đường, chắc chắn, đó là cách gõ nhiều hơn một chút, nhưng quá trình lập trình meta đó chỉ là rất nhỏ.

+0

Tôi trông giống như define_method về cơ bản thúc đẩy một khối để một phương pháp. Cho rằng tôi sẽ không biết tên phương thức của tôi hoặc biến nội bộ, làm thế nào tôi có thể xác định đây là một khối nói chung đủ? – SooDesuNe

+0

@SooDesuNe: Vì khối bạn đưa cho 'define_method' là một đóng, bạn sẽ có quyền truy cập vào các biến cục bộ. Hãy thử nó; trong trường hợp của bạn nó tầm thường và sẽ được ** nhiều ** đẹp hơn. –

2

Bạn không thể gán chuỗi cho biến trước khi instance_eval chạy và xuất nó ra bàn điều khiển?

Khi chuỗi của bạn xác định toàn bộ phương pháp bạn về cơ bản đã có mã nguồn.

0

như câu trả lời ở trên cho biết, cách tốt nhất để làm những gì bạn đang cố gắng làm là với define_method.

nếu có ai đang tìm kiếm "Meta-lập trình: cơ thể phương pháp đầu ra dưới dạng văn bản" thử điều này:

nếu bạn muốn lấy mã của một lớp hoặc một phương pháp kiểm tra ParseTreeruby2ruby

ParseTree có thể lấy cây cú pháp trừu tượng của một lớp hoặc phương thức và tạo ra "các biểu thức biểu tượng", giống như lisp, nó trông giống như danh sách các danh sách các biểu tượng, và rất thú vị.

ruby2ruby nhận các s-exp này và biến nó thành ruby ​​thông thường.

được cảnh báo, ParseTree hiện không hoạt động trong ruby ​​1.9.

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