diff --git a/app/models/message_gateway.rb b/app/models/message_gateway.rb index 74049730..0b70ca36 100644 --- a/app/models/message_gateway.rb +++ b/app/models/message_gateway.rb @@ -23,7 +23,8 @@ class MessageGateway < ActionMailer::Base end end - todo = Todo.from_rich_message(user, context.id, description, notes) + todo_builder = TodoFromRichMessage.new(user, context.id, description, notes) + todo = todo_builder.construct todo.save! Rails.logger.info "Saved email as todo for user #{user.login} in context #{context.name}" end diff --git a/app/models/todo.rb b/app/models/todo.rb index 8eb054c8..0b49c425 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -381,48 +381,6 @@ class Todo < ActiveRecord::Base end end - # Rich Todo API - def self.from_rich_message(user, default_context_id, description, notes) - fields = description.match(/([^>@]*)@?([^>]*)>?(.*)/) - description = fields[1].strip - context = fields[2].strip - project = fields[3].strip - - context = nil if context == "" - project = nil if project == "" - - context_id = default_context_id - unless(context.nil?) - found_context = user.contexts.active.where("name like ?", "%#{context}%").first - found_context = user.contexts.where("name like ?", "%#{context}%").first if !found_context - context_id = found_context.id if found_context - end - - unless user.contexts.exists? context_id - raise(CannotAccessContext, "Cannot access a context that does not belong to this user.") - end - - project_id = nil - unless(project.blank?) - if(project[0..3].downcase == "new:") - found_project = user.projects.build - found_project.name = project[4..255+4].strip - found_project.save! - else - found_project = user.projects.active.find_by_namepart(project) - found_project = user.projects.find_by_namepart(project) if found_project.nil? - end - project_id = found_project.id unless found_project.nil? - end - - todo = user.todos.build - todo.description = description - todo.raw_notes = notes - todo.context_id = context_id - todo.project_id = project_id unless project_id.nil? - return todo - end - def render_note unless self.notes.nil? self.rendered_notes = Tracks::Utils.render_text(self.notes) diff --git a/app/services/rich_message_extractor.rb b/app/services/rich_message_extractor.rb new file mode 100644 index 00000000..a357b66d --- /dev/null +++ b/app/services/rich_message_extractor.rb @@ -0,0 +1,28 @@ +class RichMessageExtractor + + RICH_MESSAGE_FIELDS_REGEX = /([^>@]*)@?([^>]*)>?(.*)/ + + def initialize(message) + @message = message + end + + def description + fields[1].strip + end + + def context + fields[2].strip + end + + def project + stripped = fields[3].strip + stripped.blank? ? nil : stripped + end + + private + + def fields + @message.match(RICH_MESSAGE_FIELDS_REGEX) + end + +end diff --git a/app/services/todo_from_rich_message.rb b/app/services/todo_from_rich_message.rb new file mode 100644 index 00000000..6efc1c8d --- /dev/null +++ b/app/services/todo_from_rich_message.rb @@ -0,0 +1,49 @@ +class TodoFromRichMessage + + attr_reader :user, :default_context_id, :description, :notes + + def initialize(user, default_context_id, description, notes) + @user = user + @default_context_id = default_context_id + @description = description + @notes = notes + end + + def construct + extractor = RichMessageExtractor.new(description) + description = extractor.description + context = extractor.context + project = extractor.project + + context_id = default_context_id + unless context.blank? + found_context = user.contexts.active.where("name like ?", "%#{context}%").first + found_context = user.contexts.where("name like ?", "%#{context}%").first if !found_context + context_id = found_context.id if found_context + end + + unless user.context_ids.include? context_id + raise(CannotAccessContext, "Cannot access a context that does not belong to this user.") + end + + project_id = nil + unless project.blank? + if project[0..3].downcase == "new:" + found_project = user.projects.build + found_project.name = project[4..259].strip + found_project.save! + else + found_project = user.projects.active.find_by_namepart(project) + found_project = user.projects.find_by_namepart(project) if found_project.nil? + end + project_id = found_project.id unless found_project.nil? + end + + todo = user.todos.build + todo.description = description + todo.raw_notes = notes + todo.context_id = context_id + todo.project_id = project_id unless project_id.nil? + todo + end +end diff --git a/test/models/rich_message_extractor_test.rb b/test/models/rich_message_extractor_test.rb new file mode 100644 index 00000000..5c264685 --- /dev/null +++ b/test/models/rich_message_extractor_test.rb @@ -0,0 +1,55 @@ +require 'test/unit' +require 'active_support/core_ext/object/blank' +require_relative '../../app/services/rich_message_extractor.rb' + +class RichMessageExtractorTest < Test::Unit::TestCase + + def test_message_with_all_options + message = "ohai@some-context>in-this-project" + extractor = RichMessageExtractor.new(message) + assert_equal "ohai", extractor.description + assert_equal "some-context", extractor.context + assert_equal "in-this-project", extractor.project + end + + def test_message_without_project + message = "ohai @ some-context" + extractor = RichMessageExtractor.new(message) + assert_equal "ohai", extractor.description + assert_equal "some-context", extractor.context + assert_equal nil, extractor.project + end + + def test_message_without_project + message = " ohai @ some-context" + extractor = RichMessageExtractor.new(message) + assert_equal "ohai", extractor.description + assert_equal "some-context", extractor.context + assert_equal nil, extractor.project + end + + def test_message_without_project_or_context + message = "ohai" + extractor = RichMessageExtractor.new(message) + assert_equal "ohai", extractor.description + assert_equal "", extractor.context + assert_equal nil, extractor.project + end + + def test_message_without_anything + message = "" + extractor = RichMessageExtractor.new(message) + assert_equal "", extractor.description + assert_equal "", extractor.context + assert_equal nil, extractor.project + end + + def test_message_with_just_a_context + message = "@some-context" + extractor = RichMessageExtractor.new(message) + assert_equal "", extractor.description + assert_equal "some-context", extractor.context + assert_equal nil, extractor.project + end + +end diff --git a/test/models/todo_from_rich_message_test.rb b/test/models/todo_from_rich_message_test.rb new file mode 100644 index 00000000..f9206624 --- /dev/null +++ b/test/models/todo_from_rich_message_test.rb @@ -0,0 +1,21 @@ +require File.expand_path(File.dirname(__FILE__) + '/../test_helper') + +class TodoFromRichMessageTest < ActiveSupport::TestCase + + def setup + @completed = Todo.find(8) + end + + def test_from_rich_message_adds_to_default_context + user = @completed.user + default_context_id = @completed.context_id + builder = TodoFromRichMessage.new(user, default_context_id, "new todo", "notes") + new_todo = builder.construct + + assert_not_nil new_todo + assert_equal "new todo", new_todo.description + assert_equal "notes", new_todo.notes + assert_equal default_context_id, new_todo.context_id + end + +end diff --git a/test/models/todo_test.rb b/test/models/todo_test.rb index a6196042..4d25525b 100644 --- a/test/models/todo_test.rb +++ b/test/models/todo_test.rb @@ -477,15 +477,4 @@ class TodoTest < ActiveSupport::TestCase assert_equal "
test
", todo.rendered_notes end - def test_from_rich_message_adds_to_default_context - user = @completed.user - default_context_id = @completed.context_id - new_todo = Todo::from_rich_message(user, default_context_id, "new todo", "notes") - - assert_not_nil new_todo - assert_equal "new todo", new_todo.description - assert_equal "notes", new_todo.notes - assert_equal default_context_id, new_todo.context_id - end - end