From 20f5105e5dea748973e9dbe4be334d87e9489ff1 Mon Sep 17 00:00:00 2001 From: danielgrippi Date: Mon, 14 Mar 2011 18:43:40 -0700 Subject: [PATCH] breaking out Diaspora::Taggable wip --- app/models/profile.rb | 6 ++ app/models/status_message.rb | 28 +-------- app/views/profiles/_edit.html.haml | 4 ++ config/locales/diaspora/en.yml | 2 + lib/diaspora/taggable.rb | 50 ++++++++++++++++ spec/controllers/profiles_controller_spec.rb | 10 +++- spec/models/profile_spec.rb | 7 +++ spec/models/status_message_spec.rb | 55 ++---------------- spec/shared_behaviors/taggable.rb | 60 ++++++++++++++++++++ spec/spec_helper.rb | 4 ++ 10 files changed, 149 insertions(+), 77 deletions(-) create mode 100644 lib/diaspora/taggable.rb create mode 100644 spec/shared_behaviors/taggable.rb diff --git a/app/models/profile.rb b/app/models/profile.rb index e1b029e7c..c3d196843 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -5,8 +5,14 @@ class Profile < ActiveRecord::Base require File.join(Rails.root, 'lib/diaspora/webhooks') include Diaspora::Webhooks + include Diaspora::Taggable include ROXML + attr_accessor :tag_string + + acts_as_taggable_on :tags + extract_tags_from :tag_string + xml_attr :diaspora_handle xml_attr :first_name xml_attr :last_name diff --git a/app/models/status_message.rb b/app/models/status_message.rb index f44a345f4..445819847 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -4,11 +4,14 @@ class StatusMessage < Post include Diaspora::Socketable + include Diaspora::Taggable + include YoutubeTitles require File.join(Rails.root, 'lib/youtube_titles') include ActionView::Helpers::TextHelper acts_as_taggable_on :tags + extract_tags_from :raw_message validates_length_of :text, :maximum => 1000, :text => "please make your status messages less than 1000 characters" xml_name :status_message @@ -45,15 +48,6 @@ class StatusMessage < Post self.format_tags(mentioned_message, opts) end - def format_tags(text, opts={}) - return text if opts[:plain_text] - regex = /(^|\s)#(\w+)/ - form_message = text.gsub(regex) do |matched_string| - "#{$~[1]}##{ERB::Util.h($~[2])}" - end - form_message - end - def format_mentions(text, opts = {}) people = self.mentioned_people regex = /@\{([^;]+); ([^\}]+)\}/ @@ -102,22 +96,6 @@ class StatusMessage < Post identifiers.empty? ? [] : Person.where(:diaspora_handle => identifiers) end - def build_tags - self.tag_list = tag_strings - end - - def tag_strings - regex = /(?:^|\s)#(\w+)/ - matches = self.raw_message.scan(regex).map do |match| - match.last - end - unique_matches = matches.inject(Hash.new) do |h,element| - h[element.downcase] = element unless h[element.downcase] - h - end - unique_matches.values - end - def to_activity <<-XML diff --git a/app/views/profiles/_edit.html.haml b/app/views/profiles/_edit.html.haml index 33ebf82f5..c7d9f1f39 100644 --- a/app/views/profiles/_edit.html.haml +++ b/app/views/profiles/_edit.html.haml @@ -29,6 +29,10 @@ = select_date profile.birthday, :prompt => true, :default => true, :order => t('date.order'), :start_year => 2000, :end_year => 1930, :prefix => 'profile[date]' + %h4 + = t('profiles.edit.your_tags') + = text_field_tag 'profile[tags]', profile.tags, :placeholder => t('.your_tags_placeholder') + %h4 = t('profiles.edit.your_bio') = text_area_tag 'profile[bio]', profile.bio, :rows => 5, :placeholder => t('fill_me_out') diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index cda1016c5..2cd0cbd22 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -409,6 +409,8 @@ en: last_name: "Last name" your_gender: "Your gender" your_birthday: "Your birthday" + your_tags: "You: in 5 tags" + your_tags_placeholder: "i.e. #ironing #knitting #kittens #knees #doors" your_bio: "Your bio" your_photo: "Your photo" update_profile: "Update Profile" diff --git a/lib/diaspora/taggable.rb b/lib/diaspora/taggable.rb new file mode 100644 index 000000000..cf5c955d2 --- /dev/null +++ b/lib/diaspora/taggable.rb @@ -0,0 +1,50 @@ +# Copyright (c) 2010, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +module Diaspora + module Taggable + def self.included(model) + model.class_eval do + + cattr_reader :field_with_tags + + def self.extract_tags_from sym + puts "extract_tags_from" + pp self + @field_with_tags = sym + end + def self.field_with_tags_setter + @field_with_tags_setter = "#{@field_with_tags}=".to_sym + end + end + end + + def build_tags + self.tag_list = tag_strings + end + + def tag_strings + regex = /(?:^|\s)#(\w+)/ + puts "tag strings" + pp self + matches = self.send(self.class.field_with_tags).scan(regex).map do |match| + match.last + end + unique_matches = matches.inject(Hash.new) do |h,element| + h[element.downcase] = element unless h[element.downcase] + h + end + unique_matches.values + end + + def format_tags(text, opts={}) + return text if opts[:plain_text] + regex = /(^|\s)#(\w+)/ + form_message = text.gsub(regex) do |matched_string| + "#{$~[1]}##{ERB::Util.h($~[2])}" + end + form_message + end + end +end diff --git a/spec/controllers/profiles_controller_spec.rb b/spec/controllers/profiles_controller_spec.rb index 28461e091..2fae00b1e 100644 --- a/spec/controllers/profiles_controller_spec.rb +++ b/spec/controllers/profiles_controller_spec.rb @@ -34,7 +34,6 @@ describe ProfilesController do end end - describe '#update' do it "sets the flash" do put :update, :profile => { @@ -45,6 +44,15 @@ describe ProfilesController do flash[:notice].should_not be_empty end + it 'sets tags' do + params = { :id => @user.person.id, + :profile => + { :tags => '#apples #oranges'}} + + put :update, params + @user.person(true).profile.tags.should =~ ['apples', 'oranges'] + end + context 'with a profile photo set' do before do @params = { :id => @user.person.id, diff --git a/spec/models/profile_spec.rb b/spec/models/profile_spec.rb index c7ebb1eab..372a98694 100644 --- a/spec/models/profile_spec.rb +++ b/spec/models/profile_spec.rb @@ -146,6 +146,13 @@ describe Profile do end end + describe 'tags' do + before do + @object = Factory.build(:profile) + end + it_should_behave_like 'it is taggable' + end + describe '#receive' do it 'updates the profile in place' do diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index e98a7c693..06a110824 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -4,7 +4,6 @@ require 'spec_helper' - describe StatusMessage do include ActionView::Helpers::UrlHelper include Rails.application.routes.url_helpers @@ -174,60 +173,14 @@ STR end end end + describe 'tags' do before do - @sm = Factory.build(:status_message) - end - describe '#format_tags' do - before do - @str = '#what #hey' - @sm.text = @str - @sm.build_tags - @sm.save - @sm.reload - end - it 'links the tag to /p' do - link = link_to('#what', posts_path(:tag => 'what'), :class => 'tag') - @sm.format_tags(@str).should include(link) - end - it 'responds to plain_text' do - @sm.format_tags(@str, :plain_text => true).should == @str - end - end - describe '#build_tags' do - it 'builds the tags' do - @sm.text = '#what' - @sm.build_tags - @sm.tag_list.should == ['what'] - lambda { - @sm.save - }.should change{@sm.tags.count}.by(1) - end - end - describe '#tag_strings' do - it 'returns a string for every #thing' do - str = '#what #hey #that"smybike. #@hey ##boo # #THATWASMYBIKE #hey#there #135440we #abc/23 ###' - arr = ['what', 'hey', 'that', 'THATWASMYBIKE', '135440we', 'abc'] - - @sm.text = str - @sm.tag_strings.should =~ arr - end - it 'returns no duplicates' do - str = '#what #what #what #whaaaaaaaaaat' - arr = ['what','whaaaaaaaaaat'] - - @sm.text = str - @sm.tag_strings.should =~ arr - end - it 'is case insensitive' do - str = '#what #wHaT #WHAT' - arr = ['what'] - - @sm.text = str - @sm.tag_strings.should =~ arr - end + @object = Factory.build(:status_message) end + it_should_behave_like 'it is taggable' end + describe "XML" do before do @message = Factory.create(:status_message, :text => "I hate WALRUSES!", :author => @user.person) diff --git a/spec/shared_behaviors/taggable.rb b/spec/shared_behaviors/taggable.rb new file mode 100644 index 000000000..9c7248fd5 --- /dev/null +++ b/spec/shared_behaviors/taggable.rb @@ -0,0 +1,60 @@ +# 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 Diaspora::Taggable do + shared_examples_for "it is taggable" do + describe '#format_tags' do + before do + @str = '#what #hey' + @object.send(@object.class.field_with_tags_setter, @str) + @object.build_tags + @object.save + @object.reload + end + it 'links the tag to /p' do + link = link_to('#what', posts_path(:tag => 'what'), :class => 'tag') + @object.format_tags(@str).should include(link) + end + it 'responds to plain_text' do + @object.format_tags(@str, :plain_text => true).should == @str + end + end + describe '#build_tags' do + it 'builds the tags' do + @object.send(@object.class.field_with_tags_setter, '#what') + @object.build_tags + @object.tag_list.should == ['what'] + lambda { + @object.save + }.should change{@object.tags.count}.by(1) + end + end + describe '#tag_strings' do + it 'returns a string for every #thing' do + str = '#what #hey #that"smybike. #@hey ##boo # #THATWASMYBIKE #hey#there #135440we #abc/23 ###' + arr = ['what', 'hey', 'that', 'THATWASMYBIKE', '135440we', 'abc'] + + @object.send(@object.class.field_with_tags_setter, str) + @object.tag_strings.should =~ arr + end + it 'returns no duplicates' do + str = '#what #what #what #whaaaaaaaaaat' + arr = ['what','whaaaaaaaaaat'] + + @object.send(@object.class.field_with_tags_setter, str) + @object.tag_strings.should =~ arr + end + it 'is case insensitive' do + str = '#what #wHaT #WHAT' + arr = ['what'] + + @object.send(@object.class.field_with_tags_setter, str) + @object.tag_strings.should =~ arr + end + end + end +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 66275fd2b..3a19f50f2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,6 +24,10 @@ support_files = Dir["#{File.dirname(__FILE__)}/support/**/*.rb"] - [fixture_buil support_files.each {|f| require f } require fixture_builder_file +Dir["#{File.dirname(__FILE__)}/shared_behaviors/**/*.rb"].each do |f| + require f +end + RSpec.configure do |config| config.include Devise::TestHelpers, :type => :controller config.mock_with :rspec