Merge branch 'follow_tags'
This commit is contained in:
commit
47e0558c3e
21 changed files with 373 additions and 37 deletions
|
|
@ -10,6 +10,9 @@ class AspectsController < ApplicationController
|
||||||
respond_to :html, :js
|
respond_to :html, :js
|
||||||
respond_to :json, :only => [:show, :create]
|
respond_to :json, :only => [:show, :create]
|
||||||
|
|
||||||
|
helper_method :tags, :tag_followings
|
||||||
|
helper_method :all_aspects_selected?
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if params[:a_ids]
|
if params[:a_ids]
|
||||||
@aspects = current_user.aspects.where(:id => params[:a_ids])
|
@aspects = current_user.aspects.where(:id => params[:a_ids])
|
||||||
|
|
@ -158,11 +161,23 @@ class AspectsController < ApplicationController
|
||||||
params[:max_time] ||= Time.now + 1
|
params[:max_time] ||= Time.now + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
helper_method :all_aspects_selected?
|
|
||||||
def all_aspects_selected?
|
def all_aspects_selected?
|
||||||
@aspect == :all
|
@aspect == :all
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tag_followings
|
||||||
|
if current_user
|
||||||
|
if @tag_followings == nil
|
||||||
|
@tag_followings = current_user.tag_followings
|
||||||
|
end
|
||||||
|
@tag_followings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tags
|
||||||
|
@tags ||= current_user.followed_tags
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def save_sort_order
|
def save_sort_order
|
||||||
if params[:sort_order].present?
|
if params[:sort_order].present?
|
||||||
|
|
|
||||||
32
app/controllers/tag_followings_controller.rb
Normal file
32
app/controllers/tag_followings_controller.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
class TagFollowingsController < ApplicationController
|
||||||
|
before_filter :authenticate_user!
|
||||||
|
|
||||||
|
# POST /tag_followings
|
||||||
|
# POST /tag_followings.xml
|
||||||
|
def create
|
||||||
|
@tag = ActsAsTaggableOn::Tag.find_or_create_by_name(params[:name])
|
||||||
|
@tag_following = current_user.tag_followings.new(:tag_id => @tag.id)
|
||||||
|
|
||||||
|
if @tag_following.save
|
||||||
|
flash[:notice] = I18n.t('tag_followings.create.success', :name => params[:name])
|
||||||
|
else
|
||||||
|
flash[:error] = I18n.t('tag_followings.create.failure', :name => params[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to tag_path(:name => params[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /tag_followings/1
|
||||||
|
# DELETE /tag_followings/1.xml
|
||||||
|
def destroy
|
||||||
|
@tag = ActsAsTaggableOn::Tag.find_by_name(params[:name])
|
||||||
|
@tag_following = current_user.tag_followings.where(:tag_id => @tag.id).first
|
||||||
|
if @tag_following && @tag_following.destroy
|
||||||
|
flash[:notice] = I18n.t('tag_followings.destroy.success', :name => params[:name])
|
||||||
|
else
|
||||||
|
flash[:error] = I18n.t('tag_followings.destroy.failure', :name => params[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to tag_path(:name => params[:name])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -8,6 +8,8 @@ class TagsController < ApplicationController
|
||||||
skip_before_filter :set_grammatical_gender
|
skip_before_filter :set_grammatical_gender
|
||||||
before_filter :ensure_page, :only => :show
|
before_filter :ensure_page, :only => :show
|
||||||
|
|
||||||
|
helper_method :tag_followed?
|
||||||
|
|
||||||
respond_to :html, :only => [:show]
|
respond_to :html, :only => [:show]
|
||||||
respond_to :json, :only => [:index]
|
respond_to :json, :only => [:index]
|
||||||
|
|
||||||
|
|
@ -41,8 +43,10 @@ class TagsController < ApplicationController
|
||||||
def show
|
def show
|
||||||
@aspect = :tag
|
@aspect = :tag
|
||||||
if current_user
|
if current_user
|
||||||
@posts = StatusMessage.joins(:contacts).where(:pending => false).where(
|
@posts = StatusMessage.
|
||||||
Contact.arel_table[:user_id].eq(current_user.id).or(
|
joins("LEFT OUTER JOIN post_visibilities ON post_visibilities.post_id = posts.id").
|
||||||
|
joins("LEFT OUTER JOIN contacts ON contacts.id = post_visibilities.contact_id").
|
||||||
|
where(Contact.arel_table[:user_id].eq(current_user.id).or(
|
||||||
StatusMessage.arel_table[:public].eq(true).or(
|
StatusMessage.arel_table[:public].eq(true).or(
|
||||||
StatusMessage.arel_table[:author_id].eq(current_user.person.id)
|
StatusMessage.arel_table[:author_id].eq(current_user.person.id)
|
||||||
)
|
)
|
||||||
|
|
@ -55,7 +59,6 @@ class TagsController < ApplicationController
|
||||||
|
|
||||||
max_time = params[:max_time] ? Time.at(params[:max_time].to_i) : Time.now
|
max_time = params[:max_time] ? Time.at(params[:max_time].to_i) : Time.now
|
||||||
@posts = @posts.where(StatusMessage.arel_table[:created_at].lt(max_time))
|
@posts = @posts.where(StatusMessage.arel_table[:created_at].lt(max_time))
|
||||||
|
|
||||||
@posts = @posts.includes(:comments, :photos).order('posts.created_at DESC').limit(15)
|
@posts = @posts.includes(:comments, :photos).order('posts.created_at DESC').limit(15)
|
||||||
|
|
||||||
@posts = PostsFake.new(@posts)
|
@posts = PostsFake.new(@posts)
|
||||||
|
|
@ -69,4 +72,11 @@ class TagsController < ApplicationController
|
||||||
@people_count = Person.where(:id => profiles.map{|p| p.person_id}).count
|
@people_count = Person.where(:id => profiles.map{|p| p.person_id}).count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def tag_followed?
|
||||||
|
if @tag_followed.nil?
|
||||||
|
@tag_followed = TagFollowing.joins(:tag).where(:tags => {:name => params[:name]}, :user_id => current_user.id).exists? #,
|
||||||
|
end
|
||||||
|
@tag_followed
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
2
app/helpers/tag_followings_helper.rb
Normal file
2
app/helpers/tag_followings_helper.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
module TagFollowingsHelper
|
||||||
|
end
|
||||||
6
app/models/tag_following.rb
Normal file
6
app/models/tag_following.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
class TagFollowing < ActiveRecord::Base
|
||||||
|
belongs_to :user
|
||||||
|
belongs_to :tag, :class_name => "ActsAsTaggableOn::Tag"
|
||||||
|
|
||||||
|
validates_uniqueness_of :tag_id, :scope => :user_id
|
||||||
|
end
|
||||||
|
|
@ -39,6 +39,8 @@ class User < ActiveRecord::Base
|
||||||
has_many :contact_people, :through => :contacts, :source => :person
|
has_many :contact_people, :through => :contacts, :source => :person
|
||||||
has_many :services, :dependent => :destroy
|
has_many :services, :dependent => :destroy
|
||||||
has_many :user_preferences, :dependent => :destroy
|
has_many :user_preferences, :dependent => :destroy
|
||||||
|
has_many :tag_followings, :dependent => :destroy
|
||||||
|
has_many :followed_tags, :through => :tag_followings, :source => :tag
|
||||||
|
|
||||||
has_many :authorizations, :class_name => 'OAuth2::Provider::Models::ActiveRecord::Authorization', :foreign_key => :resource_owner_id
|
has_many :authorizations, :class_name => 'OAuth2::Provider::Models::ActiveRecord::Authorization', :foreign_key => :resource_owner_id
|
||||||
has_many :applications, :through => :authorizations, :source => :client
|
has_many :applications, :through => :authorizations, :source => :client
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,17 @@
|
||||||
.section
|
.section
|
||||||
= render 'aspects/aspect_listings'
|
= render 'aspects/aspect_listings'
|
||||||
|
|
||||||
|
.section
|
||||||
|
%ul.left_nav
|
||||||
|
%li
|
||||||
|
%div.root_element
|
||||||
|
= t('aspects.index.tags_following')
|
||||||
|
|
||||||
|
%ul.sub_nav
|
||||||
|
- for tg in tags
|
||||||
|
%li
|
||||||
|
= link_to "##{tg.name}", tag_path(:name => tg.name), :class => "tag_selector"
|
||||||
|
|
||||||
.span-13.append-1.prepend-5
|
.span-13.append-1.prepend-5
|
||||||
#aspect_stream_container.stream_container
|
#aspect_stream_container.stream_container
|
||||||
= render 'aspect_stream',
|
= render 'aspect_stream',
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
-# licensed under the Affero General Public License version 3 or later. See
|
-# licensed under the Affero General Public License version 3 or later. See
|
||||||
-# the COPYRIGHT file.
|
-# the COPYRIGHT file.
|
||||||
|
|
||||||
|
|
||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
- if params[:name]
|
- if params[:name]
|
||||||
= "##{params[:name]}"
|
= "##{params[:name]}"
|
||||||
|
|
@ -11,18 +12,43 @@
|
||||||
- content_for :head do
|
- content_for :head do
|
||||||
= include_javascripts :home
|
= include_javascripts :home
|
||||||
:javascript
|
:javascript
|
||||||
$(".people_stream .pagination a").live("click", function() {
|
$(document).ready(function(){
|
||||||
$.getScript(this.href);
|
$(".button.tag_following").hover(function(){
|
||||||
return false;
|
$this = $(this);
|
||||||
|
$this.removeClass("in_aspects");
|
||||||
|
$this.val("#{t('.stop_following', :tag => params[:name])}");
|
||||||
|
},
|
||||||
|
function(){
|
||||||
|
$this = $(this);
|
||||||
|
$this.addClass("in_aspects");
|
||||||
|
$this.val("#{t('.following', :tag => params[:name])}");
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
- content_for :body_class do
|
- content_for :body_class do
|
||||||
= "tags_show"
|
= "tags_show"
|
||||||
|
|
||||||
.span-24.last
|
.span-6
|
||||||
%h1.tag
|
%h3
|
||||||
|
= t('people', :count => @people_count)
|
||||||
|
|
||||||
|
.side_stream.stream
|
||||||
|
= render :partial => 'people/index', :locals => {:people => @people}
|
||||||
|
|
||||||
|
.span-15.last
|
||||||
|
.stream_container
|
||||||
|
#author_info
|
||||||
|
- if user_signed_in? && current_user.person != @person
|
||||||
|
.right
|
||||||
|
- unless tag_followed?
|
||||||
|
= button_to t('.follow', :tag => params[:name]), tag_tag_followings_path(:name => params[:name]), :method => :post, :class => 'button take_action'
|
||||||
|
- else
|
||||||
|
= button_to t('.following', :tag => params[:name]), tag_tag_followings_path(:name => params[:name]), :method => :delete, :class => 'button red_on_hover tag_following in_aspects take_action'
|
||||||
|
%h2
|
||||||
= "##{params[:name]}"
|
= "##{params[:name]}"
|
||||||
|
|
||||||
.span-13
|
%hr
|
||||||
|
|
||||||
#main_stream.stream
|
#main_stream.stream
|
||||||
- if @posts.length > 0
|
- if @posts.length > 0
|
||||||
= render 'shared/stream', :posts => @posts
|
= render 'shared/stream', :posts => @posts
|
||||||
|
|
@ -31,9 +57,3 @@
|
||||||
- else
|
- else
|
||||||
= t('.nobody_talking', :tag => "##{params[:name]}")
|
= t('.nobody_talking', :tag => "##{params[:name]}")
|
||||||
|
|
||||||
.prepend-2.span-9.last
|
|
||||||
%h3
|
|
||||||
= t('people', :count => @people_count)
|
|
||||||
|
|
||||||
.side_stream.stream
|
|
||||||
= render :partial => 'people/index', :locals => {:people => @people}
|
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,7 @@ en:
|
||||||
work: "Work"
|
work: "Work"
|
||||||
index:
|
index:
|
||||||
your_aspects: "Your Aspects"
|
your_aspects: "Your Aspects"
|
||||||
|
tags_following: "Followed Tags"
|
||||||
handle_explanation: "This is your diaspora id. Like an email address, you can give this to people to reach you."
|
handle_explanation: "This is your diaspora id. Like an email address, you can give this to people to reach you."
|
||||||
no_contacts: "No contacts"
|
no_contacts: "No contacts"
|
||||||
post_a_message: "post a message >>"
|
post_a_message: "post a message >>"
|
||||||
|
|
@ -697,6 +698,17 @@ en:
|
||||||
posts_tagged_with: "Posts tagged with #%{tag}"
|
posts_tagged_with: "Posts tagged with #%{tag}"
|
||||||
nobody_talking: "Nobody is talking about %{tag} yet."
|
nobody_talking: "Nobody is talking about %{tag} yet."
|
||||||
people_tagged_with: "People tagged with %{tag}"
|
people_tagged_with: "People tagged with %{tag}"
|
||||||
|
follow: "Follow #%{tag}"
|
||||||
|
following: "Following #%{tag}"
|
||||||
|
stop_following: "Stop Following #%{tag}"
|
||||||
|
|
||||||
|
tag_followings:
|
||||||
|
create:
|
||||||
|
success: "Successfully following: #%{name}"
|
||||||
|
failure: "Failed to follow: #%{name}"
|
||||||
|
destroy:
|
||||||
|
success: "Successfully stopped following: #%{name}"
|
||||||
|
failure: "Failed to stop following: #%{name}"
|
||||||
|
|
||||||
tokens:
|
tokens:
|
||||||
show:
|
show:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
Diaspora::Application.routes.draw do
|
Diaspora::Application.routes.draw do
|
||||||
|
|
||||||
|
|
||||||
# Posting and Reading
|
# Posting and Reading
|
||||||
|
|
||||||
resources :aspects do
|
resources :aspects do
|
||||||
|
|
@ -34,6 +35,9 @@ Diaspora::Application.routes.draw do
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :tags, :only => [:index]
|
resources :tags, :only => [:index]
|
||||||
|
post "/tags/:name/tag_followings" => "tag_followings#create", :as => 'tag_tag_followings'
|
||||||
|
delete "/tags/:name/tag_followings" => "tag_followings#destroy"
|
||||||
|
|
||||||
get 'tags/:name' => 'tags#show', :as => 'tag'
|
get 'tags/:name' => 'tags#show', :as => 'tag'
|
||||||
|
|
||||||
resources :apps, :only => [:show]
|
resources :apps, :only => [:show]
|
||||||
|
|
|
||||||
14
db/migrate/20110701215925_create_tag_followings.rb
Normal file
14
db/migrate/20110701215925_create_tag_followings.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
class CreateTagFollowings < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
create_table :tag_followings do |t|
|
||||||
|
t.integer :tag_id
|
||||||
|
t.integer :user_id
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
drop_table :tag_followings
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -326,6 +326,13 @@ ActiveRecord::Schema.define(:version => 20110705003445) do
|
||||||
|
|
||||||
add_index "services", ["user_id"], :name => "index_services_on_user_id"
|
add_index "services", ["user_id"], :name => "index_services_on_user_id"
|
||||||
|
|
||||||
|
create_table "tag_followings", :force => true do |t|
|
||||||
|
t.integer "tag_id"
|
||||||
|
t.integer "user_id"
|
||||||
|
t.datetime "created_at"
|
||||||
|
t.datetime "updated_at"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "taggings", :force => true do |t|
|
create_table "taggings", :force => true do |t|
|
||||||
t.integer "tag_id"
|
t.integer "tag_id"
|
||||||
t.integer "taggable_id"
|
t.integer "taggable_id"
|
||||||
|
|
|
||||||
45
features/follows_tags.feature
Normal file
45
features/follows_tags.feature
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
@javascript
|
||||||
|
Feature: posting
|
||||||
|
In order to takeover humanity for the good of society
|
||||||
|
As a rock star
|
||||||
|
I want to see what humanity is saying about particular tags
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a user with username "bob"
|
||||||
|
And a user with username "alice"
|
||||||
|
When I sign in as "bob@bob.bob"
|
||||||
|
|
||||||
|
And I am on the home page
|
||||||
|
|
||||||
|
And I expand the publisher
|
||||||
|
And I fill in "status_message_fake_text" with "I am da #boss"
|
||||||
|
And I press the first ".public_icon" within "#publisher"
|
||||||
|
And I press "Share"
|
||||||
|
And I wait for the ajax to finish
|
||||||
|
And I wait for the ajax to finish
|
||||||
|
|
||||||
|
And I follow "#boss"
|
||||||
|
And I wait for the ajax to finish
|
||||||
|
Then I should see "I am da #boss"
|
||||||
|
|
||||||
|
|
||||||
|
And I go to the destroy user session page
|
||||||
|
|
||||||
|
And I sign in as "alice@alice.alice"
|
||||||
|
And I search for "#boss"
|
||||||
|
And I press "Follow #boss"
|
||||||
|
And I wait for the ajax to finish
|
||||||
|
|
||||||
|
Scenario: see a tag that I am following
|
||||||
|
When I go to the home page
|
||||||
|
And I follow "#boss"
|
||||||
|
Then I should see "I am da #boss"
|
||||||
|
|
||||||
|
Scenario: can stop following a particular tag
|
||||||
|
When I press "Stop Following #boss"
|
||||||
|
|
||||||
|
And I go to the home page
|
||||||
|
Then I should not see "#boss" within ".left_nav"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ Feature: new user registration
|
||||||
And I fill in "profile_last_name" with "Hai"
|
And I fill in "profile_last_name" with "Hai"
|
||||||
And I fill in "tags" with "#tags"
|
And I fill in "tags" with "#tags"
|
||||||
And I press "Save and continue"
|
And I press "Save and continue"
|
||||||
And I wait for "step 2" to load
|
And I wait for the ajax to finish
|
||||||
Then I should see "Profile updated"
|
Then I should see "Profile updated"
|
||||||
And I should see "Would you like to find your Facebook friends on Diaspora?"
|
And I should see "Would you like to find your Facebook friends on Diaspora?"
|
||||||
And I follow "Skip"
|
And I follow "Skip"
|
||||||
|
|
@ -31,5 +31,4 @@ Feature: new user registration
|
||||||
|
|
||||||
Scenario: new user skips the setup wizard
|
Scenario: new user skips the setup wizard
|
||||||
When I follow "skip getting started"
|
When I follow "skip getting started"
|
||||||
And I wait for "the aspects page" to load
|
|
||||||
Then I should be on the aspects page
|
Then I should be on the aspects page
|
||||||
|
|
|
||||||
|
|
@ -129,15 +129,6 @@ When /^I click ok in the confirm dialog to appear next$/ do
|
||||||
JS
|
JS
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I wait for "([^\"]*)" to load$/ do |page_name|
|
|
||||||
wait_until(10) do
|
|
||||||
uri = URI.parse(current_url)
|
|
||||||
current_location = uri.path
|
|
||||||
current_location << "?#{uri.query}" unless uri.query.blank?
|
|
||||||
current_location == path_to(page_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Then /^I should get download alert$/ do
|
Then /^I should get download alert$/ do
|
||||||
page.evaluate_script("window.alert = function() { return true; }")
|
page.evaluate_script("window.alert = function() { return true; }")
|
||||||
end
|
end
|
||||||
|
|
@ -183,7 +174,7 @@ And /^I scroll down$/ do
|
||||||
wait_until(10) { evaluate_script('$("#infscr-loading:visible").length') == 0 }
|
wait_until(10) { evaluate_script('$("#infscr-loading:visible").length') == 0 }
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I wait for (\d+) seconds$/ do |seconds|
|
When /^I wait for (\d+) seconds?$/ do |seconds|
|
||||||
sleep seconds.to_i
|
sleep seconds.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2786,6 +2786,7 @@ ul#requested-scopes
|
||||||
|
|
||||||
ul.left_nav
|
ul.left_nav
|
||||||
:margin 0
|
:margin 0
|
||||||
|
:bottom 20px
|
||||||
:padding 0
|
:padding 0
|
||||||
|
|
||||||
li
|
li
|
||||||
|
|
@ -2793,11 +2794,16 @@ ul.left_nav
|
||||||
:width 100%
|
:width 100%
|
||||||
|
|
||||||
a.aspect_selector,
|
a.aspect_selector,
|
||||||
a.home_selector
|
a.home_selector,
|
||||||
|
a.tag_selector,
|
||||||
|
.root_element
|
||||||
:display block
|
:display block
|
||||||
:width 100%
|
:width 100%
|
||||||
:padding 3px 7px
|
:padding 3px 7px
|
||||||
|
|
||||||
|
a.aspect_selector,
|
||||||
|
a.home_selector,
|
||||||
|
a.tag_selector
|
||||||
&:hover
|
&:hover
|
||||||
@include border-radius(2px)
|
@include border-radius(2px)
|
||||||
|
|
||||||
|
|
@ -2841,8 +2847,10 @@ ul.left_nav
|
||||||
:margin 0
|
:margin 0
|
||||||
li
|
li
|
||||||
:width 155px
|
:width 155px
|
||||||
|
|
||||||
a.aspect_selector,
|
a.aspect_selector,
|
||||||
a.new_aspect
|
a.new_aspect,
|
||||||
|
a.tag_selector
|
||||||
:padding
|
:padding
|
||||||
:left 15px
|
:left 15px
|
||||||
:width 182px
|
:width 182px
|
||||||
|
|
@ -2862,7 +2870,8 @@ ul.left_nav
|
||||||
:width 140px
|
:width 140px
|
||||||
|
|
||||||
a.aspect_selector,
|
a.aspect_selector,
|
||||||
a.new_aspect
|
a.new_aspect,
|
||||||
|
a.tag_selector
|
||||||
:width 140px
|
:width 140px
|
||||||
|
|
||||||
li:hover
|
li:hover
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
@include border-radius(2px)
|
@include border-radius(2px)
|
||||||
@include linear-gradient(rgb(248,250,250),rgb(228,223,223))
|
@include linear-gradient(rgb(248,250,250),rgb(228,223,223))
|
||||||
@include box-shadow(0,1px,1px,#cfcfcf)
|
@include box-shadow(0,1px,1px,#cfcfcf)
|
||||||
|
@include transition(width, 3s)
|
||||||
|
|
||||||
:font
|
:font
|
||||||
:style normal
|
:style normal
|
||||||
|
|
@ -82,6 +83,11 @@
|
||||||
&:hover
|
&:hover
|
||||||
@include linear-gradient(lighten($creation-blue,3%), darken($creation-blue, 8%))
|
@include linear-gradient(lighten($creation-blue,3%), darken($creation-blue, 8%))
|
||||||
|
|
||||||
|
.button.red_on_hover
|
||||||
|
&:hover
|
||||||
|
@include linear-gradient(desaturate(lighten($red, 20%),20%), desaturate(lighten($red,14%),20%))
|
||||||
|
:color black
|
||||||
|
|
||||||
.right
|
.right
|
||||||
:position absolute
|
:position absolute
|
||||||
:right 0
|
:right 0
|
||||||
|
|
|
||||||
|
|
@ -331,4 +331,23 @@ describe AspectsController do
|
||||||
@alices_aspect_1.reload.contacts_visible.should be_false
|
@alices_aspect_1.reload.contacts_visible.should be_false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'helper methods' do
|
||||||
|
before do
|
||||||
|
@tag = ActsAsTaggableOn::Tag.create!(:name => "partytimeexcellent")
|
||||||
|
TagFollowing.create!(:tag => @tag, :user => alice )
|
||||||
|
alice.should_receive(:followed_tags).once.and_return([42])
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'tags' do
|
||||||
|
it 'queries current_users tag if there are tag_followings' do
|
||||||
|
@controller.tags.should == [42]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not query twice' do
|
||||||
|
@controller.tags.should == [42]
|
||||||
|
@controller.tags.should == [42]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
89
spec/controllers/tag_followings_controller_spec.rb
Normal file
89
spec/controllers/tag_followings_controller_spec.rb
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||||
|
# licensed under the Affero General Public License version 3 or later. See
|
||||||
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe TagFollowingsController do
|
||||||
|
|
||||||
|
def valid_attributes
|
||||||
|
{:name => "partytimeexcellent"}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
@tag = ActsAsTaggableOn::Tag.create!(:name => "partytimeexcellent")
|
||||||
|
sign_in :user, bob
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "POST create" do
|
||||||
|
describe "with valid params" do
|
||||||
|
it "creates a new TagFollowing" do
|
||||||
|
expect {
|
||||||
|
post :create, valid_attributes
|
||||||
|
}.to change(TagFollowing, :count).by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "assigns a newly created tag_following as @tag_following" do
|
||||||
|
post :create, valid_attributes
|
||||||
|
assigns(:tag_following).should be_a(TagFollowing)
|
||||||
|
assigns(:tag_following).should be_persisted
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates the tag if it does not already exist' do
|
||||||
|
expect {
|
||||||
|
post :create, :name => "tomcruisecontrol"
|
||||||
|
}.to change(ActsAsTaggableOn::Tag, :count).by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not create the tag following for non signed in user' do
|
||||||
|
expect {
|
||||||
|
post :create, valid_attributes.merge(:user_id => alice.id)
|
||||||
|
}.to_not change(alice.tag_followings, :count).by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "redirects and flashes success to the tag page" do
|
||||||
|
post :create, valid_attributes
|
||||||
|
|
||||||
|
response.should redirect_to(tag_path(:name => valid_attributes[:name]))
|
||||||
|
flash[:notice].should == "Successfully following: ##{valid_attributes[:name]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "redirects and flashes error if you already have a tag" do
|
||||||
|
TagFollowing.any_instance.stub(:save).and_return(false)
|
||||||
|
post :create, valid_attributes
|
||||||
|
|
||||||
|
response.should redirect_to(tag_path(:name => valid_attributes[:name]))
|
||||||
|
flash[:error].should == "Failed to follow: ##{valid_attributes[:name]}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "DELETE destroy" do
|
||||||
|
before do
|
||||||
|
TagFollowing.create!(:tag => @tag, :user => bob )
|
||||||
|
TagFollowing.create!(:tag => @tag, :user => alice )
|
||||||
|
end
|
||||||
|
|
||||||
|
it "destroys the requested tag_following" do
|
||||||
|
expect {
|
||||||
|
delete :destroy, valid_attributes
|
||||||
|
}.to change(TagFollowing, :count).by(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "redirects and flashes error if you already don't follow the tag" do
|
||||||
|
delete :destroy, valid_attributes
|
||||||
|
|
||||||
|
response.should redirect_to(tag_path(:name => valid_attributes[:name]))
|
||||||
|
flash[:notice].should == "Successfully stopped following: ##{valid_attributes[:name]}"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "redirects and flashes error if you already don't follow the tag" do
|
||||||
|
TagFollowing.any_instance.stub(:destroy).and_return(false)
|
||||||
|
delete :destroy, valid_attributes
|
||||||
|
|
||||||
|
response.should redirect_to(tag_path(:name => valid_attributes[:name]))
|
||||||
|
flash[:error].should == "Failed to stop following: ##{valid_attributes[:name]}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -62,6 +62,13 @@ describe TagsController do
|
||||||
assigns(:posts).models.should == [other_post]
|
assigns(:posts).models.should == [other_post]
|
||||||
response.status.should == 200
|
response.status.should == 200
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'displays a public post that was sent to no one' do
|
||||||
|
stranger = Factory(:user_with_aspect)
|
||||||
|
stranger_post = stranger.post(:status_message, :text => "#hello", :public => true, :to => 'all')
|
||||||
|
get :show, :name => 'hello'
|
||||||
|
assigns(:posts).models.should == [stranger_post]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "not signed in" do
|
context "not signed in" do
|
||||||
|
|
@ -106,4 +113,24 @@ describe TagsController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'helper methods' do
|
||||||
|
describe 'tag_followed?' do
|
||||||
|
before do
|
||||||
|
sign_in bob
|
||||||
|
@tag = ActsAsTaggableOn::Tag.create!(:name => "partytimeexcellent")
|
||||||
|
@controller.stub(:current_user).and_return(bob)
|
||||||
|
@controller.stub(:params).and_return({:name => "partytimeexcellent"})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true if the following already exists' do
|
||||||
|
TagFollowing.create!(:tag => @tag, :user => bob )
|
||||||
|
@controller.tag_followed?.should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false if the following does not already exist' do
|
||||||
|
@controller.tag_followed?.should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
16
spec/models/tag_following_spec.rb
Normal file
16
spec/models/tag_following_spec.rb
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe TagFollowing do
|
||||||
|
before do
|
||||||
|
@tag = ActsAsTaggableOn::Tag.create(:name => "partytimeexcellent")
|
||||||
|
TagFollowing.create!(:tag => @tag, :user => alice)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'validates uniqueness of tag_following scoped through user' do
|
||||||
|
TagFollowing.new(:tag => @tag, :user => alice).valid?.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows multiple tag followings for different users' do
|
||||||
|
TagFollowing.new(:tag => @tag, :user => bob).valid?.should be_true
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in a new issue