Skip to content

Commit

Permalink
Following. Complete.
Browse files Browse the repository at this point in the history
  • Loading branch information
sudara committed Jan 5, 2009
1 parent 6473b41 commit 3b8f15c
Show file tree
Hide file tree
Showing 21 changed files with 205 additions and 29 deletions.
3 changes: 3 additions & 0 deletions app/controllers/assets_controller.rb
Expand Up @@ -80,6 +80,9 @@ def latest
@tab = 'home' @tab = 'home'
@welcome = true unless logged_in? @welcome = true unless logged_in?
@feature = Feature.published.first @feature = Feature.published.first
if logged_in? and current_user.has_followees?
@followee_tracks = current_user.new_tracks_from_followees(5)
end
end end
wants.rss do wants.rss do
@assets = Asset.latest(50) @assets = Asset.latest(50)
Expand Down
7 changes: 6 additions & 1 deletion app/controllers/users_controller.rb
Expand Up @@ -6,7 +6,7 @@ class UsersController < ApplicationController
before_filter :login_required, :except => [:index, :show, :new, :create, :activate, :bio] before_filter :login_required, :except => [:index, :show, :new, :create, :activate, :bio]
skip_before_filter :login_by_token, :only => :sudo skip_before_filter :login_by_token, :only => :sudo


rescue_from NoMethodError, :with => :user_not_found #rescue_from NoMethodError, :with => :user_not_found


def index def index
@page_title = "#{params[:sort] ? params[:sort].titleize+' - ' : ''} Musicians and Listeners" @page_title = "#{params[:sort] ? params[:sort].titleize+' - ' : ''} Musicians and Listeners"
Expand Down Expand Up @@ -169,6 +169,11 @@ def toggle_favorite
end end
render :nothing => true render :nothing => true
end end

def toggle_follow
current_user.add_or_remove_followee(params[:followee_id])
render :nothing => true
end


def destroy def destroy
return unless admin? return unless admin?
Expand Down
10 changes: 9 additions & 1 deletion app/helpers/users_helper.rb
Expand Up @@ -48,10 +48,18 @@ def setting(symbol_or_string, user=current_user)
def favorite_toggle(asset) def favorite_toggle(asset)
return unless logged_in? return unless logged_in?
is_favorite = current_user.has_as_favorite?(asset) is_favorite = current_user.has_as_favorite?(asset)
link_to((is_favorite ? 'remove from favorites' : 'add to favorites'), toggle_favorite_user_path(current_user, :asset_id => asset.id), link_to((is_favorite ? 'remove from favorites' : 'add to favorites'),
toggle_favorite_user_path(current_user, :asset_id => asset.id),
:class => 'add_to_favorites '+(is_favorite ? 'favorited' : '')) :class => 'add_to_favorites '+(is_favorite ? 'favorited' : ''))
end end


def follow_toggle(user)
return unless logged_in? and user.id != current_user.id
is_favorite = current_user.is_following?(user)
link_to ' ', toggle_follow_user_path(current_user, :followee_id => user.id),
:class => 'follow '+(is_favorite ? 'following' : '')
end

def new_to_user?(thing) def new_to_user?(thing)
thing && (logged_in? and current_user.last_session_at) && (current_user.last_session_at < thing.created_at.utc) thing && (logged_in? and current_user.last_session_at) && (current_user.last_session_at < thing.created_at.utc)
end end
Expand Down
2 changes: 1 addition & 1 deletion app/models/asset.rb
Expand Up @@ -96,7 +96,7 @@ def self.conditions_by_like(value, *columns)
end end


def self.latest(limit=10) def self.latest(limit=10)
find(:all, :include => [:user], :limit => limit, :order => 'assets.created_at DESC') find(:all, :include => [{:user => :pic}, :first_playlist], :limit => limit, :order => 'assets.created_at DESC')
end end


# needed for views in case we've got multiple assets on the same page # needed for views in case we've got multiple assets on the same page
Expand Down
32 changes: 32 additions & 0 deletions app/models/asset_mailer.rb
@@ -0,0 +1,32 @@
class AssetMailer < ActionMailer::Base


