2011-11-22 28 views
7

Tôi đã gặp sự cố với các trường hợp thiếu và lỗi nilClass khi gọi các tuyến đường của mình. Sau khi delving xung quanh bên trong nguồn nó có vẻ như các cuộc gọi generate_method về cơ bản tạo ra một phương pháp mới bằng cách sử dụng khối của phương pháp ban đầu.Làm việc xung quanh việc thiếu bối cảnh trong các phương pháp tuyến đường của Sinatra

get "/" do 
    @some_local_instance.do_something() 
end 

Vì vậy, trong các phương pháp trên có rất tốt có thể là một biến địa phương trong đó lớp được gọi là some_local_instance, tuy nhiên khi vẹt được đánh giá thực tế nó không có bối cảnh như đến nơi phương pháp đã được xác định, vì vậy nó sẽ thất bại.

Lý do tôi hỏi là bởi vì như một phần của kịch bản, tôi có các lớp bên ngoài được nạp khi Sinatra được nạp để đăng ký tuyến và khi các tuyến đó được gọi là tôi cần truy cập một số biến cục bộ trên các lớp này. Một ví dụ sẽ là:

class SomeRouteClass 
    def initialize(sinatra, calculator) 
     @calculator = calculator 
     @sinatra = sinatra 
    end 

    def setup_routes 
     @sinatra.get "/add" do 
      return @calculator.add(1,1) 
     end 
    end 
end 

class Calculator 
    def add(a,b) 
     return a+b; 
    end 
end 

sinatra = Sinatra.new 
calculator = Calculator.new 

routing_class = SomeRouteClass.new(sinatra, calculator) 
routing_class.setup_routes 

sinatra.run! 

Hãy tha thứ cho bất kỳ lỗi chính tả/cú pháp này chỉ là một ví dụ nhanh, nhưng như bạn có thể thấy một lớp đăng ký tuyến đường và khi tuyến đường được đánh trả về một số giá trị được tạo ra bởi một thể hiện của máy tính nó đã diễn ra khi nó được khởi tạo.

Vấn đề tôi có là trong ví dụ này khi tôi thử và chạy/thêm tuyến đường, nó cho tôi biết rằng @calculator là một nilClass, và tôi tin rằng nó nằm xuống theo cách Sinatra chỉ lấy khối mã mà không bối cảnh. Điều này có vẻ tốt cho bất kỳ khuôn mẫu đơn giản, nhưng nếu bạn cần phải làm bất cứ điều gì ưa thích hơn, hoặc muốn giữ mã mô-đun của bạn bằng cách không sử dụng ... Điện thoại

giả định của tôi đúng ở đây? và nếu như vậy có cách nào để giữ bối cảnh vì nó cảm thấy như nó buộc tôi phải viết xấu và khó duy trì mã nếu tôi phải viết mọi thứ dưới dạng thống kê và người độc thân để tương tác từ một lộ trình.

== Sửa ==

đã cơ cấu lại các câu hỏi và nội dung để phản ánh chính xác hơn các vấn đề thực tế, bây giờ mà tôi có một sự hiểu biết vững chắc hơn của thư viện.

+1

Sau khi xem xét một số nguồn khác, có vẻ như nó chỉ sao chép và dán phương pháp được sử dụng với một tuyến đường vào một phương pháp mới bằng cách sử dụng define_method. Cho nên không có ngữ cảnh nào ngoài phương pháp đó ... ngụ ý rằng cách duy nhất xung quanh đó là làm mọi thứ tĩnh, mà dường như sai ... vì khó thay đổi và thử nghiệm theo cách này ... tôi có thể hoàn toàn sai về những gì nó làm mặc dù Ruby vẫn là một ngôn ngữ mới với tôi. – Grofit

+0

Đã cố gắng sử dụng mẫu đối tượng const để giải quyết vấn đề này, nhưng điều này vẫn khiến mọi thứ trở nên khó chịu vì mọi thứ phải tĩnh để làm việc này ... có lý do tại sao họ sao chép thân phương thức vào một phương thức mới vì vậy nó mất tất cả bối cảnh? vì tôi không thể thấy bất kỳ lợi ích nào cho nó, chỉ là nhược điểm ... mặc dù một lần nữa tôi mới làm quen với điều này vì vậy có thể không hoàn toàn hiểu được một số biến chứng đòi hỏi điều này. Chỉ có điều tôi có thể nghĩ là đối tượng cơ thể phương pháp có thể được làm sạch hoặc phương pháp có thể được cập nhật hoặc lấy đi từ cá thể trước khi nó được gọi, tuy nhiên dường như không có khả năng là – Grofit

