diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2005-02-18 23:43:09 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2005-02-18 23:43:09 +0000 |
commit | 7a67d0f617db7d2962b6c3b80466e21570b244bf (patch) | |
tree | 56fa640e31f4f7f22d34a246bc1b197706a07e3a /actionwebservice/examples | |
parent | fdecb6843ba8c5b0f718225f343017e11fa7f711 (diff) | |
download | rails-7a67d0f617db7d2962b6c3b80466e21570b244bf.tar.gz rails-7a67d0f617db7d2962b6c3b80466e21570b244bf.tar.bz2 rails-7a67d0f617db7d2962b6c3b80466e21570b244bf.zip |
Renamed Action Service to Action Web Service
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@669 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionwebservice/examples')
9 files changed, 628 insertions, 0 deletions
diff --git a/actionwebservice/examples/googlesearch/README b/actionwebservice/examples/googlesearch/README new file mode 100644 index 0000000000..25ccbd2382 --- /dev/null +++ b/actionwebservice/examples/googlesearch/README @@ -0,0 +1,143 @@ += Google Service example + +This example shows how one would implement an API like Google +Search that uses lots of structured types. + +There are examples for "Direct" and "Delegated" dispatching +modes. + +There is also an example for API definition file autoloading. + + += Running the examples + + 1. Add the files to an Action Web Service enabled Rails project. + + "Direct" example: + + * Copy direct/search_controller.rb to "app/controllers" + in a Rails project. + * Copy direct/google_search_api.rb to "app/apis" + in a Rails project + + "Delegated" example: + + * Copy delegated/search_controller.rb to "app/controllers" + in a Rails project. + * Copy delegated/google_search_service.rb to "lib" + in a Rails project. + + "Autoloading" example: + + * Copy autoloading/google_search_api.rb to "app/apis" (create the directory + if it doesn't exist) in a Rails project. + + * Copy autoloading/google_search_controller.rb "app/controllers" + in a Rails project. + + + 2. Go to the WSDL url in a browser, and check that it looks correct. + + "Direct" and "Delegated" examples: + http://url_to_project/search/wsdl + + "Autoloading" example: + http://url_to_project/google_search/wsdl + + You can compare it to Google's hand-coded WSDL at http://api.google.com/GoogleSearch.wsdl + and see how close (or not) the generated version is. + + Note that I used GoogleSearch as the canonical "best practice" + interoperable example when implementing WSDL/SOAP support, which might + explain extreme similarities :) + + + 3. Test that it works with .NET (Mono in this example): + + $ wget WSDL_URL + $ mv wsdl GoogleSearch.wsdl + $ wsdl -out:GoogleSearch.cs GoogleSearch.wsdl + + Add these lines to the GoogleSearchService class body (be mindful of the + wrapping): + + public static void Main(string[] args) + { + GoogleSearchResult result; + GoogleSearchService service; + + service = new GoogleSearchService(); + result = service.doGoogleSearch("myApiKey", "my query", 10, 30, true, "restrict", false, "lr", "ie", "oe"); + System.Console.WriteLine("documentFiltering: {0}", result.documentFiltering); + System.Console.WriteLine("searchComments: {0}", result.searchComments); + System.Console.WriteLine("estimatedTotalResultsCount: {0}", result.estimatedTotalResultsCount); + System.Console.WriteLine("estimateIsExact: {0}", result.estimateIsExact); + System.Console.WriteLine("resultElements:"); + foreach (ResultElement element in result.resultElements) { + System.Console.WriteLine("\tsummary: {0}", element.summary); + System.Console.WriteLine("\tURL: {0}", element.URL); + System.Console.WriteLine("\tsnippet: {0}", element.snippet); + System.Console.WriteLine("\ttitle: {0}", element.title); + System.Console.WriteLine("\tcachedSize: {0}", element.cachedSize); + System.Console.WriteLine("\trelatedInformationPresent: {0}", element.relatedInformationPresent); + System.Console.WriteLine("\thostName: {0}", element.hostName); + System.Console.WriteLine("\tdirectoryCategory: {0}", element.directoryCategory.fullViewableName); + System.Console.WriteLine("\tdirectoryTitle: {0}", element.directoryTitle); + } + System.Console.WriteLine("searchQuery: {0}", result.searchQuery); + System.Console.WriteLine("startIndex: {0}", result.startIndex); + System.Console.WriteLine("endIndex: {0}", result.endIndex); + System.Console.WriteLine("searchTips: {0}", result.searchTips); + System.Console.WriteLine("directoryCategories:"); + foreach (DirectoryCategory cat in result.directoryCategories) { + System.Console.WriteLine("\t{0} ({1})", cat.fullViewableName, cat.specialEncoding); + } + System.Console.WriteLine("searchTime: {0}", result.searchTime); + } + + Now compile and run: + + $ mcs -reference:System.Web.Services GoogleSearch.cs + $ mono GoogleSearch.exe + + + If you had the application running (on the same host you got + the WSDL from), you should see something like this: + + + documentFiltering: True + searchComments: + estimatedTotalResultsCount: 322000 + estimateIsExact: False + resultElements: + summary: ONlamp.com: Rolling with Ruby on Rails + URL: http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html + snippet: Curt Hibbs shows off Ruby on Rails by building a simple ... + title: Teh Railz0r + cachedSize: Almost no lines of code! + relatedInformationPresent: True + hostName: rubyonrails.com + directoryCategory: Web Development + directoryTitle: + searchQuery: http://www.google.com/search?q=ruby+on+rails + startIndex: 10 + endIndex: 40 + searchTips: "on" is a very common word and was not included in your search [details] + directoryCategories: + Web Development (UTF-8) + Programming (US-ASCII) + searchTime: 1E-06 + + + Also, if an API method throws an exception, it will be sent back to the + caller in the protocol's exception format, so they should get an exception + thrown on their side with a meaningful error message. + + If you don't like this behaviour, you can do: + + class MyController < ActionController::Base + web_service_exception_reporting false + end + + 4. Crack open a beer. Publishing APIs for working with the same model as + your Rails web app should be easy from now on :) diff --git a/actionwebservice/examples/googlesearch/autoloading/google_search_api.rb b/actionwebservice/examples/googlesearch/autoloading/google_search_api.rb new file mode 100644 index 0000000000..e7e33a1105 --- /dev/null +++ b/actionwebservice/examples/googlesearch/autoloading/google_search_api.rb @@ -0,0 +1,50 @@ +class DirectoryCategory < ActionService::Struct + member :fullViewableName, :string + member :specialEncoding, :string +end + +class ResultElement < ActionService::Struct + member :summary, :string + member :URL, :string + member :snippet, :string + member :title, :string + member :cachedSize, :string + member :relatedInformationPresent, :bool + member :hostName, :string + member :directoryCategory, DirectoryCategory + member :directoryTitle, :string +end + +class GoogleSearchResult < ActionService::Struct + member :documentFiltering, :bool + member :searchComments, :string + member :estimatedTotalResultsCount, :int + member :estimateIsExact, :bool + member :resultElements, [ResultElement] + member :searchQuery, :string + member :startIndex, :int + member :endIndex, :int + member :searchTips, :string + member :directoryCategories, [DirectoryCategory] + member :searchTime, :float +end + +class GoogleSearchAPI < ActionService::API::Base + inflect_names false + + api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}] + api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}] + + api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [ + {:key=>:string}, + {:q=>:string}, + {:start=>:int}, + {:maxResults=>:int}, + {:filter=>:bool}, + {:restrict=>:string}, + {:safeSearch=>:bool}, + {:lr=>:string}, + {:ie=>:string}, + {:oe=>:string} + ] +end diff --git a/actionwebservice/examples/googlesearch/autoloading/google_search_controller.rb b/actionwebservice/examples/googlesearch/autoloading/google_search_controller.rb new file mode 100644 index 0000000000..c62e869df5 --- /dev/null +++ b/actionwebservice/examples/googlesearch/autoloading/google_search_controller.rb @@ -0,0 +1,57 @@ +class GoogleSearchController < ApplicationController + wsdl_service_name 'GoogleSearch' + + def doGetCachedPage + "<html><body>i am a cached page. my key was %s, url was %s</body></html>" % [@params['key'], @params['url']] + end + + def doSpellingSuggestion + "%s: Did you mean '%s'?" % [@params['key'], @params['phrase']] + end + + def doGoogleSearch + resultElement = ResultElement.new + resultElement.summary = "ONlamp.com: Rolling with Ruby on Rails" + resultElement.URL = "http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" + resultElement.snippet = "Curt Hibbs shows off Ruby on Rails by building a simple application that requires " + + "almost no Ruby experience. ... Rolling with Ruby on Rails. ..." + resultElement.title = "Teh Railz0r" + resultElement.cachedSize = "Almost no lines of code!" + resultElement.relatedInformationPresent = true + resultElement.hostName = "rubyonrails.com" + resultElement.directoryCategory = category("Web Development", "UTF-8") + + result = GoogleSearchResult.new + result.documentFiltering = @params['filter'] + result.searchComments = "" + result.estimatedTotalResultsCount = 322000 + result.estimateIsExact = false + result.resultElements = [resultElement] + result.searchQuery = "http://www.google.com/search?q=ruby+on+rails" + result.startIndex = @params['start'] + result.endIndex = @params['start'] + @params['maxResults'] + result.searchTips = "\"on\" is a very common word and was not included in your search [details]" + result.searchTime = 0.000001 + + # For Mono, we have to clone objects if they're referenced by more than one place, otherwise + # the Ruby SOAP collapses them into one instance and uses references all over the + # place, confusing Mono. + # + # This has recently been fixed: + # http://bugzilla.ximian.com/show_bug.cgi?id=72265 + result.directoryCategories = [ + category("Web Development", "UTF-8"), + category("Programming", "US-ASCII"), + ] + + result + end + + private + def category(name, encoding) + cat = DirectoryCategory.new + cat.fullViewableName = name.dup + cat.specialEncoding = encoding.dup + cat + end +end diff --git a/actionwebservice/examples/googlesearch/delegated/google_search_service.rb b/actionwebservice/examples/googlesearch/delegated/google_search_service.rb new file mode 100644 index 0000000000..da7f8f4529 --- /dev/null +++ b/actionwebservice/examples/googlesearch/delegated/google_search_service.rb @@ -0,0 +1,108 @@ +class DirectoryCategory < ActionService::Struct + member :fullViewableName, :string + member :specialEncoding, :string +end + +class ResultElement < ActionService::Struct + member :summary, :string + member :URL, :string + member :snippet, :string + member :title, :string + member :cachedSize, :string + member :relatedInformationPresent, :bool + member :hostName, :string + member :directoryCategory, DirectoryCategory + member :directoryTitle, :string +end + +class GoogleSearchResult < ActionService::Struct + member :documentFiltering, :bool + member :searchComments, :string + member :estimatedTotalResultsCount, :int + member :estimateIsExact, :bool + member :resultElements, [ResultElement] + member :searchQuery, :string + member :startIndex, :int + member :endIndex, :int + member :searchTips, :string + member :directoryCategories, [DirectoryCategory] + member :searchTime, :float +end + +class GoogleSearchAPI < ActionService::API::Base + inflect_names false + + api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}] + api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}] + + api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [ + {:key=>:string}, + {:q=>:string}, + {:start=>:int}, + {:maxResults=>:int}, + {:filter=>:bool}, + {:restrict=>:string}, + {:safeSearch=>:bool}, + {:lr=>:string}, + {:ie=>:string}, + {:oe=>:string} + ] +end + +class GoogleSearchService < ActionService::Base + web_service_api GoogleSearchAPI + + def doGetCachedPage(key, url) + "<html><body>i am a cached page</body></html>" + end + + def doSpellingSuggestion(key, phrase) + "Did you mean 'teh'?" + end + + def doGoogleSearch(key, q, start, maxResults, filter, restrict, safeSearch, lr, ie, oe) + resultElement = ResultElement.new + resultElement.summary = "ONlamp.com: Rolling with Ruby on Rails" + resultElement.URL = "http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" + resultElement.snippet = "Curt Hibbs shows off Ruby on Rails by building a simple application that requires " + + "almost no Ruby experience. ... Rolling with Ruby on Rails. ..." + resultElement.title = "Teh Railz0r" + resultElement.cachedSize = "Almost no lines of code!" + resultElement.relatedInformationPresent = true + resultElement.hostName = "rubyonrails.com" + resultElement.directoryCategory = category("Web Development", "UTF-8") + + result = GoogleSearchResult.new + result.documentFiltering = filter + result.searchComments = "" + result.estimatedTotalResultsCount = 322000 + result.estimateIsExact = false + result.resultElements = [resultElement] + result.searchQuery = "http://www.google.com/search?q=ruby+on+rails" + result.startIndex = start + result.endIndex = start + maxResults + result.searchTips = "\"on\" is a very common word and was not included in your search [details]" + result.searchTime = 0.000001 + + # For Mono, we have to clone objects if they're referenced by more than one place, otherwise + # the Ruby SOAP collapses them into one instance and uses references all over the + # place, confusing Mono. + # + # This has recently been fixed: + # http://bugzilla.ximian.com/show_bug.cgi?id=72265 + result.directoryCategories = [ + category("Web Development", "UTF-8"), + category("Programming", "US-ASCII"), + ] + + result + end + + private + def category(name, encoding) + cat = DirectoryCategory.new + cat.fullViewableName = name.dup + cat.specialEncoding = encoding.dup + cat + end +end diff --git a/actionwebservice/examples/googlesearch/delegated/search_controller.rb b/actionwebservice/examples/googlesearch/delegated/search_controller.rb new file mode 100644 index 0000000000..6525921b5a --- /dev/null +++ b/actionwebservice/examples/googlesearch/delegated/search_controller.rb @@ -0,0 +1,7 @@ +require 'google_search_service' + +class SearchController < ApplicationController + wsdl_service_name 'GoogleSearch' + web_service_dispatching_mode :delegated + web_service :beta3, GoogleSearchService.new +end diff --git a/actionwebservice/examples/googlesearch/direct/google_search_api.rb b/actionwebservice/examples/googlesearch/direct/google_search_api.rb new file mode 100644 index 0000000000..e7e33a1105 --- /dev/null +++ b/actionwebservice/examples/googlesearch/direct/google_search_api.rb @@ -0,0 +1,50 @@ +class DirectoryCategory < ActionService::Struct + member :fullViewableName, :string + member :specialEncoding, :string +end + +class ResultElement < ActionService::Struct + member :summary, :string + member :URL, :string + member :snippet, :string + member :title, :string + member :cachedSize, :string + member :relatedInformationPresent, :bool + member :hostName, :string + member :directoryCategory, DirectoryCategory + member :directoryTitle, :string +end + +class GoogleSearchResult < ActionService::Struct + member :documentFiltering, :bool + member :searchComments, :string + member :estimatedTotalResultsCount, :int + member :estimateIsExact, :bool + member :resultElements, [ResultElement] + member :searchQuery, :string + member :startIndex, :int + member :endIndex, :int + member :searchTips, :string + member :directoryCategories, [DirectoryCategory] + member :searchTime, :float +end + +class GoogleSearchAPI < ActionService::API::Base + inflect_names false + + api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}] + api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}] + + api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [ + {:key=>:string}, + {:q=>:string}, + {:start=>:int}, + {:maxResults=>:int}, + {:filter=>:bool}, + {:restrict=>:string}, + {:safeSearch=>:bool}, + {:lr=>:string}, + {:ie=>:string}, + {:oe=>:string} + ] +end diff --git a/actionwebservice/examples/googlesearch/direct/search_controller.rb b/actionwebservice/examples/googlesearch/direct/search_controller.rb new file mode 100644 index 0000000000..7c69f0225e --- /dev/null +++ b/actionwebservice/examples/googlesearch/direct/search_controller.rb @@ -0,0 +1,58 @@ +class SearchController < ApplicationController + web_service_api :google_search + wsdl_service_name 'GoogleSearch' + + def doGetCachedPage + "<html><body>i am a cached page. my key was %s, url was %s</body></html>" % [@params['key'], @params['url']] + end + + def doSpellingSuggestion + "%s: Did you mean '%s'?" % [@params['key'], @params['phrase']] + end + + def doGoogleSearch + resultElement = ResultElement.new + resultElement.summary = "ONlamp.com: Rolling with Ruby on Rails" + resultElement.URL = "http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" + resultElement.snippet = "Curt Hibbs shows off Ruby on Rails by building a simple application that requires " + + "almost no Ruby experience. ... Rolling with Ruby on Rails. ..." + resultElement.title = "Teh Railz0r" + resultElement.cachedSize = "Almost no lines of code!" + resultElement.relatedInformationPresent = true + resultElement.hostName = "rubyonrails.com" + resultElement.directoryCategory = category("Web Development", "UTF-8") + + result = GoogleSearchResult.new + result.documentFiltering = @params['filter'] + result.searchComments = "" + result.estimatedTotalResultsCount = 322000 + result.estimateIsExact = false + result.resultElements = [resultElement] + result.searchQuery = "http://www.google.com/search?q=ruby+on+rails" + result.startIndex = @params['start'] + result.endIndex = @params['start'] + @params['maxResults'] + result.searchTips = "\"on\" is a very common word and was not included in your search [details]" + result.searchTime = 0.000001 + + # For Mono, we have to clone objects if they're referenced by more than one place, otherwise + # the Ruby SOAP collapses them into one instance and uses references all over the + # place, confusing Mono. + # + # This has recently been fixed: + # http://bugzilla.ximian.com/show_bug.cgi?id=72265 + result.directoryCategories = [ + category("Web Development", "UTF-8"), + category("Programming", "US-ASCII"), + ] + + result + end + + private + def category(name, encoding) + cat = DirectoryCategory.new + cat.fullViewableName = name.dup + cat.specialEncoding = encoding.dup + cat + end +end diff --git a/actionwebservice/examples/metaWeblog/README b/actionwebservice/examples/metaWeblog/README new file mode 100644 index 0000000000..f8a56d7018 --- /dev/null +++ b/actionwebservice/examples/metaWeblog/README @@ -0,0 +1,28 @@ += metaWeblog example + + +This example shows how one might begin to go about adding metaWeblog +(http://www.xmlrpc.com/metaWeblogApi) API support to a Rails-based +blogging application. + + += Running + + 1. Ensure you have the 'actionservice' Gem installed. You can generate it using + this command: + + $ rake package + + + 2. Edit config/environment.rb, and add the following line after the rest of the + require_gem statements: + + require_gem 'actionservice' + + + 3. Copy blog_controller.rb to "app/controllers" in a Rails project. + + + 4. Fire up a desktop blogging application (such as BloGTK on Linux), + point it at http://localhost:3000/blog/api, and try creating or + editing blog posts. diff --git a/actionwebservice/examples/metaWeblog/blog_controller.rb b/actionwebservice/examples/metaWeblog/blog_controller.rb new file mode 100644 index 0000000000..aff2e909ea --- /dev/null +++ b/actionwebservice/examples/metaWeblog/blog_controller.rb @@ -0,0 +1,127 @@ +# point your client at http://project_url/blog/api to test +# this + +# structures as defined by the metaWeblog/blogger +# specifications. +module Blog + class Enclosure < ActionService::Struct + member :url, :string + member :length, :int + member :type, :string + end + + class Source < ActionService::Struct + member :url, :string + member :name, :string + end + + class Post < ActionService::Struct + member :title, :string + member :link, :string + member :description, :string + member :author, :string + member :category, :string + member :comments, :string + member :enclosure, Enclosure + member :guid, :string + member :pubDate, :string + member :source, Source + end + + class Blog < ActionService::Struct + member :url, :string + member :blogid, :string + member :blogName, :string + end +end + +# skeleton metaWeblog API +class MetaWeblogAPI < ActionService::API::Base + inflect_names false + + api_method :newPost, :returns => [:string], :expects => [ + {:blogid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:struct=>Blog::Post}, + {:publish=>:bool}, + ] + + api_method :editPost, :returns => [:bool], :expects => [ + {:postid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:struct=>Blog::Post}, + {:publish=>:bool}, + ] + + api_method :getPost, :returns => [Blog::Post], :expects => [ + {:postid=>:string}, + {:username=>:string}, + {:password=>:string}, + ] + + api_method :getUsersBlogs, :returns => [[Blog::Blog]], :expects => [ + {:appkey=>:string}, + {:username=>:string}, + {:password=>:string}, + ] + + api_method :getRecentPosts, :returns => [[Blog::Post]], :expects => [ + {:blogid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:numberOfPosts=>:int}, + ] +end + +class BlogController < ApplicationController + web_service_api MetaWeblogAPI + + def initialize + @postid = 0 + end + + def newPost + $stderr.puts 'Creating post: username=%s password=%s struct=%s' % [ + @params['username'], + @params['password'], + @params['struct'].inspect + ] + (@postid += 1).to_s + end + + def editPost + $stderr.puts 'Editing post: username=%s password=%s struct=%s' % [ + @params['username'], + @params['password'], + @params['struct'].inspect + ] + true + end + + def getUsersBlogs + $stderr.puts "Returning user %s's blogs" % @params['username'] + blog = Blog::Blog.new( + :url =>'http://blog.xeraph.org', + :blogid => 'sttm', + :blogName => 'slave to the machine' + ) + [blog] + end + + def getRecentPosts + $stderr.puts "Returning recent posts (%d requested)" % @params['numberOfPosts'] + post1 = Blog::Post.new( + :title => 'first post!', + :link => 'http://blog.xeraph.org/testOne.html', + :description => 'this is the first post' + ) + post2 = Blog::Post.new( + :title => 'second post!', + :link => 'http://blog.xeraph.org/testTwo.html', + :description => 'this is the second post' + ) + [post1, post2] + end +end |