def upload_notification(asset, emails, sent_at = Time.now)
subject "[alonetone] '#{asset.user.name}' uploaded a new track!"
recipients ''
from 'noreply@alonetone.com'
bcc emails.join(', ')
sent_on sent_at
body :track => asset.name,
:name => asset.user.name,
:download_link => download_link_for(asset),
:play_link => play_link_for(asset),
:user_link => user_link_for(asset),
:exclamation => ["Sweet", "Yes", "Oooooh", "Alright", "Booya", "Yum","Celebrate", "OMG"]
end

protected

def user_link_for(asset)
'http://' + ALONETONE.url + '/' + asset.user.login
end

def play_link_for(asset)
user_link_for(asset) + '/tracks/' + asset.id.to_s
end

def download_link_for(asset)
play_link_for(asset) + '.mp3?source=email'
end

end
29 changes: 29 additions & 0 deletions app/models/asset_observer.rb
@@ -0,0 +1,29 @@
class AssetObserver < ActiveRecord::Observer
def after_create(asset)
if followers_exist_for?(asset)
AssetMailer.deliver_upload_notification(asset,emails_of_followers(asset))
end
end

protected

def followers_exist_for?(asset)
emails_of_followers(asset).size > 0
end

def emails_of_followers(asset)
followers_of(asset).inject([]) do |emails, follower|
emails << follower.email if user_wants_email?(follower)
emails
end
end

def followers_of(asset)
asset.user.followers
end

def user_wants_email?(user)
# anyone who doesn't have it set to false, aka, opt-out
(user.settings == nil) || (user.settings[:email_new_tracks] != "false")
end
end
2 changes: 1 addition & 1 deletion app/models/comment.rb
Expand Up @@ -3,7 +3,7 @@ class Comment < ActiveRecord::Base
named_scope :public, { named_scope :public, {
:conditions => {:spam => false, :private => :false}, :conditions => {:spam => false, :private => :false},
:order => 'created_at DESC', :order => 'created_at DESC',
:include => [:commenter => :pic] :include => [{:commenter => :pic}, :commentable]
} }


named_scope :include_private, { named_scope :include_private, {
Expand Down
7 changes: 7 additions & 0 deletions app/models/following.rb
@@ -0,0 +1,7 @@
class Following < ActiveRecord::Base

belongs_to :user, :counter_cache => :followers_count
belongs_to :follower, :class_name => 'User'

validates_presence_of :user_id, :follower_id
end
4 changes: 2 additions & 2 deletions app/models/playlist.rb
Expand Up @@ -10,9 +10,9 @@ class Playlist < ActiveRecord::Base


named_scope :favorites, {:conditions => ['is_favorite = ?',true]} named_scope :favorites, {:conditions => ['is_favorite = ?',true]}


named_scope :public, {:conditions => ['private != ? AND is_favorite = ? AND tracks_count > 1',true, false ]} named_scope :public, {:include => :pic, :conditions => ['private != ? AND is_favorite = ? AND tracks_count > 1',true, false ]}


named_scope :include_private, {:conditions => ['is_favorite = ?',false]} named_scope :include_private, {:include => :pic, :conditions => ['is_favorite = ?',false]}




has_one :pic, :as => :picable, :dependent => :destroy has_one :pic, :as => :picable, :dependent => :destroy
Expand Down
6 changes: 0 additions & 6 deletions app/models/stalking.rb

This file was deleted.

2 changes: 1 addition & 1 deletion app/models/track.rb
Expand Up @@ -20,7 +20,7 @@ class Track < ActiveRecord::Base
:select => 'DISTINCT assets.*, tracks.*', :select => 'DISTINCT assets.*, tracks.*',
:conditions => ['is_favorite = ?',true], :conditions => ['is_favorite = ?',true],
:order => 'tracks.created_at DESC', :order => 'tracks.created_at DESC',
:joins => :asset :joins => {:asset => {:user => :pic}}
} }




Expand Down
41 changes: 34 additions & 7 deletions app/models/user.rb
Expand Up @@ -71,14 +71,15 @@ class User < ActiveRecord::Base
:limit => 10, :limit => 10,
:order => 'listens_count DESC' :order => 'listens_count DESC'


# stalking
has_many :stalkers, :class_name => 'Stalking' has_many :followings, :dependent => :destroy

has_many :follows, :dependent => :destroy, :class_name => 'Following', :foreign_key => 'follower_id'
has_many :stalkees, :class_name => 'Stalking'
# people who are following this musician
has_many :followers, :through => :followings