Trả lời

0

Tôi không chấp nhận câu trả lời này, nhưng sau khi nghiên cứu thêm, có thể bằng ngôn ngữ động như lớp tĩnh của Ruby không phải là cơn ác mộng. Có vẻ như hầu hết các thư viện Ruby chính đều hoạt động đối với các cá thể tĩnh (hoặc consts) được thiết lập sau đó được sử dụng ... điều này có vẻ hơi lạ đối với tôi, như trong quan điểm của nhà cung cấp cơ sở dữ liệu. Nó rất dễ dàng để chỉ gọi lớp cơ sở dữ liệu tĩnh của bạn và kết nối với cơ sở dữ liệu của bạn và sau đó bắt đầu truy vấn, tuy nhiên nếu bạn cần kết nối với 2 cơ sở dữ liệu riêng biệt cùng một lúc. Bạn sẽ cần phải tiếp tục trao đổi các máy chủ với cùng một lớp tĩnh mà sẽ là phiền hà.

Dù sao thì dường như vào lúc này như câu trả lời chỉ là hằng số cho mọi thứ bạn cần để lộ lộ trình, khi bạn đang thử nghiệm, hãy đặt const đó thành mô hình. Nó vẫn có vẻ hơi điên rồ khi gọi những thứ này là consts, khi thực sự chúng không phải là ý nghĩa thực sự của từ khi chúng có thể thay đổi bất cứ lúc nào ... giống như nhiều thứ cho các nhà phát triển ruby ​​mới, nó có vẻ khó hiểu vì lợi ích của nó (tức là elsif, @@ blah, trường hợp biến xác định nếu const của nó hay không).

Như tôi đã nói, tôi sẽ không chấp nhận câu trả lời này nếu ai đó có thể chỉ cho tôi một mô hình tốt hơn để làm điều này, nhưng trong thời điểm này sẽ cho thêm một vài ngày nữa.

+0

Dường như với việc sử dụng helper bạn có thể đặt một số logic trong đó nhưng vẫn không cảm thấy tốt đẹp. Tôi nhìn vào Padrino vì ít nhất nó cung cấp một bộ điều khiển và mỗi bộ điều khiển trợ giúp bởi vẻ ngoài của nó, đóng gói dữ liệu và logic của bạn tốt hơn, nhưng tất cả chỉ được xây dựng trên đầu Sinatra, vì vậy phải có khả năng làm điều này bên trong xây dựng Sinatra mặc định. – Grofit

-2
class SomeRouteClass 
    def initialize(sinatra, calculator) 
     @calculator = calculator 
     @sinatra = sinatra 
    end 

    def calculator 
     @calculator 
    end 

    def setup_routes 
     @sinatra.get "/add" do 
      return calculator.add(1,1) 
     end 
    end 
end 
+1

Gây ra ngoại lệ: biến không xác định cục bộ hoặc phương thức 'máy tính 'for # <# : 0x29c9a60>, tôi thấy những gì bạn đang cố gắng làm ở đó, nhưng nó vẫn có vẻ kỳ quặc. Như chắc chắn khi bạn đăng ký một tuyến đường bạn đang nói cho PATTERN-X gọi METHOD-Y, nhưng Sinatra chỉ cần nhổ ra phương pháp và bin lớp xung quanh nó? vì vậy nó không còn bất kỳ ngữ cảnh nào cho phạm vi bên ngoài phương thức đó? – Grofit

0

Khối được chuyển đến get được đánh giá trong một ngữ cảnh khác với đối tượng Calculator. Sinatra có lẽ đang gọi instance_eval hoặc một trong những người anh em họ của nó. Tuy nhiên, bạn có thể nắm bắt các biến cục bộ từ phạm vi xung quanh, sử dụng phương pháp như sau (phương pháp chưa được kiểm tra, than ôi):

def setup_routes 
    calculator = @calculator 
    @sinatra.get "/add" do 
     return calculator.add(1,1) 
    end 
end 
Các vấn đề liên quan