facebooker-lite 1.0.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. data/.autotest +15 -0
  2. data/CHANGELOG.rdoc +24 -0
  3. data/COPYING.rdoc +19 -0
  4. data/Manifest.txt +114 -0
  5. data/README.rdoc +120 -0
  6. data/Rakefile +94 -0
  7. data/TODO.rdoc +4 -0
  8. data/facebooker.gemspec +42 -0
  9. data/generators/xd_receiver/templates/xd_receiver.html +10 -0
  10. data/generators/xd_receiver/templates/xd_receiver_ssl.html +10 -0
  11. data/generators/xd_receiver/xd_receiver_generator.rb +10 -0
  12. data/init.rb +25 -0
  13. data/install.rb +12 -0
  14. data/lib/facebooker.rb +261 -0
  15. data/lib/facebooker/adapters/adapter_base.rb +91 -0
  16. data/lib/facebooker/adapters/bebo_adapter.rb +77 -0
  17. data/lib/facebooker/adapters/facebook_adapter.rb +60 -0
  18. data/lib/facebooker/admin.rb +42 -0
  19. data/lib/facebooker/application.rb +37 -0
  20. data/lib/facebooker/attachment.rb +51 -0
  21. data/lib/facebooker/batch_request.rb +45 -0
  22. data/lib/facebooker/data.rb +57 -0
  23. data/lib/facebooker/feed.rb +78 -0
  24. data/lib/facebooker/logging.rb +44 -0
  25. data/lib/facebooker/mobile.rb +20 -0
  26. data/lib/facebooker/mock/service.rb +50 -0
  27. data/lib/facebooker/mock/session.rb +18 -0
  28. data/lib/facebooker/model.rb +139 -0
  29. data/lib/facebooker/models/affiliation.rb +10 -0
  30. data/lib/facebooker/models/album.rb +11 -0
  31. data/lib/facebooker/models/applicationproperties.rb +39 -0
  32. data/lib/facebooker/models/applicationrestrictions.rb +10 -0
  33. data/lib/facebooker/models/comment.rb +9 -0
  34. data/lib/facebooker/models/cookie.rb +10 -0
  35. data/lib/facebooker/models/education_info.rb +11 -0
  36. data/lib/facebooker/models/event.rb +28 -0
  37. data/lib/facebooker/models/family_relative_info.rb +7 -0
  38. data/lib/facebooker/models/friend_list.rb +16 -0
  39. data/lib/facebooker/models/group.rb +36 -0
  40. data/lib/facebooker/models/info_item.rb +10 -0
  41. data/lib/facebooker/models/info_section.rb +10 -0
  42. data/lib/facebooker/models/location.rb +8 -0
  43. data/lib/facebooker/models/message_thread.rb +89 -0
  44. data/lib/facebooker/models/notifications.rb +17 -0
  45. data/lib/facebooker/models/page.rb +46 -0
  46. data/lib/facebooker/models/photo.rb +19 -0
  47. data/lib/facebooker/models/tag.rb +12 -0
  48. data/lib/facebooker/models/user.rb +751 -0
  49. data/lib/facebooker/models/video.rb +9 -0
  50. data/lib/facebooker/models/work_info.rb +10 -0
  51. data/lib/facebooker/parser.rb +970 -0
  52. data/lib/facebooker/rails/backwards_compatible_param_checks.rb +31 -0
  53. data/lib/facebooker/rails/controller.rb +353 -0
  54. data/lib/facebooker/rails/extensions/action_controller.rb +47 -0
  55. data/lib/facebooker/rails/extensions/rack_setup.rb +16 -0
  56. data/lib/facebooker/rails/extensions/routing.rb +15 -0
  57. data/lib/facebooker/rails/facebook_pretty_errors.rb +22 -0
  58. data/lib/facebooker/rails/facebook_request_fix.rb +28 -0
  59. data/lib/facebooker/rails/facebook_request_fix_2-3.rb +31 -0
  60. data/lib/facebooker/rails/facebook_session_handling.rb +68 -0
  61. data/lib/facebooker/rails/facebook_url_rewriting.rb +60 -0
  62. data/lib/facebooker/rails/helpers/fb_connect.rb +75 -0
  63. data/lib/facebooker/rails/integration_session.rb +38 -0
  64. data/lib/facebooker/rails/profile_publisher_extensions.rb +42 -0
  65. data/lib/facebooker/rails/publisher.rb +608 -0
  66. data/lib/facebooker/rails/routing.rb +49 -0
  67. data/lib/facebooker/rails/test_helpers.rb +68 -0
  68. data/lib/facebooker/rails/utilities.rb +22 -0
  69. data/lib/facebooker/server_cache.rb +24 -0
  70. data/lib/facebooker/service.rb +103 -0
  71. data/lib/facebooker/service/base_service.rb +19 -0
  72. data/lib/facebooker/service/curl_service.rb +44 -0
  73. data/lib/facebooker/service/net_http_service.rb +12 -0
  74. data/lib/facebooker/service/typhoeus_multi_service.rb +27 -0
  75. data/lib/facebooker/service/typhoeus_service.rb +17 -0
  76. data/lib/facebooker/session.rb +786 -0
  77. data/lib/facebooker/stream_post.rb +19 -0
  78. data/lib/facebooker/version.rb +9 -0
  79. data/lib/net/http_multipart_post.rb +123 -0
  80. data/lib/rack/facebook.rb +89 -0
  81. data/lib/rack/facebook_session.rb +21 -0
  82. data/lib/tasks/facebooker.rake +19 -0
  83. data/lib/tasks/facebooker.rb +2 -0
  84. data/lib/tasks/tunnel.rake +46 -0
  85. data/rails/init.rb +1 -0
  86. data/setup.rb +1585 -0
  87. data/templates/layout.erb +24 -0
  88. data/test/facebooker/adapters_test.rb +191 -0
  89. data/test/facebooker/admin_test.rb +102 -0
  90. data/test/facebooker/application_test.rb +110 -0
  91. data/test/facebooker/attachment_test.rb +72 -0
  92. data/test/facebooker/batch_request_test.rb +83 -0
  93. data/test/facebooker/data_test.rb +86 -0
  94. data/test/facebooker/logging_test.rb +43 -0
  95. data/test/facebooker/mobile_test.rb +45 -0
  96. data/test/facebooker/model_test.rb +133 -0
  97. data/test/facebooker/models/event_test.rb +15 -0
  98. data/test/facebooker/models/page_test.rb +56 -0
  99. data/test/facebooker/models/photo_test.rb +16 -0
  100. data/test/facebooker/models/user_test.rb +1074 -0
  101. data/test/facebooker/rails/facebook_request_fix_2-3_test.rb +25 -0
  102. data/test/facebooker/rails/facebook_url_rewriting_test.rb +76 -0
  103. data/test/facebooker/rails/integration_session_test.rb +13 -0
  104. data/test/facebooker/rails/publisher_test.rb +538 -0
  105. data/test/facebooker/rails_integration_test.rb +1543 -0
  106. data/test/facebooker/server_cache_test.rb +44 -0
  107. data/test/facebooker/service_test.rb +58 -0
  108. data/test/facebooker/session_test.rb +883 -0
  109. data/test/facebooker_test.rb +1263 -0
  110. data/test/fixtures/multipart_post_body_with_only_parameters.txt +33 -0
  111. data/test/fixtures/multipart_post_body_with_single_file.txt +38 -0
  112. data/test/fixtures/multipart_post_body_with_single_file_that_has_nil_key.txt +38 -0
  113. data/test/net/http_multipart_post_test.rb +52 -0
  114. data/test/rack/facebook_session_test.rb +34 -0
  115. data/test/rack/facebook_test.rb +73 -0
  116. data/test/rails_test_helper.rb +36 -0
  117. data/test/test_helper.rb +74 -0
  118. metadata +278 -0