has_many :new_tracks_from_stalkees, # musicians who this person follows
:through => :stalkees, has_many :followees, :through => :follows, :source => :follower
:class_name => 'Asset'


# The following attributes can be changed via mass assignment # The following attributes can be changed via mass assignment
attr_accessible :login, :email, :password, :password_confirmation, :website, :myspace, attr_accessible :login, :email, :password, :password_confirmation, :website, :myspace,
Expand Down Expand Up @@ -122,12 +123,38 @@ def hasnt_been_here_in(hours)
last_seen_at < hours.ago.utc last_seen_at < hours.ago.utc
end end


def is_following?(user)
follows.find_by_user_id(user)
end

def new_tracks_from_followees(limit)
Asset.find(:all, :limit => limit, :order => 'assets.created_at DESC',
:conditions => {:user_id => followee_ids})
end

def has_followees?
follows.count > 0
end

def add_or_remove_followee(followee_id)
return if followee_id == id # following yourself would be a pointless affair!
if is_following?(followee_id)
is_following?(followee_id).destroy
else
follows.find_or_create_by_user_id(followee_id)
end
end

def type def type
self.class.name self.class.name
end end


protected protected


def followee_ids
follows.find(:all, :select => 'user_id').collect(&:user_id)
end



def make_first_user_admin def make_first_user_admin
self.admin = true if User.count == 0 self.admin = true if User.count == 0
Expand Down
20 changes: 20 additions & 0 deletions app/views/asset_mailer/upload_notification.erb
@@ -0,0 +1,20 @@
Hi!

<%= @name %> just uploaded a new track on alonetone. <%= @exclamation.randomly_pick(1) %>!

It's so piping hot we don't even know the juicy details yet. <%= @name %> is still typing them in.

Listen to it at alonetone:
<%= @play_link %>

Download it directly:
<%= @download_link%>

-----8<-------------------------

You are getting this email because you decided to follow <%= @name %>. You can change your mind by clicking "un-follow" here:
<%= @user_link %>

You can also turn off all emails by editing your profile at alonetone.


7 changes: 7 additions & 0 deletions app/views/assets/latest.html.erb
Expand Up @@ -46,6 +46,13 @@
:title => 'alonetone radio: currently kicking ass' %> :title => 'alonetone radio: currently kicking ass' %>
</div> </div>


<% if @followee_tracks %>
<h2 id="kicking_ass" class="box">Tracks from those you follow</h2>
<div class="box">
<%= render :partial => 'assets/asset', :collection => @followee_tracks %>
</div>
<% end %>

<h2 id="recently_favorited" class="box">Recently favorited</h2> <h2 id="recently_favorited" class="box">Recently favorited</h2>
<div class="box"> <div class="box">
<%= render :partial => 'shared/favorite', :collection => @favorites %> <%= render :partial => 'shared/favorite', :collection => @favorites %>
Expand Down
3 changes: 2 additions & 1 deletion app/views/users/_user.html.erb
Expand Up @@ -4,8 +4,9 @@


<div class="user_title"> <div class="user_title">
<h1 class="user"><%=h @user.name %></h1><span class="user_location"><%= user_location(@user) %></span> <h1 class="user"><%=h @user.name %></h1><span class="user_location"><%= user_location(@user) %></span>
<%= follow_toggle(@user) %>
<% if authorized? %> <% if authorized? %>
<%= link_to 'edit your profile', edit_user_path(@user), :class => 'edit_profile' %> <%= link_to 'edit your profile', edit_user_path(@user), :class => "edit_profile #{ admin? ? 'admin' : ''}" %>
<%= link_to image_tag('icons/alonetone_plus_small.png'), user_plus_path(@user), :class=> 'alonetone_plus_link' if authorized? && @user.plus_enabled? %> <%= link_to image_tag('icons/alonetone_plus_small.png'), user_plus_path(@user), :class=> 'alonetone_plus_link' if authorized? && @user.plus_enabled? %>
<% end %> <% end %>
</div> </div>
Expand Down
11 changes: 10 additions & 1 deletion app/views/users/edit.html.erb
Expand Up @@ -98,12 +98,21 @@
</div> </div>


