blue_velvet 1.0.0

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 (64) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +79 -0
  3. data/Rakefile +42 -0
  4. data/app/assets/javascripts/blue_velvet/application.js +15 -0
  5. data/app/assets/stylesheets/blue_velvet/application.css +13 -0
  6. data/app/assets/stylesheets/facebook/attribute.css.scss +2 -0
  7. data/app/controllers/facebook/page_controller.rb +54 -0
  8. data/app/models/facebook/attribute.rb +8 -0
  9. data/app/models/facebook/client.rb +45 -0
  10. data/app/views/facebook/page/_attribute_not_found.html.erb +8 -0
  11. data/app/views/facebook/page/_page_attribute.html.erb +7 -0
  12. data/config/facebook.yml +18 -0
  13. data/config/initializers/koala.rb +29 -0
  14. data/config/routes.rb +2 -0
  15. data/lib/blue_velvet/engine.rb +6 -0
  16. data/lib/blue_velvet/version.rb +3 -0
  17. data/lib/blue_velvet.rb +4 -0
  18. data/lib/generators/facebook/config_generator.rb +15 -0
  19. data/lib/generators/facebook/views_generator.rb +14 -0
  20. data/test/blue_velvet_test.rb +7 -0
  21. data/test/dummy/README.rdoc +261 -0
  22. data/test/dummy/Rakefile +7 -0
  23. data/test/dummy/app/assets/javascripts/application.js +15 -0
  24. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  25. data/test/dummy/app/controllers/application_controller.rb +3 -0
  26. data/test/dummy/app/helpers/application_helper.rb +2 -0
  27. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  28. data/test/dummy/config/application.rb +59 -0
  29. data/test/dummy/config/boot.rb +10 -0
  30. data/test/dummy/config/database.yml +9 -0
  31. data/test/dummy/config/environment.rb +5 -0
  32. data/test/dummy/config/environments/development.rb +37 -0
  33. data/test/dummy/config/environments/production.rb +67 -0
  34. data/test/dummy/config/environments/test.rb +37 -0
  35. data/test/dummy/config/facebook.yml +18 -0
  36. data/test/dummy/config/facebook.yml.example +18 -0
  37. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  38. data/test/dummy/config/initializers/inflections.rb +15 -0
  39. data/test/dummy/config/initializers/mime_types.rb +5 -0
  40. data/test/dummy/config/initializers/secret_token.rb +7 -0
  41. data/test/dummy/config/initializers/session_store.rb +8 -0
  42. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  43. data/test/dummy/config/locales/en.yml +5 -0
  44. data/test/dummy/config/routes.rb +6 -0
  45. data/test/dummy/config.ru +4 -0
  46. data/test/dummy/db/development.sqlite3 +0 -0
  47. data/test/dummy/db/schema.rb +16 -0
  48. data/test/dummy/db/test.sqlite3 +0 -0
  49. data/test/dummy/log/development.log +71 -0
  50. data/test/dummy/log/test.log +935 -0
  51. data/test/dummy/public/404.html +26 -0
  52. data/test/dummy/public/422.html +26 -0
  53. data/test/dummy/public/500.html +25 -0
  54. data/test/dummy/public/favicon.ico +0 -0
  55. data/test/dummy/script/rails +6 -0
  56. data/test/fixtures/cassettes/facebook.yml +95 -0
  57. data/test/fixtures/cassettes/facebook_authentication.yml +95 -0
  58. data/test/functional/facebook/page_controller_test.rb +25 -0
  59. data/test/integration/facebook/configuration_test.rb +21 -0
  60. data/test/integration/navigation_test.rb +10 -0
  61. data/test/test_helper.rb +34 -0
  62. data/test/unit/facebook/attribute_test.rb +8 -0
  63. data/test/unit/facebook/client_test.rb +38 -0
  64. metadata +202 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Tom Scott
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.md ADDED
@@ -0,0 +1,79 @@
1
+ # BlueVelvet
2
+
3
+ BlueVelvet is a content management system that uses the Facebook
4
+ platform as the data store. It allows you to map route actions to
5
+ Facebook API calls and display the results with partials in your other
6
+ pages. You can even subclass the controller and create your own actions,
7
+ using one or more of your Facebook page's plethora of properties.
8
+
9
+ ## Usage
10
+
11
+ Add the gem to your Gemfile
12
+
13
+ gem 'blue_velvet'
14
+
15
+ Then rebundle
16
+
17
+ $ bundle install
18
+
19
+ Generate the Facebook configuration YAML file and edit it with your
20
+ Facebook App details. Obtain your Facebook page ID from the URL of your
21
+ Facebook page, it's the number at the end, after the hyphenated name and
22
+ a "/"..
23
+
24
+ $ rails generate facebook:config
25
+
26
+ And finally, add the query to your `config/routes.rb`:
27
+
28
+ get "/about" => "facebook/page#description"
29
+
30
+ If you start up your Rails server, you can now browse to
31
+ `http://localhost:3000/about` and expect to see the content in your
32
+ Facebook page's description!
33
+
34
+ For more information on the many properties available to you, check out
35
+ the API documentation.
36
+
37
+ ## Background
38
+
39
+ This project is the result of the work I've done on my band's website,
40
+ [TheWonderBars.com](http://thewonderbars.com). I didn't want to have to
41
+ maintain two versions of press data, and since we had an active Facebook
42
+ page that was chock full of content well before the site was designed and
43
+ deployed, I considered using Facebook as our main "database", rather
44
+ than a locally-maintained SQL database of some kind. At this point in
45
+ time, TheWonderBars.com does not require a database in order to
46
+ function.
47
+
48
+ ## Contributing
49
+
50
+ All contributions will be examined and considered. Anyone can feel free
51
+ to make their voice known by contributing to the project. Click the
52
+ "Fork" button on the top of the screen (register a GitHub account if you
53
+ don't already have one), create a feature branch, and submit the changes
54
+ back to me in the form of a pull request.
55
+
56
+ You must write tests for your feature or bug fix and they must pass.
57
+
58
+ ## License
59
+
60
+ Copyright 2012 Tom Scott
61
+
62
+ Permission is hereby granted, free of charge, to any person obtaining
63
+ a copy of this software and associated documentation files (the
64
+ "Software"), to deal in the Software without restriction, including
65
+ without limitation the rights to use, copy, modify, merge, publish,
66
+ distribute, sublicense, and/or sell copies of the Software, and to
67
+ permit persons to whom the Software is furnished to do so, subject to
68
+ the following conditions:
69
+
70
+ The above copyright notice and this permission notice shall be
71
+ included in all copies or substantial portions of the Software.
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
74
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
75
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
76
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
77
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
78
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
79
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'BlueVelvet'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+ desc "Configure the dummy app with a dummy Facebook page."
38
+ task :configuration do
39
+ cp "config/facebook.yml", "test/dummy/config/facebook.yml"
40
+ end
41
+
42
+ task :default => :test
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree ../facebook
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree ../facebook
13
+ */
@@ -0,0 +1,2 @@
1
+ .facebook_attribute {
2
+ }
@@ -0,0 +1,54 @@
1
+ # The interim between the Facebook page data and the end user, this defines the internal API
2
+ # used by the Rails app to call Facebook attributes as if they were controller actions.
3
+ class Facebook::PageController < ApplicationController
4
+ # Much like method_missing, this method is called when ApplicationController can't find
5
+ # the hard-coded action. For this controller specifically, it will be called on all routing
6
+ # requests to +facebook/page+.
7
+ #
8
+ # This method retrieves any attribute from the Facebook page and displays it with a consistent
9
+ # partial template. The template used is page_attribute, which creates a +<div class="facebook_attribute"
10
+ # id="{whatever-facebook-attribute-you-used}>+ and renders it with the contents of the Facebook
11
+ # attribute. Because this method makes use of a partial, it can be called in place of any other
12
+ # +render+ or +redirect_to+ call, from any part of the application like so:
13
+ #
14
+ # class InfoController < ApplicationController
15
+ # def about
16
+ # render 'facebook/page#description'
17
+ # end
18
+ # end
19
+ #
20
+ # Or, you may route to the action:
21
+ #
22
+ # get "/about" => "facebook/page#description"
23
+ #
24
+ # Note that using routes.rb is easier, but binds you to using CSS as the main method of
25
+ # customization. You may override our styles if you simply create styles for
26
+ # +.facebook_attribute+, and for individual pages the name of the attribute as an ID.
27
+ def action_missing attribute_name
28
+ if facebook.has_attribute? attribute_name
29
+ attribute_content = facebook.send(:"#{attribute_name}").gsub(/\n/, "<br>")
30
+ attribute = Facebook::Attribute.new \
31
+ name: attribute_name.parameterize,
32
+ title: attribute_name.titleize,
33
+ body: attribute_content
34
+ render partial: 'page_attribute', locals: { attribute: attribute }
35
+ else
36
+ render partial: 'attribute_not_found', locals: { attribute_name: "#{attribute_name}" }
37
+ end
38
+ end
39
+
40
+ protected
41
+ # Shorthand accessor for the omnipresent Facebook client
42
+ def facebook
43
+ @facebook_client ||= Facebook::Client.new
44
+ end
45
+
46
+ private
47
+ def use_layout
48
+ if request.xhr?
49
+ false
50
+ else
51
+ 'application'
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,8 @@
1
+ # Display a Facebook page attribute for use in the Rails view layer.
2
+ class Facebook::Attribute
3
+ attr_accessor :name, :title, :body
4
+
5
+ def initialize with_options={}
6
+ with_options.each { |key,val| self.send :"#{key}=", val }
7
+ end
8
+ end
@@ -0,0 +1,45 @@
1
+ # A client for the Facebook Graph API which looks for data on a specific Facebook page or profile. It
2
+ # reads from the YAML configuration stored in `config/facebook.yml` for the current Rails environment.
3
+ class Facebook::Client
4
+ attr_reader :graph, :oauth
5
+ attr_accessor :page
6
+
7
+ # Connects to the open graph.
8
+ def initialize options={}
9
+ @oauth = Koala::Facebook::OAuth.new \
10
+ Facebook.config[:app_id], Facebook.config[:secret_key]
11
+ @graph = Koala::Facebook::API.new access_token
12
+ @page = @graph.get_object(Facebook.config[:page_id])
13
+ end
14
+
15
+ def has_attribute? attribute
16
+ @page["#{attribute}"].present?
17
+ end
18
+
19
+ # Gets any attribute from Facebook, as long as it's within the filter, and returns it.
20
+ def method_missing attribute
21
+ if @page.present?
22
+ if self.has_attribute? attribute
23
+ @page["#{attribute}"]
24
+ else
25
+ raise Facebook::AttributeNotFound
26
+ end
27
+ else
28
+ raise Facebook::PageNotFound
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def access_token
35
+ @oauth.get_app_access_token
36
+ end
37
+ end
38
+
39
+ module Facebook
40
+ # Thrown when the Facebook page doesn't have the attribute requested.
41
+ class AttributeNotFound < StandardError; end
42
+
43
+ # Thrown when the Facebook page can't be found
44
+ class PageNotFound < StandardError; end
45
+ end
@@ -0,0 +1,8 @@
1
+ <div id="error">
2
+ <h2>Attribute Not Found</h2>
3
+ <p>
4
+ We're sorry, but the requested attribute <strong><%= attribute_name %></strong>
5
+ could not be found on this Facebook page. Either it has not been filled in yet,
6
+ or the page author has opted not to publicize its contents.
7
+ </p>
8
+ </div>
@@ -0,0 +1,7 @@
1
+ <div class="facebook_attribute" id="<%= attribute.name %>">
2
+ <h2><%= attribute.title %></h2>
3
+
4
+ <p>
5
+ <%= attribute.body %>
6
+ </p>
7
+ </div>
@@ -0,0 +1,18 @@
1
+ # This is your Facebook configuration file. Put your Facebook app info in this file
2
+ # and it will be read by the Rails application. and BlueVelvet.
3
+
4
+ development:
5
+ app_id: 149744351829141
6
+ secret_key: 0a8de678e00605bda2c583ea187d197e
7
+ page_id: 137797553025194
8
+
9
+ test:
10
+ app_id: 149744351829141
11
+ secret_key: 0a8de678e00605bda2c583ea187d197e
12
+ page_id: 137797553025194
13
+
14
+ production:
15
+ app_id: 149744351829141
16
+ secret_key: 0a8de678e00605bda2c583ea187d197e
17
+ page_id: 137797553025194
18
+
@@ -0,0 +1,29 @@
1
+ require 'koala'
2
+
3
+ module Facebook
4
+ def self.config
5
+ if Rails.env.staging?
6
+ ActiveSupport::HashWithIndifferentAccess.new \
7
+ app_id: ENV['FB_APP_ID'],
8
+ secret_key: ENV['FB_SECRET_KEY'],
9
+ page_id: ENV['FB_PAGE_ID']
10
+ else
11
+ ActiveSupport::HashWithIndifferentAccess.new \
12
+ YAML.load_file(Rails.root.join("config/facebook.yml"))[Rails.env]
13
+ end
14
+ end
15
+ end
16
+
17
+ Koala::Facebook::OAuth.class_eval do
18
+ def initialize_with_default_settings(*args)
19
+ case args.size
20
+ when 0, 1
21
+ raise "application id and/or secret are not specified in the config" unless Facebook.config[:app_id].present? && Facebook.config[:secret_key].present?
22
+ initialize_without_default_settings(Facebook.config[:app_id], Facebook.config[:secret], args.first)
23
+ when 2, 3
24
+ initialize_without_default_settings(*args)
25
+ end
26
+ end
27
+
28
+ alias_method_chain :initialize, :default_settings
29
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ BlueVelvet::Engine.routes.draw do
2
+ end
@@ -0,0 +1,6 @@
1
+ module BlueVelvet
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace BlueVelvet
4
+ #isolate_namespace Facebook
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module BlueVelvet
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,4 @@
1
+ require "blue_velvet/engine"
2
+
3
+ module BlueVelvet
4
+ end
@@ -0,0 +1,15 @@
1
+ # Creates YAML configuration in +config/facebook.yml+ which helps you
2
+ # connect to the Facebook platform. Required inherently by Koala, which
3
+ # forms the backend of this gem.
4
+ class Facebook::ConfigGenerator < Rails::Generators::Base
5
+ # Edit this file with your Facebook app details
6
+ def create_yaml_file
7
+ copy_file "config/facebook.yml", "#{Rails.root}/config/facebook/yml"
8
+ end
9
+
10
+ # Don't touch this file, all it does is read from YAML and instantiate
11
+ # Koala.
12
+ def create_initializer
13
+ copy_file "config/initializers/koala.rb", "#{Rails.root}/config/initializers/koala.rb"
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # Copies internal gem views for use in the main app. Any view files
2
+ # encountered in the app in the same location as those in the engine
3
+ # will override the default views, so this generator allows you to
4
+ # customize the display of your Facebook content.
5
+ class Facebook::ViewsGenerator < Rails::Generators::Base
6
+ def copy_page_views
7
+ views_dir = File.join(__FILE__, 'app', 'views', 'facebook')
8
+ Dir[views_dir].each do |view_file_path|
9
+ view_file = File.basename view_file_path
10
+ app_path = "#{Rails.root}/app/views/facebook/#{view_file}"
11
+ copy_file view_file_path, app_path
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class BlueVelvetTest < ActiveSupport::TestCase
4
+ test "the module exists" do
5
+ assert_kind_of Module, BlueVelvet
6
+ end
7
+ end