@@ -0,0 +1,60 @@
1
+ module Facebooker
2
+
3
+
4
+ class FacebookAdapter < AdapterBase
5
+
6
+ def canvas_server_base
7
+ "apps.facebook.com"
8
+ end
9
+
10
+ def api_server_base
11
+ "api.facebook.com"
12
+ end
13
+
14
+ def video_server_base
15
+ "api-video.facebook.com"
16
+ end
17
+
18
+ def www_server_base_url
19
+ "www.facebook.com"
20
+ end
21
+
22
+ def api_rest_path
23
+ "/restserver.php"
24
+ end
25
+
26
+ def api_key
27
+ ENV['FACEBOOK_API_KEY'] || super
28
+ end
29
+
30
+ def secret_key
31
+ ENV['FACEBOOK_SECRET_KEY'] || super
32
+ end
33
+
34
+ def is_for?(application_context)
35
+ application_context == :facebook
36
+ end
37
+
38
+
39
+
40
+ def login_url_base
41
+ "http://#{www_server_base_url}/login.php?api_key=#{api_key}&v=1.0"
42
+ end
43
+
44
+ def install_url_base
45
+ "http://#{www_server_base_url}/install.php?api_key=#{api_key}&v=1.0"
46
+ end
47
+
48
+ def connect_permission_url_base
49
+ "http://#{www_server_base_url}/connect/prompt_permissions.php?api_key=#{api_key}&v=1.0"
50
+ end
51
+
52
+ def permission_url_base
53
+ "http://#{www_server_base_url}/authorize.php?api_key=#{api_key}&v=1.0"
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+
@@ -0,0 +1,42 @@
1
+ module Facebooker
2
+ class Admin
3
+ def initialize(session)
4
+ @session = session
5
+ end
6
+
7
+ # ** BETA ***
8
+ # +properties+: Hash of properties you want to set
9
+ def set_app_properties(properties)
10
+ properties = properties.respond_to?(:to_json) ? properties.to_json : properties
11
+ (@session.post 'facebook.admin.setAppProperties', :properties => properties) == '1'
12
+ end
13
+
14
+ # ** BETA ***
15
+ # +properties+: Hash of properties you want to view.
16
+ def get_app_properties(*properties)
17
+ json = @session.post('facebook.admin.getAppProperties', :properties => properties.to_json)
18
+ hash = Facebooker.json_decode(CGI.unescapeHTML(json))
19
+ @properties = ApplicationProperties.from_hash(hash)
20
+ end
21
+
22
+ # ** BETA ***
23
+ # +restrictions+: Hash of restrictions you want to set.
24
+ def set_restriction_info(restrictions)
25
+ restrictions = restrictions.respond_to?(:to_json) ? restrictions.to_json : restrictions
26
+ (@session.post 'facebook.admin.setRestrictionInfo', :restriction_str => restrictions) == '1'
27
+ end
28
+
29
+ # ** BETA ***
30
+ def get_restriction_info(*restrictions)
31
+ json = @session.post('facebook.admin.getRestrictionInfo')
32
+ hash = Facebooker.json_decode(CGI.unescapeHTML(json))
33
+ @restrictions = ApplicationRestrictions.from_hash(hash)
34
+ end
35
+
36
+ # Integration points include..
37
+ # :notifications_per_day, :requests_per_day, :emails_per_day, :email_disable_message_location
38
+ def get_allocation(integration_point)
39
+ @session.post('facebook.admin.getAllocation', :integration_point_name => integration_point.to_s).to_i
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ module Facebooker
2
+ class Application
3
+ def initialize(session)
4
+ @session = session
5
+ end
6
+
7
+ # +properties+: Hash of properties of the desired application. Specify exactly one of: application_id, application_api_key or application_canvas_name
8
+ # eg: application.get_public_info(:application_canvas_name => ENV['FACEBOOKER_RELATIVE_URL_ROOT'])
9
+ def get_public_info(properties)
10
+ (@session.post 'facebook.application.getPublicInfo', properties)
11
+ end
12
+
13
+ # facebook_session.application.add_global_news [{ :message => 'Hi all users', :action_link => { :text => "Hi application", :href => 'http://facebook.er/' }}], 'http://facebook.er/icon.png'
14
+ def add_global_news(news, image=nil)
15
+ params = {}
16
+ params[:news] = news
17
+ params[:image] = image if image
18
+ @session.post('facebook.dashboard.addGlobalNews', params)
19
+ end
20
+
21
+ # currently bugged on Facebook; returns all
22
+ # facebook_session.application.get_global_news '310354202543'
23
+ def get_global_news(*news_ids)
24
+ params = {}
25
+ params[:news_ids] = news_ids.flatten if news_ids
26
+ @session.post('facebook.dashboard.getGlobalNews', params)
27
+ end
28
+
29
+ # facebook_session.application.clear_global_news '310354202543'
30
+ def clear_global_news(*news_ids)
31
+ params = {}
32
+ params[:news_ids] = news_ids.flatten if news_ids
33
+ @session.post('facebook.dashboard.clearGlobalNews', params)
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,51 @@
1
+ class Facebooker::Attachment
2
+
3
+ def initialize
4
+ @storage = {}
5
+ end
6
+
7
+ def self.hash_populating_accessor(*names)
8
+ names.each do |name|
9
+ define_method(name) do
10
+ @storage[name]
11
+ end
12
+ define_method("#{name}=") do |val|
13
+ @storage[name]=val
14
+ end
15
+ end
16
+ end
17
+
18
+ hash_populating_accessor :name,:href, :comments_xid, :description, :caption
19
+
20
+ def add_media(hash)
21
+ @storage[:media]||=[]
22
+ @storage[:media] << hash
23
+ end
24
+
25
+ def add_image(source,href)
26
+ add_media({:type=>"image",:src=>source,:href=>href})
27
+ end
28
+
29
+ def add_mp3(source,title=nil,artist=nil,album=nil)
30
+ params = {:src=>source,:type=>"mp3"}
31
+ params[:title] = title unless title.nil?
32
+ params[:artist] = artist unless artist.nil?
33
+ params[:album] = album unless album.nil?
34
+ add_media(params)
35
+ end
36
+
37
+ def add_flash(swfsource, imgsource, width=nil, height=nil, expanded_width=nil, expanded_height=nil)
38
+ params={:type=>"flash",:swfsrc=>swfsource,:imgsrc=>imgsource}
39
+ params[:width] = width unless width.nil?
40
+ params[:height] = height unless height.nil?
41
+ params[:expanded_width] = expanded_width unless expanded_width.nil?
42
+ params[:expanded_height] = expanded_height unless expanded_height.nil?
43
+ add_media(params)
44
+ end
45
+
46
+ def to_hash
47
+ @storage
48
+ end
49
+
50
+
51
+ end
@@ -0,0 +1,45 @@
1
+ module Facebooker
2
+ class BatchRequest
3
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^respond_to\?$|^new|object_id$)/ }
4
+ attr_reader :uri
5
+ attr_reader :method
6
+ class UnexecutedRequest < StandardError; end
7
+ def initialize(params,proc)
8
+ @exception = nil
9
+ @result = nil
10
+ @method = params[:method]
11
+ @uri = params.map{|k,v| "#{k}=#{CGI.escape(v.to_s)}"}.join("&")
12
+ @proc = proc
13
+ end
14
+
15
+ def result=(result_object)
16
+ @result = @proc.nil? ? result_object : @proc.call(result_object)
17
+ end
18
+
19
+ def exception_raised=(ex)
20
+ @exception=ex
21
+ end
22
+
23
+ def exception_raised?
24
+ @exception.nil? ? false : raise(@exception)
25
+ end
26
+
27
+ def respond_to?(name)
28
+ super || @result.respond_to?(name)
29
+ end
30
+
31
+ def ===(other)
32
+ other === @result
33
+ end
34
+
35
+ def method_missing(name,*args,&proc)
36
+ if @exception
37
+ raise @exception
38
+ elsif @result.nil?
39
+ raise UnexecutedRequest.new("You must execute the batch before accessing the result: #{@uri}")
40
+ else
41
+ @result.send(name,*args,&proc)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ module Facebooker
2
+ class Data
3
+ def initialize(session)
4
+ @session = session
5
+ end
6
+
7
+ ##
8
+ # ** BETA ***
9
+ # Sets a cookie on Facebook
10
+ # +user+ The user for whom this cookie needs to be set.
11
+ # +name+ Name of the cookie
12
+ # +value+ Value of the cookie
13
+ # Optional:
14
+ # +expires+ Time when the cookie should expire. If not specified, the cookie never expires.
15
+ # +path+ Path relative to the application's callback URL, with which the cookie should be associated. (default value is /?
16
+ def set_cookie(user, name, value, expires=nil, path=nil)
17
+ @session.post('facebook.data.setCookie',
18
+ :uid => User.cast_to_facebook_id(user),
19
+ :name => name,
20
+ :value => value,
21
+ :expires => expires,
22
+ :path => path) {|response| response == '1'}
23
+ end
24
+
25
+ ##
26
+ # ** BETA ***
27
+ # Gets a cookie stored on Facebook
28
+ # +user+ The user from whom to get the cookies.
29
+ # Optional:
30
+ # +name+ The name of the cookie. If not specified, all the cookies for the given user get returned.
31
+ def get_cookies(user, name=nil)
32
+ @cookies = @session.post(
33
+ 'facebook.data.getCookies', :uid => User.cast_to_facebook_id(user), :name => name) do |response|
34
+ response.map do |hash|
35
+ Cookie.from_hash(hash)
36
+ end
37
+ end
38
+ end
39
+
40
+ ##
41
+ # ** BETA ***
42
+ # Gets a preference stored on Facebook
43
+ # +pref_id+ The id of the preference to get
44
+ def get_preference(pref_id)
45
+ @session.post('facebook.data.getUserPreference', :pref_id=>pref_id)
46
+ end
47
+
48
+ ##
49
+ # ** BETA ***
50
+ # Sets a preference on Facebook
51
+ # +pref_id+ The id of the preference to set
52
+ # +value+ The value to set for this preference
53
+ def set_preference(pref_id, value)
54
+ @session.post('facebook.data.setUserPreference', :pref_id=>pref_id, :value=>value)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,78 @@
1
+ module Facebooker
2
+ module Feed
3
+ METHODS = {'Action' => 'facebook.feed.publishActionOfUser', 'Story' => 'facebook.feed.publishStoryToUser',
4
+ 'TemplatizedAction' => 'facebook.feed.publishTemplatizedAction' }
5
+
6
+ class ActionBase
7
+ 1.upto(4) do |num|
8
+ attr_accessor "image_#{num}"
9
+ attr_accessor "image_#{num}_link"
10
+ end
11
+
12
+ def add_image(image,link=nil)
13
+ 1.upto(4) do |num|
14
+ if send("image_#{num}").blank?
15
+ send("image_#{num}=",image)
16
+ send("image_#{num}_link=",link) unless link.nil?
17
+ return num
18
+ end
19
+ end
20
+ end
21
+
22
+
23
+ protected
24
+ def image_params
25
+ image_hash = {}
26
+ 1.upto(4) do |num|
27
+ image_attribute = "image_#{num}"
28
+ image_link_attribute = image_attribute + "_link"
29
+ self.__send__(image_attribute) ? image_hash[image_attribute] = self.__send__(image_attribute) : nil
30
+ self.__send__(image_link_attribute) ? image_hash[image_link_attribute] = self.__send__(image_link_attribute) : nil
31
+ end
32
+ image_hash
33
+ end
34
+ end
35
+
36
+ ##
37
+ # Representation of a templatized action to be published into a user's news feed
38
+ class TemplatizedAction < ActionBase
39
+ attr_accessor :page_actor_id, :title_template, :title_data, :body_template, :body_data, :body_general, :target_ids
40
+
41
+ def to_params
42
+ raise "Must set title_template" if self.title_template.nil?
43
+ { :page_actor_id => page_actor_id,
44
+ :title_template => title_template,
45
+ :title_data => convert_json(title_data),
46
+ :body_template => body_template,
47
+ :body_data => convert_json(body_data),
48
+ :body_general => body_general,
49
+ :target_ids => target_ids }.merge image_params
50
+ end
51
+
52
+ def convert_json(hash_or_string)
53
+ (hash_or_string.is_a?(Hash) and hash_or_string.respond_to?(:to_json)) ? hash_or_string.to_json : hash_or_string
54
+ end
55
+ end
56
+
57
+ ##
58
+ # Representation of a story to be published into a user's news feed.
59
+ class Story < ActionBase
60
+ attr_accessor :title, :body
61
+
62
+ ##
63
+ # Converts Story to a Hash of its attributes for use as parameters to Facebook REST API calls
64
+ def to_params
65
+ raise "Must set title before converting" if self.title.nil?
66
+ { :title => title, :body => body }.merge image_params
67
+ end
68
+
69
+ end
70
+ Action = Story.dup
71
+ def Action.name
72
+ "Action"
73
+ end
74
+ ##
75
+ # Representation of an action to be published into a user's news feed. Alias for Story.
76
+ class Action; end
77
+ end
78
+ end
@@ -0,0 +1,44 @@
1
+ require 'benchmark'
2
+ module Facebooker
3
+ @@logger = nil
4
+ def self.logger=(logger)
5
+ @@logger = logger
6
+ end
7
+ def self.logger
8
+ @@logger
9
+ end
10
+
11
+ module Logging
12
+ @skip_api_logging = nil
13
+ class << self; attr_accessor :skip_api_logging; end
14
+
15
+ def self.log_fb_api(method, params)
16
+ message = method # might customize later
17
+ dump = format_fb_params(params)
18
+ if block_given?
19
+ result = nil
20
+ seconds = Benchmark.realtime { result = yield }
21
+ log_info(message, dump, seconds) unless skip_api_logging
22
+ result
23
+ else
24
+ log_info(message, dump) unless skip_api_logging
25
+ nil
26
+ end
27
+ rescue Exception => e
28
+ exception = "#{e.class.name}: #{e.message}: #{dump}"
29
+ log_info(message, exception)
30
+ raise
31
+ end
32
+
33
+ def self.format_fb_params(params)
34
+ params.map { |key,value| "#{key} = #{value}" }.join(', ')
35
+ end
36
+
37
+ def self.log_info(message, dump, seconds = 0)
38
+ return unless Facebooker.logger
39
+ log_message = "#{message} (#{seconds}) #{dump}"
40
+ Facebooker.logger.info(log_message)
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,20 @@
1
+ module Facebooker
2
+ class Mobile
3
+ def initialize(session)
4
+ @session = session
5
+ end
6
+
7
+ # Used to determine whether the user identified by "uid" has enabled SMS for this application.
8
+ def can_send(user)
9
+ @session.post('facebook.sms.canSend', :uid => User.cast_to_facebook_id(user))
10
+ end
11
+
12
+ # Send the given message to the user.
13
+ # See http://wiki.developers.facebook.com/index.php/Mobile
14
+ def send(user, message)
15
+ @session.post('facebook.sms.send',
16
+ {:uid => User.cast_to_facebook_id(user),
17
+ :message => message}, false)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,50 @@
1
+ require 'digest/md5'
2
+ require 'facebooker/service'
3
+
4
+ module Facebooker
5
+ # A mock service that reads the Facebook response from fixtures
6
+ # Adapted from http://gist.github.com/44344
7
+ #
8
+ # Facebooker::MockService.fixture_path = 'path/to/dir'
9
+ # Facebooker::Session.current = Facebooker::MockSession.create
10
+ #
11
+ class MockService < Service
12
+ class << self
13
+ attr_accessor :fixture_path
14
+ end
15
+
16
+ def read_fixture(method, filename, original = nil)
17
+ path = fixture_path(method, filename)
18
+ File.read path
19
+ rescue Errno::ENAMETOOLONG
20
+ read_fixture(method, hash_fixture_name(filename), filename)
21
+ rescue Errno::ENOENT => e
22
+ if File.exists?(fixture_path(method, 'default'))
23
+ File.read fixture_path(method, 'default')
24
+ else
25
+ e.message << "\n(Non-hashed path is #{original})" if original
26
+ e.message << "\nFacebook API Reference: http://wiki.developers.facebook.com/index.php/#{method.sub(/^facebook\./, '')}#Example_Return_XML"
27
+ raise e
28
+ end
29
+ end
30
+
31
+ def post(params)
32
+ method = params.delete(:method)
33
+ params.delete_if {|k,_| [:v, :api_key, :call_id, :sig].include?(k) }
34
+ Parser.parse(method, read_fixture(method, fixture_name(params)))
35
+ end
36
+
37
+ private
38
+ def fixture_path(method, filename)
39
+ File.join(self.class.fixture_path, method, "#{filename}.xml")
40
+ end
41
+
42
+ def hash_fixture_name(filename)
43
+ Digest::MD5.hexdigest(filename)
44
+ end
45
+
46
+ def fixture_name(params)
47
+ params.map {|*args| args.join('=') }.sort.join('&')
48
+ end
49
+ end
50
+ end