Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenrails committed Feb 23, 2011
0 parents commit f74a0d4
Show file tree
Hide file tree
Showing 12 changed files with 530 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
pkg/*
*.gem
.bundle
doc/*
Gemfile.lock
.yardoc
4 changes: 4 additions & 0 deletions Gemfile
@@ -0,0 +1,4 @@
source "http://rubygems.org"

# Specify your gem's dependencies in acts_as_opengraph.gemspec
gemspec
19 changes: 19 additions & 0 deletions LICENSE
@@ -0,0 +1,19 @@
Copyright (c) 2011 Ruben Ascencio

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
137 changes: 137 additions & 0 deletions README.markdown
@@ -0,0 +1,137 @@
# acts\_as\_opengraph

ActiveRecord extension that turns your models into [facebook opengraph](http://developers.facebook.com/docs/opengraph/) objects.

## Installation

gem install acts_as_opengraph

Now just add the gem dependency in your projects configuration.

## Usage

### Adding acts\_as\_opengraph

# app/models/movie.rb
class Movie < ActiveRecord::Base
acts_as_opengraph
end

### Generating the opengraph meta tags

# app/views/layouts/application.html.erb
<head>
<%= yield :opengraph_meta_tags %>
</head>

# app/views/movies/show.html.erb
<% content_for :opengraph_meta_tags, opengraph_meta_tags_for(@movie) %>

### Displaying the Like Button
# app/views/movies/show.html.erb
<%= like_button_for @movie %>

\* Notice that the Like Button will retrieve the required `href` attribute by calling `@movie.opengraph_url`. Read below for more options.


## Options

### Database columns

Even when the names of these columns can be changed with configuration, `acts_as_opengraph` tries to guess these names by checking for the existence of common names. Chances are that your model already has some of the opengraph defined properties.

This is the list of supported opengraph protocol properties and their possible column names (in precedence order):

* __title__ - og\_title, title, name
* __type__ - og\_type, kind, category
* __image__ - og\_image, image, photo, picture, thumb, thumbnail
* __url__ - og\_url, url, uri, link
* __description__ - og\_description, description, summary
* __site\_name__ - og\_site, website, web
* __latitude__ - og\_latitude, latitude
* __longitude__ - og\_longitude, longitude
* __street\_address__ - og\_street\_address, street_address, address, street
* __locality__ - og\_locality, locality
* __region__ - og\_region, region
* __postal\_code__ - og\_postal\_code, postal\_code, zip\_code, zip
* __country\_name__ - og\_country_name, country\_name, country
* __email__ - og\_email, email, mail
* __phone\_number__ - og\_phone\_number, phone\_number, phone
* __fax\_number__ - og\_fax\_number, fax\_number, fax

### Using a different column name

If you need to use a different column then use the __columns__ option. For example, if you store the url of your movies using the `imdb_url` column in your movies table, then do this:

# app/models/movie.rb
acts_as_opengraph :columns => { :url => :imdb_url }

### What about using a custom method?

If you wish to use a custom method for some opengraph field, then all you need to do is to define a method with the prefix `opengraph_`.
For example, if you are using [Paperclip](https://github.com/thoughtbot/paperclip) for your image attachments, you can do this:

# app/models/movie.rb
class Movie < ActiveRecord::Base

has_attached_file :picture, :styles => { :small => "160x130>"}

acts_as_opengraph
def opengraph_image
picture.url(:small)
end
end

### Default values

Use the __values__ option for passing default opengraph values. For our Movie example we can specify that all of our records are movies by doing this:

acts_as_opengraph :values => { :type => "movie" }

\* Notice that `acts_as_opengraph` only accepts an options hash argument, so if you want to combine default values and column names you'd do this:

acts_as_opengraph :columns => { :url => :imdb_url, :email => :contact },
:values => { :type => "movie", :site_name => "http://example.com" }

## Like Button options

Along with the object for which you want to display the Like button, you can pass an options hash to configure its appearance:

# app/views/layouts/application.html.erb
<%= like_button_for @movie, :layout => :box_count, :show_faces => true %>

### Using url helpers

By default, `acts_as_opengraph` will try to retrieve your object's url by calling `opengraph_url` on it. You could override it by defining a custom method, like this:

# app/models/movie.rb
def opengraph_url
"http://example.com/movies/#{self.id}"
end

But that's not the Rails way, so instead of doing that, you can pass an `href` option from your views, which means you can easily take advantage of the url helpers, like this:

# app/views/movies/show.html.erb
<%= like_button_for @movie, :href => movie_path(@movie) %>

See the complete list of allowed attributes and options [here](http://developers.facebook.com/docs/reference/plugins/like/).

## Note on Patches/Pull Requests

* Fork the project.
* Make your feature addition or bug fix.
* Add tests for it. This is important so I don’t break it in a future version unintentionally.
* Send me a pull request. Bonus points for topic branches.


## Copyright

Copyright &copy; 2011 Ruben Ascencio, released under the MIT license






2 changes: 2 additions & 0 deletions Rakefile
@@ -0,0 +1,2 @@
require 'bundler'
Bundler::GemHelper.install_tasks
23 changes: 23 additions & 0 deletions acts_as_opengraph.gemspec
@@ -0,0 +1,23 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "acts_as_opengraph/version"

Gem::Specification.new do |s|
s.name = "acts_as_opengraph"
s.version = ActsAsOpengraph::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ["Ruben Ascencio"]
s.email = ["galateaweb@gmail.com"]
s.homepage = "https://github.com/rubenrails/acts_as_opengraph"
s.summary = %q{ActiveRecord extension that turns your models into graph objects}
s.description = %q{ActiveRecord extension that turns your models into graph objects. Includes helper methods for adding <meta> tags and the Like Button to your views.}

s.rubyforge_project = "acts_as_opengraph"

s.add_development_dependency('sqlite3')

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
end
10 changes: 10 additions & 0 deletions lib/acts_as_opengraph.rb
@@ -0,0 +1,10 @@
if defined? ActiveRecord::Base
require File.join(File.dirname(__FILE__), 'acts_as_opengraph', 'active_record', 'acts', 'opengraph')
ActiveRecord::Base.send :include, ActiveRecord::Acts::Opengraph
end

if defined? ActionView::Base
require File.join(File.dirname(__FILE__), 'acts_as_opengraph', 'helper', 'acts_as_opengraph_helper')
ActionView::Base.send :include, ActsAsOpengraphHelper
end

121 changes: 121 additions & 0 deletions lib/acts_as_opengraph/active_record/acts/opengraph.rb
@@ -0,0 +1,121 @@
module ActiveRecord
module Acts
module Opengraph

def self.included(base)
base.extend ActMethods
end

module ActMethods
def acts_as_opengraph(options = {})
# don't allow multiple calls
return if included_modules.include? InstanceMethods

extend ClassMethods

opengraph_atts = %w(title type image url description site_name latitude longitude street_address locality region postal_code country_name email phone_number fax_number)

options[:columns] ||= {}
options[:values] ||= {}

opengraph_atts.each do |att_name|
options[:columns]["#{att_name}".to_sym] ||= alternative_column_name_for("og_#{att_name}".to_sym)
end

write_inheritable_attribute :opengraph_atts, opengraph_atts
class_inheritable_reader :opengraph_atts

write_inheritable_attribute :options, options
class_inheritable_reader :options

opengraph_atts.each do |att_name|
define_method "opengraph_#{att_name}" do
return_value_or_default att_name.to_sym
end
end

include InstanceMethods

end

end

module ClassMethods

private

# Returns a list of possible column names for a given attribute.
#
# @param [Symbol] att_name An opengraph attribute name prefixed with 'og_', i.e. :og_title, :og_type, etc
# @return [Array] A list of possible names for the given opengraph attribute
def alternative_names_for(att_name)
case att_name
when :og_title then [:title, :name]
when :og_type then [:kind, :category]
when :og_image then [:image, :photo, :picture, :thumb, :thumbnail]
when :og_url then [:url, :uri, :link]
when :og_description then [:description, :summary]
when :og_site_name then [:site, :website, :web]
when :og_latitude then [:latitude]
when :og_longitude then [:longitude]
when :og_street_address then [:street_address, :address, :street]
when :og_locality then [:locality]
when :og_region then [:region]
when :og_postal_code then [:postal_code, :zip_code, :zip]
when :og_country_name then [:country_name, :country]
when :og_email then [:email, :mail]
when :og_phone_number then [:phone_number, :phone]
when :og_fax_number then [:fax_number, :fax]
else []
end
end

# Tries to guess the column name for the given attribute. If it can't find any column (or similar) then it will create a virtual attribute
# for the object called: ATT_NAME_placeholder, so the object responds to that column.
#
# @param [Symbol] att_name An opengraph attribute name prefixed with 'og_', i.e. :og_title, :og_type, etc
# @return [String] The final name (found or created) for the opengraph attribute
def alternative_column_name_for(att_name)
alt_names = alternative_names_for(att_name)
columns_to_check = [att_name] + alt_names
columns_to_check.each do |column_name|
return column_name.to_sym if column_names.include?(column_name.to_s)
end

# Define placeholder method
ph_method_name = "#{alt_names.first}_placeholder"
define_method(ph_method_name) { "" }
ph_method_name
end

end

module InstanceMethods
# Returns an array of hashes representing the opengraph attribute/values for the Object.
#
# @return [Array] List of hashes representing opengraph attribute/values
# @example
# @movie.opengraph_data #=> {name=> "og:title", :value => "The Rock"}, {:name => "og:type", :value=> "movie"}
def opengraph_data
data_list = opengraph_atts.map do |att_name|
{:name => "og:#{att_name}", :value => self.send("opengraph_#{att_name}")}
end
data_list.delete_if{ |el| el[:value].blank? }
end


private

def return_value_or_default(att_name)
if options[:values].has_key?(att_name.to_sym)
options[:values][att_name]
else
self.send options[:columns]["#{att_name}".to_sym]
end
end

end

end
end
end
48 changes: 48 additions & 0 deletions lib/acts_as_opengraph/helper/acts_as_opengraph_helper.rb
@@ -0,0 +1,48 @@
module ActsAsOpengraphHelper
# Generates the opengraph meta tags for your views
#
# @param [Object, #opengraph_data] obj An instance of your ActiveRecord model that responds to opengraph_data
# @return [String] A set of meta tags describing your graph object based on the {http://ogp.me/ opengraph protocol}
# @raise [ArgumentError] When you pass an instance of an object that doesn't responds to opengraph_data (maybe you forgot to add acts_as_opengraph in your model)
# @example
# opengraph_meta_tags_for(@movie)
def opengraph_meta_tags_for(obj)
raise(ArgumentError.new, "You need to call acts_as_opengraph on your #{obj.class} model") unless obj.respond_to?(:opengraph_data)
tags = obj.opengraph_data.map do |att|
%(<meta name="#{att[:name].dasherize}" content="#{Rack::Utils.escape_html(att[:value])}"/>)
end
tags = tags.join("\n")
tags.respond_to?(:html_safe) ? tags.html_safe : tags
end

# Displays the Facebook Like Button in your views.
#
# @param [Object, #opengraph_data] obj An instance of your ActiveRecord model that responds to opengraph_data
# @param [Hash] options A Hash of {http://developers.facebook.com/docs/reference/plugins/like/ supported attributes}. Defaults to { :layout => :standard, :show_faces => false, :width => 450, :action => :like, :colorscheme => :light }
# @return [String] An iFrame version of the Facebook Like Button
# @raise [ArgumentError] When you pass an instance of an object that doesn't responds to opengraph_data (maybe you forgot to add acts_as_opengraph in your model)
# @example
# like_button_for(@movie)
# like_button_for(@movie, :layout => :button_count, :display_faces => true)
# @example Specifying href using rails helpers
# like_button_for(@movie, :href => movie_url(@movie))
def like_button_for(obj, options = {})
raise(ArgumentError.new, "You need to call acts_as_opengraph on your #{obj.class} model") unless obj.respond_to?(:opengraph_data)
href = options[:href] ? options[:href] : obj.opengraph_url
return unless href.present?

config = { :layout => :standard, :show_faces => false, :width => 450, :action => :like, :colorscheme => :light }
config.update(options) if options.is_a?(Hash)

o_layout = config[:layout].to_sym
if o_layout == :standard
config[:height] = config[:show_faces].to_s.to_sym == :true ? 80 : 35
elsif o_layout == :button_count
config[:height] = 21
elsif o_layout == :box_count
config[:height] = 65
end

%(<iframe src="http://www.facebook.com/plugins/like.php?href=#{CGI.escape(href)}&amp;layout=#{config[:layout]}&amp;show_faces=#{config[:show_faces]}&amp;width=#{config[:width]}&amp;action=#{config[:action]}&amp;colorscheme=#{config[:colorscheme]}&amp;height=#{config[:height]}" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:#{config[:width]}px; height:#{config[:height]}px;" allowTransparency="true"></iframe>)
end
end
3 changes: 3 additions & 0 deletions lib/acts_as_opengraph/version.rb
@@ -0,0 +1,3 @@
module ActsAsOpengraph
VERSION = "0.0.1"
end

0 comments on commit f74a0d4

Please sign in to comment.