2009-08-26 42 views
6

Tôi có một giao diện Flickr mà tôi đã viết một lúc trước và một phần của nó làm phiền tôi và tôi muốn làm cho nó đẹp hơn. Cách nó hoạt động là tôi sử dụng phương pháp thiếu để xây dựng các tham số url cho cuộc gọi flickr từ các phương thức được gọi trên đối tượng flickr, ví dụ.Làm thế nào để phát hiện sự kết thúc của một chuỗi phương pháp trong Ruby

@flickr.groups.pools.getPhotos(:user_id => "[email protected]", :group_id => "[email protected]") 

Những 'phương pháp gọi là' xây dựng một cuộc gọi api trông như thế này

http://api.flickr.com/services/rest/?method=groups.pools.getPhotos&user_id=1848466274& group_id= [email protected] 

(Tôi đã rời khỏi api chút key) Nó làm điều này bằng cách ghi nhớ từng 'phương pháp' cho đến khi một phương pháp được gọi với các đối số tại thời điểm nó xây dựng url và thực hiện cuộc gọi tới Flickr.

Lý do tôi thực hiện phương pháp này là mã ruby ​​khớp với tài liệu trên trang Flickr, bạn có thể sao chép và dán nó và hầu hết sẽ hoạt động, và hy vọng nó sẽ làm cho nó trở nên linh hoạt hơn đối với thay đổi api vì tôi không có phương pháp mã hóa cứng.

Điều gì gây khó chịu cho điều này mặc dù trong ví dụ này, id nhóm đang được chuyển sang phương thức getPhotos thay vì phương pháp nhóm. Tôi sẽ khá giống như thế này.

@flickr.groups(:group_id => "[email protected]").pools.getPhotos(:user_id => "[email protected]") 

Vì vậy, câu hỏi của tôi. Có cách nào trong Ruby mà tôi có thể phát hiện ra phương pháp cuối cùng đã được gọi để tôi có thể kích hoạt cuộc gọi tới Flickr không?

Trả lời

6

Vì tôi không thể nghĩ ra bất kỳ cách nào để phát hiện cuộc gọi phương thức cuối cùng, tôi sẽ đề xuất một cách tiếp cận khác. Nó tương tự như những gì ActiveRecord thực hiện; một lớp proxy xây dựng các tùy chọn và không tìm nạp dữ liệu cho đến khi bạn gọi một phương thức hoạt động trên dữ liệu.

class Flickr 
    def initialize 
    @result = FlickrResult.new 
    end 

    def method_missing(method, *args, &block) 
    if @result.data.respond_to?(method) 
     @result.run(method, args, block) 
    else 
     @result.append(method, args[0]) 
     return self 
    end 
    end 

    class FlickrResult 
    attr_reader :data 

    def initialize 
     @data = [] 
     @keys = [] 
     @options = {} 
    end 

    def append(key, options) 
     @keys << key 
     @options.merge!(options) if options 
    end 

    def run(method, args, block) 
     if [email protected]_run 
     fetch_data 
     end 

     @data.send(method, *args, &block) 
    end 

    def fetch_data 
     puts "Only runs once!" 
     @url = @keys.join(".") + "?" + @options.map {|k, v| "#{k}=#{v}" }.join("&") 
     # use @url and fetch data.. 
     @data = ["foo", "bar"] 

     @did_run = true 
    end 
    end 
end 

@flickr = Flickr.new 
@flickr.groups(:group_id => "123").pools.thing.users(:user_id => "456") 

@flickr.each {|f| p f } 
# => "Only runs once!" 
# => "foo" 
# => "bar" 
p @flickr.map {|f| f.upcase } 
# => ["FOO", "BAR"] 

Nó chỉ fetches các dữ liệu khi bạn each hay map nó hay bất cứ điều gì (bất kỳ phương pháp mảng).

+0

Tại sao "@flickr" trong phạm vi bên ngoài? Lợi thế của việc biến nó thành một biến cá thể của Object so với biến cục bộ là gì? –

+0

Không có lợi thế (trong trường hợp này). Chỉ là một brainfart, không có cân nhắc đặc biệt trong nó :) –

+0

Vâng, đây là một phương pháp thay thế tôi đã xem xét. Và sử dụng ghi nhớ trên các thuộc tính. Tôi đã hy vọng có một số phương pháp sôi nổi mà tôi không biết. – Henry

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