Created
October 17, 2012 09:23
-
-
Save leafmind/3904653 to your computer and use it in GitHub Desktop.
Models samples with built-in integrations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Mechanize based Altergeo integration | |
# -*- encoding : utf-8 -*- | |
class Altergeo::Places | |
PER_PAGE = 3 | |
EXPANDED_DISTANCE = 10000 | |
def self.find_by_query(altergeo_user, query = '', page = 1) | |
options = { :query => query, :limit => PER_PAGE, :offset => PER_PAGE * (page - 1) } | |
response = make_request(altergeo_user, options) | |
response ||= make_request(altergeo_user, options.merge(:distance => EXPANDED_DISTANCE)) | |
if response.respond_to?(:xpath) | |
total_pages = response.xpath('//count').first.content.to_i | |
places = response.xpath('//place').map do |place| | |
OpenStruct.new( | |
:place_id => place.at_xpath('id').content, | |
:title => place.at_xpath('title').content, | |
:street => place.at_xpath('street').content | |
) | |
end | |
Altergeo::Collection.new(places, PER_PAGE, total_pages, page) | |
end | |
end | |
private | |
def self.make_request(altergeo_user, options) | |
add_coordinates!(altergeo_user, options) | |
Altergeo::Client.post(Settings.altergeo.places, user(altergeo_user), options) | |
end | |
def self.add_coordinates!(altergeo_user, options) | |
return unless altergeo_user | |
coordinates = altergeo_user.coordinates | |
if coordinates | |
options[:lat] = coordinates.lat | |
options[:lng] = coordinates.lng | |
end | |
end | |
def self.user(altergeo_user) | |
if altergeo_user | |
{ :email => altergeo_user.email, :password => altergeo_user.password } | |
else | |
Hash.new | |
end | |
end | |
end | |
######################################## | |
# Mechanize based Altergeo integration | |
# -*- encoding : utf-8 -*- | |
class Altergeo::User < ActiveRecord::Base | |
self.table_name = :altergeo_users | |
belongs_to :user, :class_name => "BhUser", :primary_key => "user_id" | |
def self.authorize(params, current_user) | |
return unless params | |
email = params[:email] | |
password = params[:password] | |
if Altergeo::Client.post(Settings.altergeo.login_url, params) | |
find_or_create_by_email(email, :password => password, :user => current_user) | |
end | |
end | |
def coordinates | |
Slot::MsisdnCoordinates.new(user.msisdn).read if user | |
end | |
end | |
################################### | |
# Mechanize based Altergeo integration | |
# -*- encoding : utf-8 -*- | |
class Altergeo::Client | |
class << self | |
def get(uri, params, options = {}) | |
prepare agent.get(uri, options, headers(params)) | |
rescue Mechanize::ResponseCodeError => e | |
handle(e) | |
end | |
def post(uri, params, options = {}) | |
prepare agent.post(uri, options, headers(params)) | |
rescue Mechanize::ResponseCodeError => e | |
handle(e) | |
end | |
private | |
def handle(exception) | |
%w{403 401}.include?(exception.response_code).blank? | |
end | |
def prepare(response) | |
Nokogiri::XML(response.body) | |
end | |
def headers(params) | |
{ | |
"Authorization" => 'Basic ' + ["#{params[:email]}:#{params[:password]}"].pack('m').delete("\r\n"), | |
} | |
end | |
def agent | |
@mechanize ||= Mechanize.new do |a| | |
a.log = Logger.new('log/mechanize.log') | |
a.user_agent_alias = 'Windows Mozilla' | |
end | |
end | |
end | |
end | |
############################################## | |
# Nokogiri based LJ integration | |
# -*- encoding : utf-8 -*- | |
class Livejournal::FriendsFeed | |
include Livejournal::Mixin | |
LIMIT = 3 | |
POST_LINK_PATTERN = /http:\/\/([^.]+)\.livejournal.com\/[\d]+\.html$/ | |
URL = 'http://%s.livejournal.com/friends' | |
def initialize(livejournal_user) | |
raise ArgumentError unless livejournal_user.respond_to?(:nickname) | |
@nickname = livejournal_user.nickname | |
end | |
def all(limit = LIMIT) | |
safe do | |
doc = Nokogiri::HTML(open(URL % @nickname)) | |
return [] unless doc.respond_to?(:css) | |
doc.css('a'). | |
find_all { |link| post_link?(link) }. | |
take(limit). | |
map { |link| | |
fetch_post_from_page(link['href']) | |
} | |
end | |
end | |
private | |
def post_link?(link) | |
link['href'] =~ POST_LINK_PATTERN | |
end | |
def fetch_post_from_page(url) | |
nickname = (url =~ POST_LINK_PATTERN; $1) | |
mobile_link = link_to_mobile(nickname, url) | |
doc = Nokogiri::HTML(open(mobile_link)) | |
return {} unless doc.respond_to?(:css) | |
{ | |
:nickname => nickname, | |
:title => Sanitize.clean(doc.at_css('.l .item-header').content), | |
:link => mobile_link | |
} | |
end | |
end | |
################################### | |
# OmniAuth based facebook integration | |
require_dependency 'user/acts_as_forum_user' | |
class User < ActiveRecord::Base | |
include ActiveModel::ForbiddenAttributesProtection | |
include ActsAsForumUser | |
include Mailboxer::Models::Messageable | |
module Types | |
COURSE_MANAGER = 'CourseManager' | |
MENTOR = 'Mentor' | |
STUDENT = 'Student' | |
SUPERADMIN = 'SuperAdmin' | |
TEACHER = 'Teacher' | |
TUTOR = 'Tutor' | |
ALL = [COURSE_MANAGER, MENTOR, STUDENT, SUPERADMIN, TEACHER, TUTOR].freeze | |
end | |
acts_as_messageable | |
# Dimensions and type names match Facebook's dimensions convetion | |
has_attached_file :avatar, :default_url => "/assets/default_:style_avatar.jpg", :styles => {:small => '50', :normal => '100', :large => '200'} | |
# Include default devise modules. Others available are: | |
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable | |
devise :database_authenticatable, :registerable, | |
:recoverable, :rememberable, :trackable, :confirmable, | |
:omniauthable | |
scope :without, lambda{ |user| user ? {:conditions => ["users.id != ?", user.id]} : {} } | |
# Reason why we can't just use :validatable Devise plugin - http://jessewolgamott.com/blog/2011/12/08/the-one-where-devise-validations-are-customized/ | |
validates_presence_of :email | |
validates_uniqueness_of :email, :allow_blank => true, :if => :email_changed? | |
validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true, :if => :email_changed? | |
validates :first_name, :presence => true, :if => :profile_data_required? | |
validates :last_name, :presence => true, :if => :profile_data_required? | |
validates_presence_of :password, :if => :password_required? | |
validates_confirmation_of :password, :if => :password_required? | |
validates_length_of :password, :within => Devise.password_length, :allow_blank => true | |
validates_uniqueness_of :email | |
validates :type, :inclusion => Types::ALL | |
def profile_data_required? | |
!new_record? | |
end | |
# Checks whether a password is needed or not. For validations only. | |
# Passwords are always required if it's a new record, or if the password | |
# or confirmation are being set somewhere. | |
def password_required? | |
return false if !persisted? && has_connected_facebook_account? | |
!persisted? || !password.nil? || !password_confirmation.nil? | |
end | |
def has_connected_facebook_account? | |
uid.present? | |
end | |
# taken from https://github.com/ging/social_stream/blob/12eca97a22a34fb44abd9341c6d25ad14c975c8e/base/app/models/actor.rb#L589 | |
# | |
# Returns [Integer] | |
def unread_messages_count | |
mailbox.inbox(:unread => true).count(:id, :distinct => true) | |
end | |
def to_param | |
"#{id}-#{full_name.parameterize}" | |
end | |
def has_access_to_rails_admin? | |
User::Types::ALL.reject { |role| role == User::Types::STUDENT }.include?(type) | |
end | |
def avatar_path(type) | |
raise "unknow type: #{type}" unless %w(small normal large).include?(type.to_s) | |
if has_connected_facebook_account? && !avatar? | |
facebook_avatar_url(type) | |
else | |
avatar(type.to_sym) | |
end | |
end | |
def facebook_avatar_url(type) | |
"http://graph.facebook.com/#{uid.to_s}/picture?type=#{type.to_s}" | |
end | |
def full_name | |
"#{first_name} #{last_name}" | |
end | |
alias_method :name, :full_name # required by Messageable | |
alias_method :to_s, :full_name # required by Forem | |
# Returning the email address of the model if an email should be sent for this object (Message or Notification). | |
# If no mail has to be sent, return nil. | |
def mailboxer_email(object) | |
end | |
def self.teacher_or_mentor | |
User.where 'type IN ("Teacher", "Mentor")' | |
end | |
# Find or create user based on Facebook Auth payload | |
# this method is called in omniauth callback action | |
# | |
# @param payload - request.env["omniauth.auth"] object that is passed from controller | |
# @param current_user - current logged in user(if present) | |
# | |
# Returns [User] | |
def self.find_or_create_from_facebook(payload, current_user) | |
if current_user.present? | |
current_user.update_attributes(:provider => payload.provider, :uid => payload.uid) | |
current_user | |
else | |
find_from(payload) || create_from(payload) | |
end | |
end | |
# Devise RegistrationsController by default calls "User.new_with_session" before building a resource. | |
# This means that, if we need to copy data from session whenever a user is initialized before sign up, | |
# we just need to implement new_with_session in our model. | |
# | |
# @see https://github.com/plataformatec/devise/wiki/OmniAuth%3A-Overview | |
def self.new_with_session(params, session) | |
super.tap do |user| | |
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"] | |
user.email = data["email"] if user.email.blank? | |
end | |
end | |
end | |
private | |
def self.find_from(payload) | |
where(:provider => payload.provider, :uid => payload.uid).first | |
end | |
def self.create_from(payload) | |
user = new(:first_name => payload.extra.raw_info.first_name, | |
:last_name => payload.extra.raw_info.last_name, | |
:provider => payload.provider, | |
:uid => payload.uid, | |
:email => payload.info.email) | |
user.skip_confirmation! | |
user.save | |
user | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment