oembed_provider 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +104 -0
  5. data/Rakefile +59 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/oembed_provider_controller.rb +55 -0
  8. data/config/routes.rb +8 -0
  9. data/lib/oembed_providable.rb +201 -0
  10. data/lib/oembed_provider.rb +91 -0
  11. data/lib/oembed_provider_helper.rb +18 -0
  12. data/rails/init.rb +1 -0
  13. data/test/full_2_3_5_app_with_tests/.gitignore +27 -0
  14. data/test/full_2_3_5_app_with_tests/README +1 -0
  15. data/test/full_2_3_5_app_with_tests/Rakefile +10 -0
  16. data/test/full_2_3_5_app_with_tests/app/controllers/application_controller.rb +7 -0
  17. data/test/full_2_3_5_app_with_tests/app/controllers/items_controller.rb +85 -0
  18. data/test/full_2_3_5_app_with_tests/app/controllers/photos_controller.rb +85 -0
  19. data/test/full_2_3_5_app_with_tests/app/helpers/application_helper.rb +4 -0
  20. data/test/full_2_3_5_app_with_tests/app/helpers/items_helper.rb +2 -0
  21. data/test/full_2_3_5_app_with_tests/app/helpers/photos_helper.rb +2 -0
  22. data/test/full_2_3_5_app_with_tests/app/models/item.rb +4 -0
  23. data/test/full_2_3_5_app_with_tests/app/models/photo.rb +4 -0
  24. data/test/full_2_3_5_app_with_tests/app/views/items/edit.html.erb +24 -0
  25. data/test/full_2_3_5_app_with_tests/app/views/items/index.html.erb +24 -0
  26. data/test/full_2_3_5_app_with_tests/app/views/items/new.html.erb +23 -0
  27. data/test/full_2_3_5_app_with_tests/app/views/items/show.html.erb +21 -0
  28. data/test/full_2_3_5_app_with_tests/app/views/layouts/items.html.erb +20 -0
  29. data/test/full_2_3_5_app_with_tests/app/views/layouts/photos.html.erb +18 -0
  30. data/test/full_2_3_5_app_with_tests/app/views/photos/edit.html.erb +12 -0
  31. data/test/full_2_3_5_app_with_tests/app/views/photos/index.html.erb +18 -0
  32. data/test/full_2_3_5_app_with_tests/app/views/photos/new.html.erb +11 -0
  33. data/test/full_2_3_5_app_with_tests/app/views/photos/show.html.erb +3 -0
  34. data/test/full_2_3_5_app_with_tests/config/boot.rb +110 -0
  35. data/test/full_2_3_5_app_with_tests/config/database.yml +22 -0
  36. data/test/full_2_3_5_app_with_tests/config/environment.rb +54 -0
  37. data/test/full_2_3_5_app_with_tests/config/environments/development.rb +17 -0
  38. data/test/full_2_3_5_app_with_tests/config/environments/production.rb +28 -0
  39. data/test/full_2_3_5_app_with_tests/config/environments/test.rb +28 -0
  40. data/test/full_2_3_5_app_with_tests/config/initializers/backtrace_silencers.rb +7 -0
  41. data/test/full_2_3_5_app_with_tests/config/initializers/inflections.rb +10 -0
  42. data/test/full_2_3_5_app_with_tests/config/initializers/mime_types.rb +5 -0
  43. data/test/full_2_3_5_app_with_tests/config/initializers/new_rails_defaults.rb +21 -0
  44. data/test/full_2_3_5_app_with_tests/config/initializers/oembed_provider.rb +2 -0
  45. data/test/full_2_3_5_app_with_tests/config/initializers/session_store.rb +15 -0
  46. data/test/full_2_3_5_app_with_tests/config/locales/en.yml +4 -0
  47. data/test/full_2_3_5_app_with_tests/config/locales/fr.yml +4 -0
  48. data/test/full_2_3_5_app_with_tests/config/locales/zh.yml +4 -0
  49. data/test/full_2_3_5_app_with_tests/config/locales.yml +5 -0
  50. data/test/full_2_3_5_app_with_tests/config/routes.rb +4 -0
  51. data/test/full_2_3_5_app_with_tests/db/migrate/20110212010602_create_items.rb +13 -0
  52. data/test/full_2_3_5_app_with_tests/db/migrate/20110212022722_create_photos.rb +15 -0
  53. data/test/full_2_3_5_app_with_tests/db/schema.rb +35 -0
  54. data/test/full_2_3_5_app_with_tests/db/seeds.rb +7 -0
  55. data/test/full_2_3_5_app_with_tests/doc/README_FOR_APP +2 -0
  56. data/test/full_2_3_5_app_with_tests/public/404.html +30 -0
  57. data/test/full_2_3_5_app_with_tests/public/422.html +30 -0
  58. data/test/full_2_3_5_app_with_tests/public/500.html +30 -0
  59. data/test/full_2_3_5_app_with_tests/public/favicon.ico +0 -0
  60. data/test/full_2_3_5_app_with_tests/public/images/rails.png +0 -0
  61. data/test/full_2_3_5_app_with_tests/public/index.html +275 -0
  62. data/test/full_2_3_5_app_with_tests/public/javascripts/application.js +2 -0
  63. data/test/full_2_3_5_app_with_tests/public/javascripts/controls.js +963 -0
  64. data/test/full_2_3_5_app_with_tests/public/javascripts/dragdrop.js +973 -0
  65. data/test/full_2_3_5_app_with_tests/public/javascripts/effects.js +1128 -0
  66. data/test/full_2_3_5_app_with_tests/public/javascripts/prototype.js +4320 -0
  67. data/test/full_2_3_5_app_with_tests/public/robots.txt +5 -0
  68. data/test/full_2_3_5_app_with_tests/public/stylesheets/scaffold.css +54 -0
  69. data/test/full_2_3_5_app_with_tests/script/about +4 -0
  70. data/test/full_2_3_5_app_with_tests/script/console +3 -0
  71. data/test/full_2_3_5_app_with_tests/script/dbconsole +3 -0
  72. data/test/full_2_3_5_app_with_tests/script/destroy +3 -0
  73. data/test/full_2_3_5_app_with_tests/script/generate +3 -0
  74. data/test/full_2_3_5_app_with_tests/script/performance/benchmarker +3 -0
  75. data/test/full_2_3_5_app_with_tests/script/performance/profiler +3 -0
  76. data/test/full_2_3_5_app_with_tests/script/plugin +3 -0
  77. data/test/full_2_3_5_app_with_tests/script/runner +3 -0
  78. data/test/full_2_3_5_app_with_tests/script/server +3 -0
  79. data/test/full_2_3_5_app_with_tests/test/factories.rb +14 -0
  80. data/test/full_2_3_5_app_with_tests/test/functional/oembed_provider_controller_test.rb +34 -0
  81. data/test/full_2_3_5_app_with_tests/test/integration/oembed_test.rb +88 -0
  82. data/test/full_2_3_5_app_with_tests/test/performance/browsing_test.rb +9 -0
  83. data/test/full_2_3_5_app_with_tests/test/selenium.rb +83 -0
  84. data/test/full_2_3_5_app_with_tests/test/test_helper.rb +55 -0
  85. data/test/full_2_3_5_app_with_tests/test/unit/oembed_providable_test.rb +211 -0
  86. data/test/full_2_3_5_app_with_tests/test/unit/oembed_provider_test.rb +97 -0
  87. data/test/full_2_3_5_app_with_tests/tmp/restart.txt +0 -0
  88. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/init.rb +1 -0
  89. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/base.rb +31 -0
  90. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/force_extension.rb +57 -0
  91. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/locale.rb +70 -0
  92. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb +33 -0
  93. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/uuid_token.rb +78 -0
  94. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter.rb +94 -0
  95. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/force_extension_spec.rb +65 -0
  96. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/generation_spec.rb +367 -0
  97. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/pagination_extension_spec.rb +19 -0
  98. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/recognition_spec.rb +76 -0
  99. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/routing_filter_spec.rb +114 -0
  100. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/spec_helper.rb +108 -0
  101. metadata +238 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Horowhenua Library Trust
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,104 @@
1
+ = oembed_provider
2
+
3
+ A Rails engine to answer oEmbed requests for application media asset models.
4
+
5
+ In other words, this gem allows your application, after configuring the gem and the relevant models, to act as an oEmbed Provider by providing a controller that returns JSON or XML for a given oEmbed consumer request for the specified media asset.
6
+
7
+ The gem creates one unified oEmbed endpoint for all the oEmbed provided models via OembedProviderController.
8
+
9
+ This gem does not offer oEmbed consumer functionality.
10
+
11
+ Project homepage: https://github.com/kete/oembed_provider
12
+
13
+ Project issue tracker: http://kete.lighthouseapp.com/projects/69994-oembed_provider/
14
+
15
+ More details of oEmbed and its specification can be found at http://oembed.com/
16
+
17
+ IMPORTANT: Currently only known to work with Rails 2.3.5. Feel free to fork and get working with later versions of Rails. I'll happily add this as long as it stills works with Rails 2.3.5.
18
+
19
+ == Usage
20
+
21
+ === Installing Gem
22
+
23
+ gem install oembed_provider
24
+
25
+ === Installing from Source
26
+
27
+ Get source from git and checkout submodules:
28
+ git clone http://github.com/kete/oembed_provider.git
29
+ cd oembed_provider
30
+ git submodule init
31
+ git submodule update
32
+
33
+ Installing Gem:
34
+ rake gemspec
35
+ gem build {generated gemspec file}
36
+ gem install {generated gem file}
37
+
38
+ Running rake will check that you have the dependencies installed correctly.
39
+
40
+ === Declare your model oEmbed providable
41
+
42
+ Simple examples:
43
+
44
+ include OembedProvidable
45
+ # the first argument to oembed_providable_as is required
46
+ # and is the oembed type, can be :photo, :video, :link, or :rich
47
+ oembed_providable_as :link
48
+
49
+ If your model has methods that match the oEmbed method names relevant to your oembed type, you are done. Otherwise change your oembed_providable_as like so:
50
+
51
+ include OembedProvidable
52
+ oembed_providable_as :link, :title => :label
53
+
54
+ The second argument is hash where keys are names of oembed attributes needed and the value is the name of model's method for giving the corresponding value. Adjust to suit. Of course, you may need to implement methods to give what oembed_provider expects for your oembed type.
55
+
56
+ You'll also need to include logic in your methods that deals with maxheight and maxwidth if they are passed in as parameters to your oembed_response for photo, video, and rich types (for thumbnails for video and rich types).
57
+
58
+ For :link type, unless you do webpage thumbnails, you'll want to do something like this:
59
+
60
+ %w(url height width).each do |method_stub|
61
+ define_method('thumbnail_' + method_stub) do
62
+ nil
63
+ end
64
+ end
65
+
66
+ === More complex example:
67
+
68
+ Links to commits to how oembed_provider is used in Kete application (http://kete.net.nz) coming soon...
69
+
70
+ === Get oEmbed requests
71
+
72
+ A route is installed by the engine to answer requests at /oembed. It will answer json (when no format is specifed), json-p (callback and/or variable), and xml requests.
73
+
74
+ === Discoverability helper
75
+
76
+ You can optionally add links to the HTML head of relevant pages by adding this to your appropriate helper modules (i.e. in something under app/helpers/ that suits):
77
+
78
+ include OembedProviderHelper
79
+
80
+ and then adding this to the appropriate layout file (i.e. something under app/views/layout that matchs):
81
+
82
+ <%= oembed_provider_links %>
83
+
84
+ == TODO:
85
+ * a caching system
86
+
87
+ == Note on Patches/Pull Requests
88
+
89
+ * Fork the project.
90
+ * Make your feature addition or bug fix to a branch following this convention:
91
+ enhancement_[ticket #]_short_description
92
+ or
93
+ bugfix_[ticket #]_short_description
94
+ replace [ticket #] with ticket number from http://kete.lighthouseapp.com/projects/69994-oembed_provider
95
+ * Make your feature addition or bug fix.
96
+ * Add tests for it. This is important so I don't break it in a
97
+ future version unintentionally.
98
+ * Commit, do not mess with rakefile, version, or history.
99
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
100
+ * Send me a pull request. Bonus points for topic branches.
101
+
102
+ == Copyright
103
+
104
+ Copyright (c) 2011 Horowhenua Library Trust. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,59 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "oembed_provider"
8
+ gem.summary = %Q{A Rails engine to answer oEmbed requests for application media asset models.}
9
+ gem.description = %Q{A Rails engine to answer oEmbed requests for application media asset models. In other words, this gem allows your application, after configuring the gem and the relevant models, to act as an oEmbed Provider by providing a controller that returns JSON or XML for a given oEmbed consumer request for the specified media asset. This gem does not offer oEmbed consumer functionality. (Rails 2.3.5 only for now)}
10
+ gem.email = "walter@katipo.co.nz"
11
+ gem.homepage = "https://github.com/kete/oembed_provider"
12
+ gem.authors = ["Walter McGinnis"]
13
+ gem.add_dependency "addressable"
14
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ puts "This gem includes a full rails app for running tests (and staging development not yet extracted to the gem proper). Run tests there by changing to test/full_[RAIlS_VERSION_#_with_underscores]_app_with_tests and doing 'rake test'."
25
+ end
26
+
27
+ # require 'rake/testtask'
28
+ # Rake::TestTask.new(:test) do |test|
29
+ # test.libs << 'lib' << 'test'
30
+ # test.pattern = 'test/**/test_*.rb'
31
+ # test.verbose = true
32
+ # end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ end
41
+ rescue LoadError
42
+ task :rcov do
43
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
44
+ end
45
+ end
46
+
47
+ task :test => :check_dependencies
48
+
49
+ task :default => :test
50
+
51
+ require 'rake/rdoctask'
52
+ Rake::RDocTask.new do |rdoc|
53
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
54
+
55
+ rdoc.rdoc_dir = 'rdoc'
56
+ rdoc.title = "oembed_provider #{version}"
57
+ rdoc.rdoc_files.include('README*')
58
+ rdoc.rdoc_files.include('lib/**/*.rb')
59
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,55 @@
1
+ class OembedProviderController < ApplicationController
2
+ # Prevents the following error from showing up, common in Rails engines
3
+ # A copy of ApplicationController has been removed from the module tree but is still active!
4
+ unloadable
5
+
6
+ # GET /oembed?url=... json by default
7
+ # GET /oembed.json?url=...
8
+ # GET /oembed.json?url=...&callback=myCallback
9
+ # GET /oembed.xml?url=...
10
+ def endpoint
11
+ # get object that we want an oembed_response from
12
+ # based on url
13
+ # and get its oembed_response
14
+ media_item = OembedProvider.find_provided_from(params[:url])
15
+ options = Hash.new
16
+ max_dimensions = [:maxwidth, :maxheight]
17
+
18
+ unless media_item.class::OembedResponse.providable_oembed_type == :link
19
+ max_dimensions.each { |dimension| options[dimension] = params[dimension] if params[dimension].present? }
20
+ end
21
+
22
+ @oembed_response = media_item.oembed_response(options)
23
+
24
+ # to_xml and to_json overidden in oembed_providable module
25
+ # to be properly formatted
26
+ # TODO: handle unauthorized case
27
+ respond_to do |format|
28
+ if @oembed_response
29
+ format.html { render_json @oembed_response.to_json } # return json for default
30
+ format.json { render_json @oembed_response.to_json }
31
+ format.xml { render :xml => @oembed_response }
32
+ else
33
+ format.all { render_404 }
34
+ end
35
+ end
36
+ end
37
+
38
+ protected
39
+ # thanks to http://blogs.sitepoint.com/2006/10/05/json-p-output-with-rails/
40
+ def render_json(json, options={})
41
+ callback, variable = params[:callback], params[:variable]
42
+ response = begin
43
+ if callback && variable
44
+ "var #{variable} = #{json};\n#{callback}(#{variable});"
45
+ elsif variable
46
+ "var #{variable} = #{json};"
47
+ elsif callback
48
+ "#{callback}(#{json});"
49
+ else
50
+ json
51
+ end
52
+ end
53
+ render({:content_type => :js, :text => response}.merge(options))
54
+ end
55
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ # extend routes for oembed provider endpoint
2
+ ActionController::Routing::Routes.draw do |map|
3
+ # only one route needed
4
+ map.with_options :controller => 'oembed_provider' do |oembed_provider|
5
+ oembed_provider.connect 'oembed.:format', :action => 'endpoint'
6
+ oembed_provider.connect 'oembed', :action => 'endpoint'
7
+ end
8
+ end
@@ -0,0 +1,201 @@
1
+ require 'oembed_provider'
2
+ require 'builder'
3
+
4
+ module OembedProvidable #:nodoc:
5
+ def self.included(base)
6
+ base.send(:include, OembedProvidable::Provided)
7
+ end
8
+
9
+ # use this to make your model able to respond to requests
10
+ # against the OembedProviderController
11
+ module Provided
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+
16
+ module ClassMethods
17
+ def oembed_providable_as(*args)
18
+ # don't allow multiple calls
19
+ return if self.included_modules.include?(OembedProvidable::Provided::InstanceMethods)
20
+
21
+ send :include, OembedProvidable::Provided::InstanceMethods
22
+
23
+ specs = args.last.is_a?(Hash) ? args.pop : Hash.new
24
+
25
+ oembed_type = args.first
26
+
27
+ if !oembed_type.is_a?(Symbol) || ![:photo, :video, :link, :rich].include?(oembed_type)
28
+ raise ArgumentError, "oEmbed type must be :photo, :video, :link, or :rich"
29
+ end
30
+
31
+ # create the scoped oembed_response model
32
+ const_set("OembedResponse", Class.new).class_eval do
33
+ cattr_accessor :providable_class
34
+ self.providable_class = self.name.split('::').first.constantize
35
+
36
+ cattr_accessor :providable_specs
37
+ self.providable_specs = specs
38
+
39
+ cattr_accessor :oembed_version
40
+ self.oembed_version = OembedProvider.version
41
+
42
+ cattr_accessor :providable_oembed_type
43
+ self.providable_oembed_type = oembed_type
44
+
45
+ the_provider_name = specs[:provider_name].present? ? specs[:provider_name] : OembedProvider.provider_name
46
+ raise ArgumentError, "Missing provider_name setting in either OembedProvider.provider_name or oembed_providable_as spec." unless the_provider_name.present?
47
+ cattr_accessor :providable_provider_name
48
+ self.providable_provider_name = the_provider_name
49
+
50
+ the_provider_url = specs[:provider_url].present? ? specs[:provider_url] : OembedProvider.provider_url
51
+ raise ArgumentError, "Missing provider_url setting in either OembedProvider.provider_url or oembed_providable_as spec." unless the_provider_url.present?
52
+ cattr_accessor :providable_provider_url
53
+ self.providable_provider_url = the_provider_url
54
+
55
+ # cache_age is optional and can be nil
56
+ the_cache_age = specs[:cache_age].present? ? specs[:cache_age] : OembedProvider.cache_age
57
+ cattr_accessor :providable_cache_age
58
+ self.providable_cache_age = the_cache_age
59
+
60
+ # these are what the response should return
61
+ # as per the oEmbed Spec
62
+ # http://oembed.com/#section2 - 2.3.4
63
+ # :type is required, but is model wide and set via oembed_providable_as
64
+ # :version is required and is handled below
65
+ attributes_to_define = OembedProvider.optional_attributes
66
+
67
+ attributes_to_define += OembedProvider.required_attributes[oembed_type]
68
+
69
+ # site wide values
70
+ # :provider_name, :provider_url, :cache_age
71
+ # can be set via oembed_providable_as
72
+ # or set via OembedProvider initialization
73
+ attributes_to_define += OembedProvider.base_attributes
74
+
75
+ # not relevant to links, but everything else
76
+ attributes_to_define += [:maxheight, :maxwidth] unless oembed_type == :link
77
+
78
+ cattr_accessor :providable_all_attributes
79
+ self.providable_all_attributes = attributes_to_define
80
+
81
+ attributes_to_define.each do |attr|
82
+ attr_accessor attr
83
+ end
84
+
85
+ # datastructure is hash
86
+ # with attribute name as key
87
+ # and method to call on providable as value
88
+ # both as symbol
89
+ # oembed_providable_as can specify method to call for an attribute
90
+ def self.method_specs_for(attributes)
91
+ method_specs = Hash.new
92
+ attributes.each do |attr|
93
+ if providable_specs.keys.include?(attr)
94
+ method_specs[attr] = providable_specs[attr]
95
+ else
96
+ method_specs[attr] = attr
97
+ end
98
+ end
99
+ method_specs
100
+ end
101
+
102
+ cattr_accessor :optional_attributes_specs
103
+ self.optional_attributes_specs = method_specs_for(OembedProvider.optional_attributes)
104
+
105
+ cattr_accessor :required_attributes_specs
106
+ self.required_attributes_specs = method_specs_for(OembedProvider.required_attributes[oembed_type])
107
+
108
+ # options are added to handle passing maxwidth and maxheight
109
+ # relevant to oembed types photo, video, and rich
110
+ # if they have a thumbnail, then these also much not be bigger
111
+ # than maxwidth, maxheight
112
+ def initialize(providable, options = {})
113
+ self.version = self.class.oembed_version
114
+
115
+ # we set maxwidth, maxheight first
116
+ # so subsequent calls to providable.send(some_method_name)
117
+ # can use them to adjust their values
118
+ unless type == :link
119
+ self.maxheight = options[:maxheight].to_i if options[:maxheight].present?
120
+ self.maxwidth = options[:maxwidth].to_i if options[:maxwidth].present?
121
+
122
+ providable.oembed_max_dimensions = { :height => maxheight, :width => maxwidth }
123
+ end
124
+
125
+ self.class.required_attributes_specs.each do |k,v|
126
+ value = providable.send(v)
127
+ raise ArgumentError, "#{k} is required for an oEmbed response." if value.blank?
128
+
129
+ send(k.to_s + '=', value)
130
+ end
131
+
132
+ self.class.optional_attributes_specs.each do |k,v|
133
+ send(k.to_s + '=', providable.send(v))
134
+ end
135
+
136
+ self.provider_name = self.class.providable_provider_name
137
+ self.provider_url = self.class.providable_provider_url
138
+ self.cache_age = self.class.providable_cache_age
139
+ end
140
+
141
+ def type
142
+ self.class.providable_oembed_type
143
+ end
144
+
145
+ # because this isn't an AR record, doesn't include to_xml
146
+ # plus we need a custom
147
+ # root node needs to replaced with oembed rather than oembed_response
148
+ def to_xml
149
+ attributes = self.class.providable_all_attributes
150
+
151
+ builder = Nokogiri::XML::Builder.new do |xml|
152
+ xml.oembed {
153
+ attributes.each do |attr|
154
+ next if attr.to_s.include?('max')
155
+ value = self.send(attr)
156
+ xml.send(attr, value) if value.present?
157
+ end
158
+ }
159
+ end
160
+
161
+ builder.to_xml
162
+ end
163
+
164
+ # override default to_json
165
+ def as_json(options = {})
166
+ as_json = super(options)
167
+
168
+ attributes = self.class.providable_all_attributes
169
+
170
+ as_json.delete_if { |k,v| v.blank? }
171
+
172
+ as_json.delete_if { |k,v| k.include?('max') }
173
+
174
+ as_json
175
+ end
176
+
177
+
178
+ end
179
+ end
180
+
181
+ def oembed_type
182
+ self::OembedResponse.providable_oembed_type
183
+ end
184
+ end
185
+
186
+ module InstanceMethods
187
+ def oembed_response(options = {})
188
+ @oembed_response ||= self.class::OembedResponse.new(self, options)
189
+ end
190
+
191
+ def oembed_max_dimensions=(options)
192
+ options = { :height => nil, :width => nil } if options.blank?
193
+ @oembed_max_dimensions = options
194
+ end
195
+
196
+ def oembed_max_dimensions
197
+ @oembed_max_dimensions || { :height => nil, :width => nil }
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,91 @@
1
+ require 'addressable/uri'
2
+ require 'oembed_providable'
3
+ # set OembedProvider.provide_name, etc. in your config/initializers or somewhere
4
+ class OembedProvider
5
+ class << self
6
+ def provider_url
7
+ @@provider_url ||= String.new
8
+ end
9
+
10
+ def provider_url=(url)
11
+ @@provider_url = url
12
+ end
13
+
14
+ def provider_name
15
+ @@provider_name ||= String.new
16
+ end
17
+
18
+ def provider_name=(name)
19
+ @@provider_name = name
20
+ end
21
+
22
+ def cache_age
23
+ @@cache_age ||= nil
24
+ end
25
+
26
+ def cache_age=(age)
27
+ @@cache_age = age
28
+ end
29
+
30
+ def version
31
+ "1.0"
32
+ end
33
+
34
+ # every request has these, mostly required
35
+ # mostly site wide
36
+ # version is special case
37
+ def base_attributes
38
+ [:provider_url,
39
+ :provider_name,
40
+ :cache_age,
41
+ :version]
42
+ end
43
+
44
+ # optional attributes
45
+ # that are specific to an instance of the providable model
46
+ def optional_attributes
47
+ [:title,
48
+ :author_name,
49
+ :author_url,
50
+ :thumbnail_url,
51
+ :thumbnail_width,
52
+ :thumbnail_height]
53
+ end
54
+
55
+ # these may be required depending on type
56
+ # see 2.3.4.1 - 2.3.4.4 of spec
57
+ # type specific attributes
58
+ # all attributes listed for these types are required
59
+ # the empty link array shows that nothing is required
60
+ def required_attributes
61
+ { :photo => [:url, :width, :height],
62
+ :video => [:html, :width, :height],
63
+ :link => [],
64
+ :rich => [:html, :width, :height] }
65
+ end
66
+
67
+ def controller_model_maps
68
+ @@controller_model_maps ||= Hash.new
69
+ end
70
+
71
+ def controller_model_maps=(hash_map)
72
+ @@controller_model_maps = hash_map
73
+ end
74
+
75
+ def find_provided_from(url)
76
+ url = Addressable::URI.parse(url)
77
+ submitted_url_params = ActionController::Routing::Routes.recognize_path(url.path, :method=>:get)
78
+
79
+ controller = submitted_url_params[:controller]
80
+ id = submitted_url_params[:id]
81
+
82
+ # handle special cases where controllers are directly configured to point at a specific model
83
+ model = OembedProvider.controller_model_maps[controller]
84
+
85
+ # otherwise we use convention over configuration to determine model
86
+ model = controller.singularize.camelize unless model
87
+
88
+ model.constantize.find(id)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,18 @@
1
+ # include this in your relevant helpers
2
+ # to add discoverability link, etc.
3
+ module OembedProviderHelper
4
+ # hardcodes http as protocol
5
+ # http is specified in http://oembed.com/
6
+ def oembed_provider_links
7
+ host_url = request.host
8
+ escaped_request_url = request.url.sub('://', '%3A//')
9
+ html = tag(:link, :rel => "alternate",
10
+ :type => "application/json+oembed",
11
+ :href => "http://#{host_url}/oembed?url=#{escaped_request_url}",
12
+ :title => "JSON oEmbed for #{@title}")
13
+ html += tag(:link, :rel => "alternate",
14
+ :type => "application/xml+oembed",
15
+ :href => "http://#{host_url}/oembed.xml?url=#{escaped_request_url}",
16
+ :title => "XML oEmbed for #{@title}")
17
+ end
18
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'oembed_provider'
@@ -0,0 +1,27 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ webrat*
23
+ test.sqlite3
24
+ test/debug.log
25
+ db/development.sqlite3
26
+ db/test.sqlite3
27
+ log/*.log
@@ -0,0 +1 @@
1
+ This is a full Rails app used to test the gem's functionality.
@@ -0,0 +1,10 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require(File.join(File.dirname(__FILE__), 'config', 'boot'))
5
+
6
+ require 'rake'
7
+ require 'rake/testtask'
8
+ require 'rake/rdoctask'
9
+
10
+ require 'tasks/rails'
@@ -0,0 +1,7 @@
1
+ # Filters added to this controller apply to all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+
4
+ class ApplicationController < ActionController::Base
5
+ helper :all # include all helpers, all the time
6
+ protect_from_forgery # See ActionController::RequestForgeryProtection for details
7
+ end