2010-05-26 28 views
37

Đây là cách để chuyển đổi một chuỗi để một lớp trong Rails/Ruby:Làm cách nào để chuyển đổi chuỗi thành phương thức lớp?

p = "Post" 
Kernel.const_get(p) 
eval(p) 
p.constantize 

Nhưng những gì nếu tôi lấy một phương pháp từ một mảng/đối tượng kỷ lục hoạt động như:

Post.description 

nhưng nó có thể là

Post.anything 

nơi bất kỳ thứ gì là một chuỗi như anything = "description".

Điều này rất hữu ích vì tôi muốn cấu trúc lại một lớp rất lớn và giảm dòng mã và lặp lại. Làm thế nào tôi có thể làm cho nó hoạt động?

+0

bạn nhận ra bạn chỉ cần một trong {const_get, eval, constantize}, phải ? – klochner

+0

có. Tất nhiên tôi làm. như tôi vừa thử nghiệm 3. – kgpdeveloper

Trả lời

61
Post.send(anything) 
+0

hoạt động hoàn hảo, cảm ơn. đã giảm rất nhiều dòng mã xuống chỉ còn một vài dòng. – kgpdeveloper

+0

Vì vậy, bạn có thể chấp nhận câu trả lời. – shingara

+0

nếu phương pháp của tôi là: def test = (string) {puts string}. Tôi không nghĩ Post.send ("test", "hi") sẽ hoạt động tốt .. –

15

Mặc dù eval có thể là công cụ hữu ích cho loại điều này và những thứ từ các nền tảng khác có thể sử dụng thường xuyên như người có thể mở, thật sự rất nguy hiểm khi sử dụng một cách tình cờ. Eval ngụ ý rằng bất cứ điều gì có thể xảy ra nếu bạn không cẩn thận.

Một phương pháp an toàn hơn là thế này:

on_class = "Post" 
on_class.constantize.send("method_name") 
on_class.constantize.send("method_name", arg1) 

Object # gửi sẽ gọi bất cứ phương pháp nào bạn muốn. Bạn có thể gửi biểu tượng hoặc chuỗi và cung cấp phương thức không phải là riêng tư hoặc được bảo vệ, nên hoạt động.

+0

Điều này đã thực hiện các phương thức tùy ý. An ninh dường như không phải là yếu tố chính ở đây. – Chuck

+0

Phương pháp tùy ý khác rất nhiều so với mã tùy ý. Tôi nghi ngờ bạn có một phương pháp "DROP ALL TABLES" trên lớp của bạn. Nó cũng là tiểu học để xác minh rằng một chuỗi nhất định là an toàn hoặc không sử dụng như một tên phương pháp, bạn có thể có một danh sách trắng đơn giản để kiểm tra, tuy nhiên đánh giá sự nguy hiểm của một khối eval tùy ý là không thể. – tadman

0

Hãy thử điều này:

class Test 
def method_missing(id, *args) 
    puts "#{id} - get your method name" 
    puts "#{args} - get values" 
end 
end 

a = Test.new 
a.name('123') 

Vì vậy, cú pháp chung sẽ a.<anything>(<any argument>).

12

Vì điều này được gắn thẻ dưới dạng câu hỏi Ruby on Rails, tôi sẽ giải thích một chút.

Trong Rails 3, giả sử title là tên của một cánh đồng vào một đối tượng ActiveRecord, thì sau đây cũng là hợp lệ:

@post = Post.new 
method = "title" 

@post.send(method)    # => @post.title 
@post.send(method+'=',"New Name") # => @post.title = "New Name" 
Các vấn đề liên quan