Skip to content

Instantly share code, notes, and snippets.

@craigmartin
Created April 1, 2011 19:47

Revisions

  1. craigmartin created this gist Apr 1, 2011.
    543 changes: 543 additions & 0 deletions new models.rb file
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,543 @@
    %w(dm-core dm-timestamps dm-validations dm-aggregates).each {|lib| gem lib, '=1.1.0'}
    %w(dm-core dm-timestamps dm-validations dm-aggregates dm-migrations RMagick aws ./config).each { |lib| require lib}
    include Magick
    DataMapper.setup(:default, ENV['DATABASE_URL'] || 'mysql://root:fa1556cm@localhost/monsoc')

    S3 = Aws::S3Interface.new(S3_CONFIG['AWS_ACCESS_KEY'], S3_CONFIG['AWS_SECRET_KEY'], {:multi_thread => true, :protocol => 'http', :port => 80} )

    module Commentable
    def people_who_likes
    self.likes.collect { |l| "<a href='/user/#{l.user.nickname}'>#{l.user.formatted_name}</a>" }
    end
    end

    module Update_or_create

    # update_or_create method: finds and updates, or creates;
    # merger is a boolean that determines if the conditions are merged with the attributes upon create;
    # merge = true => merges conditions to attributes and passes the merge to the create method
    # merge = false => only attributes are passed into the create method
    def update_or_create(conditions = {}, attributes = {}, merger = true)
    (first(conditions) && first(conditions).update(attributes)) || create(merger ? (conditions.merge(attributes)) : attributes )
    end

    end # Module Update_or_create

    class User

    include DataMapper::Resource
    #include MongoMapper::Document

    property :id, Serial
    property :email, String, :length => 255
    property :nickname, String, :length => 255
    property :formatted_name, String, :length => 255
    property :sex, String, :length => 6
    property :relationship_status, String
    property :provider, String, :length => 255
    property :identifier, String, :length => 255
    property :photo_url, String, :length => 255
    property :location, String, :length => 255
    property :description, String, :length => 255
    property :interests, Text
    property :education, Text
    has n, :relationships, :child_key => [ :user_id ]
    has n, :followers, :through => :relationships, :model => 'User', :child_key => [:user_id]
    has n, :follows, :through => :relationships, :model => 'User', :remote_name => :user, :child_key => [:follower_id]
    has n, :statuses
    belongs_to :wall
    has n, :groups, :through => Resource
    has n, :sent_messages, :model => 'Message', :child_key => [:user_id]
    has n, :received_messages, :model => 'Message', :child_key => [:recipient_id]
    has n, :confirms
    has n, :confirmed_events, :through => :confirms, :model => 'Event', :child_key => [:user_id], :date.gte => Date.today
    has n, :pendings
    has n, :pending_events, :through => :pendings, :model => 'Event', :child_key => [:user_id], :date.gte => Date.today
    has n, :requests
    has n, :albums
    has n, :photos, :through => :albums
    has n, :comments
    has n, :activities
    has n, :pages

    validates_uniqueness_of :nickname, :message => "Someone else has taken up this nickname, try something else!"
    after :create, :create_s3_bucket
    after :create, :create_wall

    #def update

    def add_friend(user)
    Relationship.create(:user => user, :follower => self)
    end

    def friends
    (followers + follows).uniq
    end

    def self.find(identifier)
    u = first(:identifier => identifier)
    u = new(:identifier => identifier) if u.nil?
    return u
    end

    def feed
    feed = [] + activities
    friends.each do |friend|
    feed += friend.activities
    end
    return feed.sort {|x,y| y.created_at <=> x.created_at}
    end

    def possessive_pronoun
    sex.downcase == 'male' ? 'his' : 'her'
    end

    def pronoun
    sex.downcase == 'male' ? 'he' : 'she'
    end

    def create_s3_bucket
    S3.create_bucket("fc.#{id}")
    end

    def create_wall
    self.wall = Wall.create
    self.save
    end

    def all_events
    confirmed_events + pending_events
    end

    def friend_events
    events = []
    friends.each do |friend|
    events += friend.confirmed_events
    end
    return events.sort {|x,y| y.time <=> x.time}
    end

    def friend_groups
    groups = []
    friends.each do |friend|
    groups += friend.groups
    end
    groups - self.groups
    end

    end

    class Relationship
    include DataMapper::Resource
    #include MongoMapper::Document

    property :user_id, Integer, :key => true, :min => 1
    property :follower_id, Integer, :key => true, :min => 1
    belongs_to :user, :child_key => [:user_id]
    belongs_to :follower, :model => 'User', :child_key => [:follower_id]
    after :save, :add_activity

    def add_activity
    Activity.create(:user => user, :activity_type => 'relationship', :text => "<a href='/user/#{user.nickname}'>#{user.formatted_name}</a> and <a href='/user/#{follower.nickname}'>#{follower.formatted_name}</a> are now friends.")
    end
    end

    class Mention
    include DataMapper::Resource
    #include MongoMapper::Document

    property :id, Serial
    belongs_to :user
    belongs_to :status
    has n, :mentions
    has n, :mentioned_users, :model =>'User', :child_key => [:id]
    end

    URL_REGEXP = Regexp.new('\b ((https?|telnet|gopher|file|wais|ftp) : [\w/#~:.?+=&%@!\-] +?) (?=[.:?\-] * (?: [^\w/#~:.?+=&%@!\-]| $ ))', Regexp::EXTENDED)
    AT_REGEXP = Regexp.new('@[\w.@_-]+', Regexp::EXTENDED)

    class Message
    include DataMapper::Resource
    #include MongoMapper::Document

    property :id, Serial
    property :subject, String
    property :text, Text
    property :created_at, DateTime
    property :read, Boolean, :default => false
    property :thread, Integer

    belongs_to :sender, :model => 'User', :child_key => [:user_id]
    belongs_to :recipient, :model => 'User', :child_key => [:recipient_id]
    end

    class Status
    include DataMapper::Resource
    #include MongoMapper::Document
    include Commentable

    property :id, Serial
    property :text, String, :length => 160
    property :created_at, DateTime
    belongs_to :recipient, :model => "User", :child_key => [:recipient_id]
    belongs_to :user
    has n, :mentions
    has n, :mentioned_users, :through => :mentions, :model => 'User', :child_key => [:user_id]
    has n, :comments
    has n, :likes

    before :save do
    @mentions = []
    process
    end

    after :save do
    unless @mentions.nil?
    @mentions.each {|m|
    m.status = self
    m.save
    }
    end
    Activity.create(:user => user, :activity_type => 'status', :text => self.text )
    end

    # general scrubbing
    def process
    # process url
    urls = self.text.scan(URL_REGEXP)
    urls.each { |url|
    tiny_url = RestClient.get "http://tinyurl.com/api-create.php?url=#{url[0]}"
    self.text.sub!(url[0], "<a href='#{tiny_url}'>#{tiny_url}</a>")
    }
    # process @
    ats = self.text.scan(AT_REGEXP)
    ats.each { |at|
    user = User.first(:nickname => at[1,at.length])
    if user
    self.text.sub!(at, "<a href='/#{user.nickname}'>#{at}</a>")
    @mentions << Mention.new(:user => user, :status => self)
    end
    }
    end

    def starts_with?(prefix)
    prefix = prefix.to_s
    self.text[0, prefix.length] == prefix
    end

    def to_json(*a)
    {'id' => id, 'text' => text, 'created_at' => created_at, 'user' => user.nickname}.to_json(*a)
    end
    end

    class Activity
    include DataMapper::Resource
    #include MongoMapper::Document
    include Commentable

    property :id, Serial
    property :activity_type, String
    property :text, Text
    property :created_at, DateTime
    has n, :comments
    has n, :likes
    belongs_to :user
    end

    class Photo
    include DataMapper::Resource
    #include MongoMapper::Document
    include Commentable

    attr_writer :tmpfile
    property :id, Serial
    property :title, String, :length => 255
    property :caption, String, :length => 255
    property :privacy, String, :default => 'public'

    property :format, String
    property :created_at, DateTime

    belongs_to :album

    has n, :annotations
    has n, :comments
    has n, :likes

    after :save, :save_image_s3
    after :create, :add_activity
    after :destroy, :destroy_image_s3


    def filename_display; "#{id}.disp"; end
    def filename_thumbnail; "#{id}.thmb"; end

    def s3_url_thumbnail; S3.get_link(s3_bucket, filename_thumbnail, Time.now.to_i + (365*24*60*60)); end
    def s3_url_display; S3.get_link(s3_bucket, filename_display, Time.now.to_i + (365*24*60*60)); end

    def url_thumbnail
    s3_url_thumbnail
    end

    def url_display
    s3_url_display
    end

    def previous_in_album
    photos = album.photos
    index = photos.index self
    return nil unless index
    photos[index - 1] if index > 0
    end

    def next_in_album
    photos = album.photos
    index = photos.index self
    return nil unless index
    photos[index + 1] if index < album.photos.length
    end

    def save_image_s3
    return unless @tmpfile
    img = Magick::Image.from_blob(@tmpfile.open.read).first
    display = img.resize_to_fit(500, 500)
    S3.put(s3_bucket, filename_display, display.to_blob)

    t = img.resize_to_fit(150, 150)
    length = t.rows > t.columns ? t.columns : t.rows
    thumbnail = t.crop(CenterGravity, length, length)
    S3.put(s3_bucket, filename_thumbnail, thumbnail.to_blob)
    end

    def destroy_image_s3
    S3.delete s3_bucket, filename_display
    S3.delete s3_bucket, filename_thumbnail
    end

    def s3_bucket
    "fc.#{album.user.id}"
    end

    def add_activity
    Activity.create(:user => album.user, :activity_type => 'photo', :text => "<a href='/user/#{album.user.nickname}'>#{album.user.formatted_name}</a> added a new photo - <a href='/photo/#{self.id}'><img class='span-1' src='#{self.url_thumbnail}'/></a>")
    end

    end

    class Album
    include DataMapper::Resource
    property :id, Serial
    property :name, String, :length => 255
    property :description, Text
    property :created_at, DateTime

    belongs_to :user
    has n, :photos
    belongs_to :cover_photo, :model => 'Photo', :child_key => [:cover_photo_id]
    after :save, :add_activity

    def add_activity
    Activity.create(:user => user, :activity_type => 'album', :text => "<a href='/user/#{user.nickname}'>#{user.formatted_name}</a> created a new album <a href='/album/#{self.id}'>#{self.name}</a>")
    end
    end

    class Annotation
    include DataMapper::Resource
    property :id, Serial
    property :description,Text
    property :x, Integer
    property :y, Integer
    property :height, Integer
    property :width, Integer
    property :created_at, DateTime

    belongs_to :photo
    after :save, :add_activity

    def add_activity
    Activity.create(:user => self.photo.album.user, :activity_type => 'annotation', :text => "<a href='/user/#{self.photo.album.user.nickname}'>#{self.photo.album.user.formatted_name}</a> annotated a photo - <a href='/photo/#{self.photo.id}'><img class='span-1' src='#{self.photo.url_thumbnail}'/></a> with '#{self.description}'")
    end

    end

    class Group
    include DataMapper::Resource

    property :id, Serial
    property :name, String
    property :description, String

    has n, :pages
    has n, :members, :model => 'User', :through => Resource
    belongs_to :user
    belongs_to :wall

    after :create, :create_wall

    def create_wall
    self.wall = Wall.create
    self.save
    end

    after :create, :add_activity

    def add_activity
    Activity.create(:user => self.user, :activity_type => 'event', :text => "<a href='/user/#{self.user.nickname}'>#{self.user.formatted_name}</a> created a new group - <a href='/group/#{self.id}'>#{self.name}</a>.")
    end
    end


    class Event
    include DataMapper::Resource

    property :id, Serial
    property :name, String
    property :description, String
    property :venue, String
    property :date, DateTime
    property :time, Time

    belongs_to :user
    has n, :pages
    has n, :confirms
    has n, :confirmed_users, :through => :confirms, :model => 'User', :child_key => [:event_id], :mutable => true
    has n, :pendings
    has n, :pending_users, :through => :pendings, :model => 'User', :child_key => [:event_id], :mutable => true
    has n, :declines
    has n, :declined_users, :through => :declines, :model => 'User', :child_key => [:event_id], :mutable => true

    belongs_to :wall
    after :create, :create_wall

    def create_wall
    self.wall = Wall.create
    self.save
    end

    after :create, :add_activity

    def add_activity
    Activity.create(:user => self.user, :activity_type => 'event', :text => "<a href='/user/#{self.user.nickname}'>#{self.user.formatted_name}</a> created a new event - <a href='/event/#{self.id}'>#{self.name}</a>.")
    end

    end

    class Pending
    include DataMapper::Resource
    property :id, Serial
    belongs_to :pending_user, :model => 'User', :child_key => [:user_id]
    belongs_to :pending_event, :model => 'Event', :child_key => [:event_id]

    end

    class Decline
    include DataMapper::Resource
    property :id, Serial
    belongs_to :declined_user, :model => 'User', :child_key => [:user_id]
    belongs_to :declined_event, :model => 'Event', :child_key => [:event_id]
    end

    class Confirm
    include DataMapper::Resource
    property :id, Serial
    belongs_to :confirmed_user, :model => 'User', :child_key => [:user_id]
    belongs_to :confirmed_event, :model => 'Event', :child_key => [:event_id]
    end

    class Wall
    include DataMapper::Resource
    property :id, Serial
    has n, :posts

    end


    class Page
    include DataMapper::Resource
    include Commentable
    property :id, Serial
    property :title, String
    property :body, Text
    property :created_at, DateTime
    has n, :comments
    has n, :likes
    belongs_to :user
    belongs_to :event
    belongs_to :group


    after :create, :add_activity

    def add_activity
    if self.event
    Activity.create(:user => self.user, :activity_type => 'event page', :text => "<a href='/user/#{self.user.nickname}'>#{self.user.formatted_name}</a> created a page - <a href='/event/page/#{self.id}'>#{self.title}</a> for the event <a href='/event/#{self.event.id}'>#{self.event.name}</a>.")
    elsif self.group
    Activity.create(:user => self.user, :activity_type => 'group page', :text => "<a href='/user/#{self.user.nickname}'>#{self.user.formatted_name}</a> created a page - <a href='/group/page/#{self.id}'>#{self.title}</a> for the group <a href='/group/#{self.group.id}'>#{self.group.name}</a>.")
    else
    Activity.create(:user => self.user, :activity_type => 'page', :text => "<a href='/user/#{self.user.nickname}'>#{self.user.formatted_name}</a> created a page - <a href='/page/#{self.id}'>#{self.title}</a>.")
    end
    end
    end


    class Post
    include DataMapper::Resource
    include Commentable
    property :id, Serial
    property :text, Text
    property :created_at, DateTime
    belongs_to :user
    belongs_to :wall
    has n, :comments
    has n, :likes

    end



    class Comment
    include DataMapper::Resource

    property :id, Serial
    property :text, Text
    property :created_at, DateTime
    belongs_to :user
    belongs_to :page
    belongs_to :post
    belongs_to :photo
    belongs_to :activity
    belongs_to :status

    end

    class Like
    include DataMapper::Resource
    property :id, Serial
    belongs_to :user
    belongs_to :page
    belongs_to :post
    belongs_to :photo
    belongs_to :activity
    belongs_to :status

    end

    class Request
    include DataMapper::Resource
    property :id, Serial
    property :text, Text
    property :created_at, DateTime

    belongs_to :from, :model => User, :child_key => [:from_id]
    belongs_to :user

    def approve
    self.user.add_friend(self.from)
    end
    end

    DataMapper.finalize
    require 'dm-migrations'
    DataMapper.auto_migrate!
    # Create or upgrade all tables at once, like magic
    # DataMapper.auto_upgrade!