From c1bcfef90c3a93a6a7f557794d0c73fff079c3b2 Mon Sep 17 00:00:00 2001 From: Raphael Sofaer <raphael@joindiaspora.com> Date: Thu, 10 Mar 2011 16:54:44 -0800 Subject: [PATCH] TAGS ARE SO COOL --- Gemfile | 6 +-- Gemfile.lock | 4 +- app/models/status_message.rb | 21 +++++++++ ...311000150_acts_as_taggable_on_migration.rb | 28 +++++++++++ db/schema.rb | 19 +++++++- spec/models/status_message_spec.rb | 46 +++++++++++++++++++ 6 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20110311000150_acts_as_taggable_on_migration.rb diff --git a/Gemfile b/Gemfile index 61f2ac22d1..38ea5ec327 100644 --- a/Gemfile +++ b/Gemfile @@ -24,12 +24,12 @@ gem 'twitter', :git => 'git://github.com/jnunemaker/twitter.git', :ref => 'ef122 gem 'haml', '3.0.25' gem 'will_paginate', '3.0.pre2' -#Statistics -gem 'googlecharts' - #Inflected translations gem 'i18n-inflector-rails', '~> 1.0' +#Tags +gem 'acts-as-taggable-on', '2.0.6' + #Uncatagorized gem 'roxml', :git => 'git://github.com/Empact/roxml.git', :ref => '7ea9a9ffd2338aaef5b0' gem 'addressable', '2.2.2', :require => 'addressable/uri' diff --git a/Gemfile.lock b/Gemfile.lock index 2f85205a28..cd611be097 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -86,6 +86,7 @@ GEM activemodel (= 3.0.3) activesupport (= 3.0.3) activesupport (3.0.3) + acts-as-taggable-on (2.0.6) addressable (2.2.2) arel (2.0.9) aws (2.3.32) @@ -189,7 +190,6 @@ GEM gem_plugin (0.2.3) gherkin (2.3.3) json (~> 1.4.6) - googlecharts (1.6.1) haml (3.0.25) hashie (0.4.0) highline (1.6.1) @@ -387,6 +387,7 @@ PLATFORMS DEPENDENCIES SystemTimer (= 1.2.1) + acts-as-taggable-on (= 2.0.6) addressable (= 2.2.2) aws (= 2.3.32) bundler (>= 1.0.0) @@ -408,7 +409,6 @@ DEPENDENCIES fog (= 0.3.25) foreigner (= 0.9.1) fuubar - googlecharts haml (= 3.0.25) http_accept_language! i18n-inflector-rails (~> 1.0) diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 224d14cd43..7aa0e5add6 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -8,6 +8,9 @@ class StatusMessage < Post require File.join(Rails.root, 'lib/youtube_titles') include ActionView::Helpers::TextHelper + acts_as_taggable + acts_as_taggable_on :tags + validates_length_of :message, :maximum => 1000, :message => "please make your status messages less than 1000 characters" xml_name :status_message xml_attr :raw_message @@ -22,6 +25,8 @@ class StatusMessage < Post get_youtube_title message end + before_create :build_tags + def message(opts = {}) self.formatted_message(opts) end @@ -84,6 +89,22 @@ 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 <entry> diff --git a/db/migrate/20110311000150_acts_as_taggable_on_migration.rb b/db/migrate/20110311000150_acts_as_taggable_on_migration.rb new file mode 100644 index 0000000000..7c07fef22e --- /dev/null +++ b/db/migrate/20110311000150_acts_as_taggable_on_migration.rb @@ -0,0 +1,28 @@ +class ActsAsTaggableOnMigration < ActiveRecord::Migration + def self.up + create_table :tags do |t| + t.string :name + end + + create_table :taggings do |t| + t.references :tag + + # You should make sure that the column created is + # long enough to store the required class names. + t.references :taggable, :polymorphic => {:limit => 127} + t.references :tagger, :polymorphic => {:limit => 127} + + t.string :context, :limit => 127 + + t.datetime :created_at + end + + add_index :taggings, :tag_id + add_index :taggings, [:taggable_id, :taggable_type, :context] + end + + def self.down + drop_table :taggings + drop_table :tags + end +end diff --git a/db/schema.rb b/db/schema.rb index 051abe6f70..5f818163d3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110301202619) do +ActiveRecord::Schema.define(:version => 20110311000150) do create_table "aspect_memberships", :force => true do |t| t.integer "aspect_id", :null => false @@ -459,6 +459,23 @@ ActiveRecord::Schema.define(:version => 20110301202619) do add_index "services", ["mongo_id"], :name => "index_services_on_mongo_id" add_index "services", ["user_id"], :name => "index_services_on_user_id" + create_table "taggings", :force => true do |t| + t.integer "tag_id" + t.integer "taggable_id" + t.string "taggable_type", :limit => 127 + t.integer "tagger_id" + t.string "tagger_type", :limit => 127 + t.string "context", :limit => 127 + t.datetime "created_at" + end + + add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" + add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" + + create_table "tags", :force => true do |t| + t.string "name" + end + create_table "users", :force => true do |t| t.string "username" t.text "serialized_private_key" diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index afd7eddb77..e71e3df0ba 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -18,6 +18,11 @@ describe StatusMessage do status.should_receive(:create_mentions) status.save end + it 'calls build_tags' do + status = Factory.build(:status_message) + status.should_receive(:build_tags) + status.save + end end describe '#diaspora_handle=' do @@ -103,6 +108,9 @@ STR it 'escapes the link title' do p = @people[0].profile p.first_name="</a><script>alert('h')</script>" +["a", "b", "A", "C"]\ +.inject(Hash.new){ |h,element| h[element.downcase] = element unless h[element.downcase] ; h }\ +.values p.save! @sm.formatted_message.should_not include(@people[0].profile.first_name) @@ -165,6 +173,44 @@ STR end end end + describe 'tags' do + before do + @sm = Factory.build(:status_message) + end + describe '#build_tags' do + it 'builds the tags' do + @sm.message = '#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.message = str + @sm.tag_strings.should =~ arr + end + it 'returns no duplicates' do + str = '#what #what #what #whaaaaaaaaaat' + arr = ['what','whaaaaaaaaaat'] + + @sm.message = str + @sm.tag_strings.should =~ arr + end + it 'is case insensitive' do + str = '#what #wHaT #WHAT' + arr = ['what'] + + @sm.message = str + @sm.tag_strings.should =~ arr + end + end + end describe "XML" do before do @message = Factory.create(:status_message, :message => "I hate WALRUSES!", :author => @user.person) -- GitLab