oembed_provider 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +104 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/app/controllers/oembed_provider_controller.rb +55 -0
- data/config/routes.rb +8 -0
- data/lib/oembed_providable.rb +201 -0
- data/lib/oembed_provider.rb +91 -0
- data/lib/oembed_provider_helper.rb +18 -0
- data/rails/init.rb +1 -0
- data/test/full_2_3_5_app_with_tests/.gitignore +27 -0
- data/test/full_2_3_5_app_with_tests/README +1 -0
- data/test/full_2_3_5_app_with_tests/Rakefile +10 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/application_controller.rb +7 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/items_controller.rb +85 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/photos_controller.rb +85 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/application_helper.rb +4 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/items_helper.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/photos_helper.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/models/item.rb +4 -0
- data/test/full_2_3_5_app_with_tests/app/models/photo.rb +4 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/edit.html.erb +24 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/index.html.erb +24 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/new.html.erb +23 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/show.html.erb +21 -0
- data/test/full_2_3_5_app_with_tests/app/views/layouts/items.html.erb +20 -0
- data/test/full_2_3_5_app_with_tests/app/views/layouts/photos.html.erb +18 -0
- data/test/full_2_3_5_app_with_tests/app/views/photos/edit.html.erb +12 -0
- data/test/full_2_3_5_app_with_tests/app/views/photos/index.html.erb +18 -0
- data/test/full_2_3_5_app_with_tests/app/views/photos/new.html.erb +11 -0
- data/test/full_2_3_5_app_with_tests/app/views/photos/show.html.erb +3 -0
- data/test/full_2_3_5_app_with_tests/config/boot.rb +110 -0
- data/test/full_2_3_5_app_with_tests/config/database.yml +22 -0
- data/test/full_2_3_5_app_with_tests/config/environment.rb +54 -0
- data/test/full_2_3_5_app_with_tests/config/environments/development.rb +17 -0
- data/test/full_2_3_5_app_with_tests/config/environments/production.rb +28 -0
- data/test/full_2_3_5_app_with_tests/config/environments/test.rb +28 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/backtrace_silencers.rb +7 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/inflections.rb +10 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/mime_types.rb +5 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/new_rails_defaults.rb +21 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/oembed_provider.rb +2 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/session_store.rb +15 -0
- data/test/full_2_3_5_app_with_tests/config/locales/en.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales/fr.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales/zh.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales.yml +5 -0
- data/test/full_2_3_5_app_with_tests/config/routes.rb +4 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110212010602_create_items.rb +13 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110212022722_create_photos.rb +15 -0
- data/test/full_2_3_5_app_with_tests/db/schema.rb +35 -0
- data/test/full_2_3_5_app_with_tests/db/seeds.rb +7 -0
- data/test/full_2_3_5_app_with_tests/doc/README_FOR_APP +2 -0
- data/test/full_2_3_5_app_with_tests/public/404.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/422.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/500.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/favicon.ico +0 -0
- data/test/full_2_3_5_app_with_tests/public/images/rails.png +0 -0
- data/test/full_2_3_5_app_with_tests/public/index.html +275 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/application.js +2 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/controls.js +963 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/dragdrop.js +973 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/effects.js +1128 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/prototype.js +4320 -0
- data/test/full_2_3_5_app_with_tests/public/robots.txt +5 -0
- data/test/full_2_3_5_app_with_tests/public/stylesheets/scaffold.css +54 -0
- data/test/full_2_3_5_app_with_tests/script/about +4 -0
- data/test/full_2_3_5_app_with_tests/script/console +3 -0
- data/test/full_2_3_5_app_with_tests/script/dbconsole +3 -0
- data/test/full_2_3_5_app_with_tests/script/destroy +3 -0
- data/test/full_2_3_5_app_with_tests/script/generate +3 -0
- data/test/full_2_3_5_app_with_tests/script/performance/benchmarker +3 -0
- data/test/full_2_3_5_app_with_tests/script/performance/profiler +3 -0
- data/test/full_2_3_5_app_with_tests/script/plugin +3 -0
- data/test/full_2_3_5_app_with_tests/script/runner +3 -0
- data/test/full_2_3_5_app_with_tests/script/server +3 -0
- data/test/full_2_3_5_app_with_tests/test/factories.rb +14 -0
- data/test/full_2_3_5_app_with_tests/test/functional/oembed_provider_controller_test.rb +34 -0
- data/test/full_2_3_5_app_with_tests/test/integration/oembed_test.rb +88 -0
- data/test/full_2_3_5_app_with_tests/test/performance/browsing_test.rb +9 -0
- data/test/full_2_3_5_app_with_tests/test/selenium.rb +83 -0
- data/test/full_2_3_5_app_with_tests/test/test_helper.rb +55 -0
- data/test/full_2_3_5_app_with_tests/test/unit/oembed_providable_test.rb +211 -0
- data/test/full_2_3_5_app_with_tests/test/unit/oembed_provider_test.rb +97 -0
- data/test/full_2_3_5_app_with_tests/tmp/restart.txt +0 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/init.rb +1 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/base.rb +31 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/force_extension.rb +57 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/locale.rb +70 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb +33 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/uuid_token.rb +78 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter.rb +94 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/force_extension_spec.rb +65 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/generation_spec.rb +367 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/pagination_extension_spec.rb +19 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/recognition_spec.rb +76 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/routing_filter_spec.rb +114 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/spec_helper.rb +108 -0
- metadata +238 -0
data/.document
ADDED
data/.gitignore
ADDED
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
|