<div class="static_content"> <div class="static_content">
Email you new comments on your tracks?<br/> Should we email you new comments on your tracks?<br/>
<%= select_tag('user[settings][email_comments]', <%= select_tag('user[settings][email_comments]',
options_for_select([['of course, silly!','true'], ['I do not like email','false']], options_for_select([['of course, silly!','true'], ['I do not like email','false']],
setting(:email_comments))) %> setting(:email_comments))) %>


</div> </div>

<div class="static_content">
Email notifications when folks you follow upload tracks?<br/>
<%= select_tag('user[settings][email_new_tracks]',
options_for_select([['please! it helps me keep track of the artists i love','true'], ['I told you already, I hate email','false']],
setting(:email_new_tracks))) %>

</div>



<div class="static_content"> <div class="static_content">
<%= submit_tag "Save your alonetone settings" %> <%= submit_tag "Save your alonetone settings" %>
Expand Down
2 changes: 1 addition & 1 deletion config/environment.rb
Expand Up @@ -28,5 +28,5 @@


config.action_controller.session_store = :active_record_store config.action_controller.session_store = :active_record_store


config.active_record.observers = :user_observer, :comment_observer config.active_record.observers = :user_observer, :comment_observer, :asset_observer
end end
15 changes: 15 additions & 0 deletions db/migrate/20090103235851_replace_stalkings_with_followers.rb
@@ -0,0 +1,15 @@
class ReplaceStalkingsWithFollowers < ActiveRecord::Migration
def self.up
drop_table :stalkings
create_table :followings do |t|
t.integer :user_id
t.integer :follower_id
t.timestamps
end
add_index :followings, :user_id
add_index :followings, :follower_id
end

def self.down
end
end
8 changes: 8 additions & 0 deletions db/migrate/20090104003313_add_followers_count_to_user.rb
@@ -0,0 +1,8 @@
class AddFollowersCountToUser < ActiveRecord::Migration
def self.up
add_column :users, :followers_count, :integer, :default => 0
end

def self.down
end
end
6 changes: 3 additions & 3 deletions public/javascripts/application.js
Expand Up @@ -58,9 +58,9 @@ FavoriteToggle = $.klass(Remote.Link,{
FollowToggle = $.klass(Remote.Link,{ FollowToggle = $.klass(Remote.Link,{
beforeSend:function(e){ beforeSend:function(e){
if(this.element.hasClass('following')) if(this.element.hasClass('following'))
this.element.removeClass('following').html('Follow'); this.element.removeClass('following');
else else
this.element.addClass('following').html('Stop Following'); this.element.addClass('following');
} }
}); });


Expand Down Expand Up @@ -895,7 +895,7 @@ jQuery(function($) {
$('#single_track a.add_to_favorites').attach(FavoriteToggle); $('#single_track a.add_to_favorites').attach(FavoriteToggle);


// bio // bio
$('a.follow',this.more).attach(FollowToggle); $('a.follow').attach(FollowToggle);




// sort playlists // sort playlists
Expand Down
17 changes: 14 additions & 3 deletions public/stylesheets/sass/typography.sass
Expand Up @@ -366,9 +366,9 @@ a.edit_in_box
&:active &:active
:background-position -146px 0px :background-position -146px 0px


a.edit_profile a.edit_profile, a.follow
:display block :display block
:background url(../images/icons/edit_profile.png) no-repeat left center :background url(../images/icons/follow.png) no-repeat left center
:text-indent -1000px :text-indent -1000px
:width 48px :width 48px
:height 48px :height 48px
Expand All @@ -379,11 +379,22 @@ a.edit_profile
:background-position -48px 0px :background-position -48px 0px
&:active &:active
:background-position -96px 0px :background-position -96px 0px
a.edit_profile
:right 2px
:background url(../images/icons/edit_profile.png) no-repeat left center
&.admin
:right 50px
a.follow.following
:background-position -144px 0px
&:hover
:background-position -192px 0px
&:active
:background-position -240px 0px
a.alonetone_plus_link a.alonetone_plus_link
:position absolute :position absolute
:float right :float right
:top 12px :top 12px
:right 60px :right 110px


.button_wrapper .button_wrapper
:float right :float right
Expand Down

0 comments on commit 3b8f15c

Please sign in to comment.