Merge branch 'follow_tags'
This commit is contained in:
commit
47e0558c3e
21 changed files with 373 additions and 37 deletions
|
|
@ -9,6 +9,9 @@ class AspectsController < ApplicationController
|
|||
|
||||
respond_to :html, :js
|
||||
respond_to :json, :only => [:show, :create]
|
||||
|
||||
helper_method :tags, :tag_followings
|
||||
helper_method :all_aspects_selected?
|
||||
|
||||
def index
|
||||
if params[:a_ids]
|
||||
|
|
@ -158,11 +161,23 @@ class AspectsController < ApplicationController
|
|||
params[:max_time] ||= Time.now + 1
|
||||
end
|
||||
|
||||
helper_method :all_aspects_selected?
|
||||
def all_aspects_selected?
|
||||
@aspect == :all
|
||||
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
|
||||
def save_sort_order
|
||||
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
|
||||
before_filter :ensure_page, :only => :show
|
||||
|
||||
helper_method :tag_followed?
|
||||
|
||||
respond_to :html, :only => [:show]
|
||||
respond_to :json, :only => [:index]
|
||||
|
||||
|
|
@ -41,8 +43,10 @@ class TagsController < ApplicationController
|
|||
def show
|
||||
@aspect = :tag
|
||||
if current_user
|
||||
@posts = StatusMessage.joins(:contacts).where(:pending => false).where(
|
||||
Contact.arel_table[:user_id].eq(current_user.id).or(
|
||||
@posts = StatusMessage.
|
||||
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[: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
|
||||
@posts = @posts.where(StatusMessage.arel_table[:created_at].lt(max_time))
|
||||
|
||||
@posts = @posts.includes(:comments, :photos).order('posts.created_at DESC').limit(15)
|
||||
|
||||
@posts = PostsFake.new(@posts)
|
||||
|
|
@ -69,4 +72,11 @@ class TagsController < ApplicationController
|
|||
@people_count = Person.where(:id => profiles.map{|p| p.person_id}).count
|
||||
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
|
||||
|
|
|
|||
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 :services, :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 :applications, :through => :authorizations, :source => :client
|
||||
|
|
|
|||
|
|
@ -15,6 +15,17 @@
|
|||
.section
|
||||
= 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
|
||||
#aspect_stream_container.stream_container
|
||||
= render 'aspect_stream',
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
-# licensed under the Affero General Public License version 3 or later. See
|
||||
-# the COPYRIGHT file.
|
||||
|
||||
|
||||
- content_for :page_title do
|
||||
- if params[:name]
|
||||
= "##{params[:name]}"
|
||||
|
|
@ -11,29 +12,48 @@
|
|||
- content_for :head do
|
||||
= include_javascripts :home
|
||||
:javascript
|
||||
$(".people_stream .pagination a").live("click", function() {
|
||||
$.getScript(this.href);
|
||||
return false;
|
||||
$(document).ready(function(){
|
||||
$(".button.tag_following").hover(function(){
|
||||
$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
|
||||
= "tags_show"
|
||||
|
||||
.span-24.last
|
||||
%h1.tag
|
||||
= "##{params[:name]}"
|
||||
|
||||
.span-13
|
||||
#main_stream.stream
|
||||
- if @posts.length > 0
|
||||
= render 'shared/stream', :posts => @posts
|
||||
#pagination
|
||||
=link_to(t('more'), next_page_path, :class => 'paginate')
|
||||
- else
|
||||
= t('.nobody_talking', :tag => "##{params[:name]}")
|
||||
|
||||
.prepend-2.span-9.last
|
||||
.span-6
|
||||
%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]}"
|
||||
|
||||
%hr
|
||||
|
||||
#main_stream.stream
|
||||
- if @posts.length > 0
|
||||
= render 'shared/stream', :posts => @posts
|
||||
#pagination
|
||||
=link_to(t('more'), next_page_path, :class => 'paginate')
|
||||
- else
|
||||
= t('.nobody_talking', :tag => "##{params[:name]}")
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ en:
|
|||
work: "Work"
|
||||
index:
|
||||
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."
|
||||
no_contacts: "No contacts"
|
||||
post_a_message: "post a message >>"
|
||||
|
|
@ -697,6 +698,17 @@ en:
|
|||
posts_tagged_with: "Posts tagged with #%{tag}"
|
||||
nobody_talking: "Nobody is talking about %{tag} yet."
|
||||
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:
|
||||
show:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
Diaspora::Application.routes.draw do
|
||||
|
||||
|
||||
# Posting and Reading
|
||||
|
||||
resources :aspects do
|
||||
|
|
@ -34,6 +35,9 @@ Diaspora::Application.routes.draw do
|
|||
end
|
||||
|
||||
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'
|
||||
|
||||
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"
|
||||
|
||||
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|
|
||||
t.integer "tag_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 "tags" with "#tags"
|
||||
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"
|
||||
And I should see "Would you like to find your Facebook friends on Diaspora?"
|
||||
And I follow "Skip"
|
||||
|
|
@ -31,5 +31,4 @@ Feature: new user registration
|
|||
|
||||
Scenario: new user skips the setup wizard
|
||||
When I follow "skip getting started"
|
||||
And I wait for "the aspects page" to load
|
||||
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
|
||||
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
|
||||
page.evaluate_script("window.alert = function() { return true; }")
|
||||
end
|
||||
|
|
@ -183,7 +174,7 @@ And /^I scroll down$/ do
|
|||
wait_until(10) { evaluate_script('$("#infscr-loading:visible").length') == 0 }
|
||||
end
|
||||
|
||||
When /^I wait for (\d+) seconds$/ do |seconds|
|
||||
When /^I wait for (\d+) seconds?$/ do |seconds|
|
||||
sleep seconds.to_i
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2786,6 +2786,7 @@ ul#requested-scopes
|
|||
|
||||
ul.left_nav
|
||||
:margin 0
|
||||
:bottom 20px
|
||||
:padding 0
|
||||
|
||||
li
|
||||
|
|
@ -2793,11 +2794,16 @@ ul.left_nav
|
|||
:width 100%
|
||||
|
||||
a.aspect_selector,
|
||||
a.home_selector
|
||||
a.home_selector,
|
||||
a.tag_selector,
|
||||
.root_element
|
||||
:display block
|
||||
:width 100%
|
||||
:padding 3px 7px
|
||||
|
||||
a.aspect_selector,
|
||||
a.home_selector,
|
||||
a.tag_selector
|
||||
&:hover
|
||||
@include border-radius(2px)
|
||||
|
||||
|
|
@ -2841,8 +2847,10 @@ ul.left_nav
|
|||
:margin 0
|
||||
li
|
||||
:width 155px
|
||||
|
||||
a.aspect_selector,
|
||||
a.new_aspect
|
||||
a.new_aspect,
|
||||
a.tag_selector
|
||||
:padding
|
||||
:left 15px
|
||||
:width 182px
|
||||
|
|
@ -2862,7 +2870,8 @@ ul.left_nav
|
|||
:width 140px
|
||||
|
||||
a.aspect_selector,
|
||||
a.new_aspect
|
||||
a.new_aspect,
|
||||
a.tag_selector
|
||||
:width 140px
|
||||
|
||||
li:hover
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
@include border-radius(2px)
|
||||
@include linear-gradient(rgb(248,250,250),rgb(228,223,223))
|
||||
@include box-shadow(0,1px,1px,#cfcfcf)
|
||||
@include transition(width, 3s)
|
||||
|
||||
:font
|
||||
:style normal
|
||||
|
|
@ -82,6 +83,11 @@
|
|||
&:hover
|
||||
@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
|
||||
:position absolute
|
||||
:right 0
|
||||
|
|
|
|||
|
|
@ -331,4 +331,23 @@ describe AspectsController do
|
|||
@alices_aspect_1.reload.contacts_visible.should be_false
|
||||
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
|
||||
|
|
|
|||
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]
|
||||
response.status.should == 200
|
||||
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
|
||||
|
||||
context "not signed in" do
|
||||
|
|
@ -106,4 +113,24 @@ describe TagsController do
|
|||
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
|
||||
|
|
|
|||
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