mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-27 04:18:49 +01:00
Merge pull request #1905 from lrbalt/add-attachments
Add attachments to Todo model using Paperclip
This commit is contained in:
commit
00143ece20
19 changed files with 229 additions and 52 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -15,6 +15,7 @@
|
|||
/db/*.db
|
||||
/db/*.sqlite3
|
||||
/db/*.sqlite3-journal
|
||||
/db/assets/*
|
||||
/log/*.log
|
||||
/public/assets/
|
||||
/tmp
|
||||
|
|
|
|||
1
Gemfile
1
Gemfile
|
|
@ -32,6 +32,7 @@ gem "htmlentities"
|
|||
gem "swf_fu"
|
||||
gem "rails_autolink"
|
||||
gem 'thin'
|
||||
gem 'paperclip'
|
||||
|
||||
# To use ActiveModel has_secure_password
|
||||
gem 'bcrypt', '~> 3.1.7'
|
||||
|
|
|
|||
12
Gemfile.lock
12
Gemfile.lock
|
|
@ -52,6 +52,10 @@ GEM
|
|||
xpath (~> 2.0)
|
||||
childprocess (0.5.5)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
climate_control (0.0.3)
|
||||
activesupport (>= 3.0)
|
||||
cocaine (0.5.7)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
codeclimate-test-reporter (0.4.1)
|
||||
simplecov (>= 0.7.1, < 1.0.0)
|
||||
coffee-rails (4.1.0)
|
||||
|
|
@ -101,6 +105,7 @@ GEM
|
|||
mime-types (>= 1.16, < 3)
|
||||
metaclass (0.0.4)
|
||||
mime-types (2.6.1)
|
||||
mimemagic (0.3.0)
|
||||
mini_portile (0.6.1)
|
||||
minitest (5.7.0)
|
||||
mocha (1.1.0)
|
||||
|
|
@ -112,6 +117,12 @@ GEM
|
|||
mini_portile (~> 0.6.0)
|
||||
nokogumbo (1.1.12)
|
||||
nokogiri
|
||||
paperclip (4.3.0)
|
||||
activemodel (>= 3.2.0)
|
||||
activesupport (>= 3.2.0)
|
||||
cocaine (~> 0.5.5)
|
||||
mime-types
|
||||
mimemagic (= 0.3.0)
|
||||
rack (1.5.5)
|
||||
rack-dev-mark (0.7.3)
|
||||
rack (>= 1.1)
|
||||
|
|
@ -228,6 +239,7 @@ DEPENDENCIES
|
|||
jquery-rails
|
||||
mocha
|
||||
mysql2
|
||||
paperclip
|
||||
rack-dev-mark
|
||||
rack-mini-profiler
|
||||
rails (~> 4.1.11)
|
||||
|
|
|
|||
|
|
@ -124,6 +124,11 @@ img.delete_item {
|
|||
}
|
||||
}
|
||||
|
||||
a.todo_attachment {
|
||||
background: image-url('bottom_off.png') no-repeat top;
|
||||
border: none;
|
||||
}
|
||||
|
||||
a.undecorated_link {background-color:transparent;color:transparent;}
|
||||
img.todo_star {background-image: image-url('staricons.png'); background-repeat: no-repeat; border:none; background-position: -32px 0px;}
|
||||
img.todo_star.starred{ background-position: 0px 0px; }
|
||||
|
|
|
|||
|
|
@ -815,6 +815,20 @@ class TodosController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def attachment
|
||||
id = params[:id]
|
||||
filename = params[:filename]
|
||||
attachment = current_user.attachments.find(id)
|
||||
|
||||
if attachment
|
||||
send_file(attachment.file.path,
|
||||
disposition: 'attachment',
|
||||
type: 'message/rfc822')
|
||||
else
|
||||
head :not_found
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_group_view_by
|
||||
|
|
|
|||
|
|
@ -204,6 +204,14 @@ module TodosHelper
|
|||
link_to(t('todos.convert_to_project'), url, {:class => "icon_item_to_project", :id => dom_id(todo, "to_project")})
|
||||
end
|
||||
|
||||
def attachment_image(todo)
|
||||
link_to(
|
||||
image_tag('blank.png', width: 16, height: 16, border:0),
|
||||
todo.attachments.first.file.url,
|
||||
{:class => 'todo_attachment', title: 'Get attachments of this todo'}
|
||||
)
|
||||
end
|
||||
|
||||
def collapsed_notes_image(todo)
|
||||
link = link_to(
|
||||
image_tag( 'blank.png', :width=>'16', :height=>'16', :border=>'0' ),
|
||||
|
|
|
|||
20
app/models/attachment.rb
Normal file
20
app/models/attachment.rb
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
class Attachment < ActiveRecord::Base
|
||||
belongs_to :todo, touch: true
|
||||
|
||||
has_attached_file :file,
|
||||
url: '/:class/:id/:basename.:extension',
|
||||
path: ":rails_root/db/assets/#{Rails.env}/:class/:id/:basename.:extension",
|
||||
override_file_permissions: 0660
|
||||
|
||||
do_not_validate_attachment_file_type :file
|
||||
# validates_attachment_content_type :file, :content_type => ["text/plain"]
|
||||
|
||||
before_destroy :delete_attached_file
|
||||
|
||||
private
|
||||
|
||||
def delete_attached_file
|
||||
file = nil
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
|
@ -10,13 +10,41 @@ class MessageGateway < ActionMailer::Base
|
|||
|
||||
todo_builder = TodoFromRichMessage.new(user, context.id, todo_params[:description], todo_params[:notes])
|
||||
todo = todo_builder.construct
|
||||
todo.save!
|
||||
Rails.logger.info "Saved email as todo for user #{user.login} in context #{context.name}"
|
||||
|
||||
if todo.save!
|
||||
Rails.logger.info "Saved email as todo for user #{user.login} in context #{context.name}"
|
||||
|
||||
if attach_email_to_todo(todo, email)
|
||||
Rails.logger.info "Saved email as attachment to todo for user #{user.login} in context #{context.name}"
|
||||
end
|
||||
end
|
||||
todo
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def attach_email_to_todo(todo, email)
|
||||
attachment = todo.attachments.build
|
||||
|
||||
# create temp file
|
||||
tmp = Tempfile.new(['attachment', '.eml'], {universal_newline: true})
|
||||
tmp.write email.raw_source.gsub(/\r/, "")
|
||||
|
||||
# add temp file to attachment. paperclip will copy the file to the right location
|
||||
Rails.logger.info "Saved received email to #{tmp.path}"
|
||||
attachment.file = tmp
|
||||
tmp.close
|
||||
saved = attachment.save!
|
||||
|
||||
# enable write permissions on group, since MessageGateway could be run under different
|
||||
# user than Tracks (i.e. apache versus mail)
|
||||
dir = File.open(File.dirname(attachment.file.path))
|
||||
dir.chmod(0770)
|
||||
|
||||
# delete temp file
|
||||
tmp.unlink
|
||||
end
|
||||
|
||||
def get_todo_params(email)
|
||||
params = {}
|
||||
|
||||
|
|
@ -111,5 +139,4 @@ class MessageGateway < ActionMailer::Base
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class Todo < ActiveRecord::Base
|
|||
:source => :predecessor
|
||||
has_many :pending_successors, -> {where('todos.state = ?', 'pending')}, :through => :predecessor_dependencies,
|
||||
:source => :successor
|
||||
has_many :attachments, dependent: :destroy
|
||||
|
||||
# scopes for states of this todo
|
||||
scope :active, -> { where state: 'active' }
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ class User < ActiveRecord::Base
|
|||
|
||||
has_many :notes, -> { order "created_at DESC" }, dependent: :delete_all
|
||||
has_one :preference, dependent: :destroy
|
||||
has_many :attachments, through: :todos
|
||||
|
||||
validates_presence_of :login
|
||||
validates_presence_of :password, if: :password_required?
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ cache [todo, current_user.date.strftime("%Y%m%d"), @source_view, current_user.pr
|
|||
<%= project_and_context_links( todo, parent_container_type, :suppress_context => suppress_context, :suppress_project => suppress_project ) %>
|
||||
<%= collapsed_notes_image(todo) if todo.notes.present? %>
|
||||
<%= collapsed_successors_image(todo) if todo.has_pending_successors %>
|
||||
<%= attachment_image(todo) if todo.attachments.present? %>
|
||||
</div>
|
||||
</div>
|
||||
<div id="<%= dom_id(todo, 'edit') %>" class="edit-form" style="display:none">
|
||||
|
|
|
|||
10
config/initializers/paperclip.rb
Normal file
10
config/initializers/paperclip.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#config/initilizers/paperclip.rb
|
||||
require 'paperclip/media_type_spoof_detector'
|
||||
|
||||
module Paperclip
|
||||
class MediaTypeSpoofDetector
|
||||
def spoofed?
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -101,11 +101,12 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
# match /todos/tag and put everything in :name, including extensions like .m and .txt.
|
||||
# match /todos/tag and put everything in :name, including extensions like .m and .txt.
|
||||
# This means the controller action needs to parse the extension and set format/content type
|
||||
# Needed for /todos/tag/first.last.m to work
|
||||
get 'todos/tag/:name' => 'todos#tag', :as => :tag, :format => false, :name => /.*/
|
||||
|
||||
get 'attachments/:id/:filename' => "todos#attachment"
|
||||
get 'tags.autocomplete' => "todos#tags", :format => 'autocomplete'
|
||||
get 'todos/done/tag/:name' => "todos#done_tag", :as => :done_tag
|
||||
get 'todos/all_done/tag/:name' => "todos#all_done_tag", :as => :all_done_tag
|
||||
|
|
|
|||
9
db/migrate/20150805144100_create_attachments.rb
Normal file
9
db/migrate/20150805144100_create_attachments.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
class CreateAttachments < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :attachments do |t|
|
||||
t.references :todo, index: true
|
||||
t.attachment :file
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
56
db/schema.rb
56
db/schema.rb
|
|
@ -11,11 +11,23 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20150209233951) do
|
||||
ActiveRecord::Schema.define(version: 20150805144100) do
|
||||
|
||||
create_table "attachments", force: true do |t|
|
||||
t.integer "todo_id"
|
||||
t.string "file_file_name"
|
||||
t.string "file_content_type"
|
||||
t.integer "file_file_size"
|
||||
t.datetime "file_updated_at"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "attachments", ["todo_id"], name: "index_attachments_on_todo_id", using: :btree
|
||||
|
||||
create_table "contexts", force: true do |t|
|
||||
t.string "name", null: false
|
||||
t.integer "position"
|
||||
t.integer "position", default: 0
|
||||
t.integer "user_id", default: 1
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
|
|
@ -85,11 +97,11 @@ ActiveRecord::Schema.define(version: 20150209233951) do
|
|||
add_index "preferences", ["user_id"], name: "index_preferences_on_user_id", using: :btree
|
||||
|
||||
create_table "projects", force: true do |t|
|
||||
t.string "name", null: false
|
||||
t.integer "position"
|
||||
t.integer "user_id", default: 1
|
||||
t.text "description"
|
||||
t.string "state", limit: 20, null: false
|
||||
t.string "name", null: false
|
||||
t.integer "position", default: 0
|
||||
t.integer "user_id", default: 1
|
||||
t.text "description", limit: 16777215
|
||||
t.string "state", limit: 20, null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "default_context_id"
|
||||
|
|
@ -104,17 +116,17 @@ ActiveRecord::Schema.define(version: 20150209233951) do
|
|||
add_index "projects", ["user_id"], name: "index_projects_on_user_id", using: :btree
|
||||
|
||||
create_table "recurring_todos", force: true do |t|
|
||||
t.integer "user_id", default: 1
|
||||
t.integer "context_id", null: false
|
||||
t.integer "user_id", default: 1
|
||||
t.integer "context_id", null: false
|
||||
t.integer "project_id"
|
||||
t.string "description", null: false
|
||||
t.text "notes"
|
||||
t.string "state", limit: 20, null: false
|
||||
t.string "description", null: false
|
||||
t.text "notes", limit: 16777215
|
||||
t.string "state", limit: 20, null: false
|
||||
t.datetime "start_from"
|
||||
t.string "ends_on"
|
||||
t.datetime "end_date"
|
||||
t.integer "number_of_occurrences"
|
||||
t.integer "occurrences_count", default: 0
|
||||
t.integer "occurrences_count", default: 0
|
||||
t.string "target"
|
||||
t.integer "show_from_delta"
|
||||
t.string "recurring_period"
|
||||
|
|
@ -123,7 +135,7 @@ ActiveRecord::Schema.define(version: 20150209233951) do
|
|||
t.integer "every_other2"
|
||||
t.integer "every_other3"
|
||||
t.string "every_day"
|
||||
t.boolean "only_work_days", default: false
|
||||
t.boolean "only_work_days", default: false
|
||||
t.integer "every_count"
|
||||
t.integer "weekday"
|
||||
t.datetime "completed_at"
|
||||
|
|
@ -141,7 +153,7 @@ ActiveRecord::Schema.define(version: 20150209233951) do
|
|||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", using: :btree
|
||||
add_index "sessions", ["session_id"], name: "sessions_session_id_index", using: :btree
|
||||
|
||||
create_table "taggings", force: true do |t|
|
||||
t.integer "taggable_id"
|
||||
|
|
@ -162,19 +174,19 @@ ActiveRecord::Schema.define(version: 20150209233951) do
|
|||
add_index "tags", ["name"], name: "index_tags_on_name", using: :btree
|
||||
|
||||
create_table "todos", force: true do |t|
|
||||
t.integer "context_id", null: false
|
||||
t.integer "context_id", null: false
|
||||
t.integer "project_id"
|
||||
t.string "description", null: false
|
||||
t.text "notes"
|
||||
t.string "description", null: false
|
||||
t.text "notes", limit: 16777215
|
||||
t.datetime "created_at"
|
||||
t.datetime "due"
|
||||
t.datetime "completed_at"
|
||||
t.integer "user_id", default: 1
|
||||
t.integer "user_id", default: 1
|
||||
t.datetime "show_from"
|
||||
t.string "state", limit: 20, null: false
|
||||
t.string "state", limit: 20, null: false
|
||||
t.integer "recurring_todo_id"
|
||||
t.datetime "updated_at"
|
||||
t.text "rendered_notes"
|
||||
t.text "rendered_notes", limit: 16777215
|
||||
end
|
||||
|
||||
add_index "todos", ["context_id"], name: "index_todos_on_context_id", using: :btree
|
||||
|
|
@ -212,7 +224,7 @@ ActiveRecord::Schema.define(version: 20150209233951) do
|
|||
|
||||
create_table "users", force: true do |t|
|
||||
t.string "login", limit: 80, null: false
|
||||
t.string "crypted_password", limit: 60, null: false
|
||||
t.string "crypted_password", limit: 60
|
||||
t.string "token"
|
||||
t.boolean "is_admin", default: false, null: false
|
||||
t.string "first_name"
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ class MessageGatewayTest < ActiveSupport::TestCase
|
|||
|
||||
def test_sms_with_no_subject
|
||||
todo_count = Todo.count
|
||||
|
||||
|
||||
load_message('sample_sms.txt')
|
||||
# assert some stuff about it being created
|
||||
assert_equal(todo_count+1, Todo.count)
|
||||
|
||||
|
||||
message_todo = Todo.where(:description => "message_content").first
|
||||
assert_not_nil(message_todo)
|
||||
|
||||
|
||||
assert_equal(@inbox, message_todo.context)
|
||||
assert_equal(@user, message_todo.user)
|
||||
end
|
||||
|
||||
|
||||
def test_mms_with_subject
|
||||
todo_count = Todo.count
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ class MessageGatewayTest < ActiveSupport::TestCase
|
|||
assert_equal(@user, message_todo.user)
|
||||
assert_equal("This is the message body", message_todo.notes)
|
||||
end
|
||||
|
||||
|
||||
def test_email_with_winmail_dat
|
||||
todo_count = Todo.count
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ class MessageGatewayTest < ActiveSupport::TestCase
|
|||
# assert some stuff about it being created
|
||||
assert_equal(todo_count+1, Todo.count)
|
||||
end
|
||||
|
||||
|
||||
def test_no_user
|
||||
todo_count = Todo.count
|
||||
badmessage = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_sms.txt'))
|
||||
|
|
@ -66,21 +66,38 @@ class MessageGatewayTest < ActiveSupport::TestCase
|
|||
MessageGateway.receive(badmessage)
|
||||
assert_equal(todo_count, Todo.count)
|
||||
end
|
||||
|
||||
|
||||
def test_direct_to_context
|
||||
message = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_sms.txt'))
|
||||
|
||||
|
||||
valid_context_msg = message.gsub('message_content', 'this is a task @ anothercontext')
|
||||
invalid_context_msg = message.gsub('message_content', 'this is also a task @ notacontext')
|
||||
|
||||
|
||||
MessageGateway.receive(valid_context_msg)
|
||||
valid_context_todo = Todo.where(:description => "this is a task").first
|
||||
assert_not_nil(valid_context_todo)
|
||||
assert_equal(contexts(:anothercontext), valid_context_todo.context)
|
||||
|
||||
|
||||
MessageGateway.receive(invalid_context_msg)
|
||||
invalid_context_todo = Todo.where(:description => 'this is also a task').first
|
||||
assert_not_nil(invalid_context_todo)
|
||||
assert_equal(@inbox, invalid_context_todo.context)
|
||||
end
|
||||
|
||||
def test_receiving_email_adds_attachment
|
||||
attachment_count = Attachment.count
|
||||
|
||||
load_message('sample_mms.txt')
|
||||
|
||||
message_todo = Todo.where(:description => "This is the subject").first
|
||||
assert_not_nil(message_todo)
|
||||
|
||||
assert_equal attachment_count+1, Attachment.count
|
||||
assert_equal 1,message_todo.attachments.count
|
||||
|
||||
orig = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_mms.txt'))
|
||||
attachment = File.read(message_todo.attachments.first.file.path)
|
||||
|
||||
assert_equal orig, attachment
|
||||
end
|
||||
end
|
||||
|
|
|
|||
7
test/fixtures/attachments.yml
vendored
Normal file
7
test/fixtures/attachments.yml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
one:
|
||||
todo_id:
|
||||
|
||||
two:
|
||||
todo_id:
|
||||
7
test/models/attachment_test.rb
Normal file
7
test/models/attachment_test.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
require 'test_helper'
|
||||
|
||||
class AttachmentTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
||||
|
|
@ -72,26 +72,26 @@ class TodoTest < ActiveSupport::TestCase
|
|||
def test_validate_show_from_must_be_a_date_in_the_future
|
||||
t = @not_completed2
|
||||
t.show_from = 1.week.ago
|
||||
|
||||
|
||||
assert !t.save, "todo should not be saved without validation errors"
|
||||
assert_equal 1, t.errors.count
|
||||
assert_equal "must be a date in the future", t.errors[:show_from][0]
|
||||
end
|
||||
|
||||
|
||||
def test_validate_circular_dependencies
|
||||
@completed.activate!
|
||||
@not_completed3=@completed
|
||||
|
||||
|
||||
# 2 -> 1
|
||||
@not_completed1.add_predecessor(@not_completed2)
|
||||
assert @not_completed1.save!
|
||||
assert_equal 1, @not_completed2.successors.count
|
||||
|
||||
|
||||
# 3 -> 2 -> 1
|
||||
@not_completed2.add_predecessor(@not_completed3)
|
||||
assert @not_completed2.save!
|
||||
assert_equal 1, @not_completed3.successors.count
|
||||
|
||||
|
||||
# 1 -> 3 -> 2 -> 1 == circle
|
||||
assert_raises ActiveRecord::RecordInvalid do
|
||||
@not_completed3.add_predecessor(@not_completed1)
|
||||
|
|
@ -131,7 +131,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
t.toggle_completion!
|
||||
assert_equal :active, t.aasm.current_state
|
||||
end
|
||||
|
||||
|
||||
def test_toggle_completion_with_show_from_in_future
|
||||
t = @not_completed1
|
||||
t.show_from= 1.week.from_now
|
||||
|
|
@ -140,12 +140,12 @@ class TodoTest < ActiveSupport::TestCase
|
|||
t.toggle_completion!
|
||||
assert_equal :completed, t.aasm.current_state
|
||||
end
|
||||
|
||||
|
||||
def test_toggle_completion_with_show_from_in_past
|
||||
t = @not_completed1
|
||||
t.update_attribute(:show_from, 1.week.ago)
|
||||
assert_equal :active, t.aasm.current_state
|
||||
|
||||
|
||||
assert t.toggle_completion!, "shoud be able to mark active todo complete even if show_from is set in the past"
|
||||
assert_equal :completed, t.aasm.current_state
|
||||
end
|
||||
|
|
@ -219,7 +219,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
# And I update the state of the todo from its project
|
||||
new_todo.update_state_from_project
|
||||
# Then the todo should be hidden
|
||||
assert new_todo.hidden?
|
||||
assert new_todo.hidden?
|
||||
end
|
||||
|
||||
def test_initial_state_defaults_to_active
|
||||
|
|
@ -280,7 +280,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert todo.pending?, "todo with predecessor should be blocked"
|
||||
|
||||
# cannot activate if part of hidden project
|
||||
assert_raise(AASM::InvalidTransition) { todo.activate! }
|
||||
assert_raise(AASM::InvalidTransition) { todo.activate! }
|
||||
|
||||
todo.remove_predecessor(todo2)
|
||||
assert todo.reload.hidden?, "todo should be put back in hidden state"
|
||||
|
|
@ -337,7 +337,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
@not_completed1.add_predecessor(@not_completed2)
|
||||
@not_completed1.save_predecessors
|
||||
# blocking is not done automagically
|
||||
@not_completed1.block!
|
||||
@not_completed1.block!
|
||||
|
||||
assert @not_completed1.uncompleted_predecessors?
|
||||
assert @not_completed1.pending?, "a todo with predecessors should be pending"
|
||||
|
|
@ -358,7 +358,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
@not_completed1.add_predecessor_list("#{@not_completed2.id}, #{@not_completed3.id}")
|
||||
@not_completed1.save_predecessors
|
||||
# blocking is not done automagically
|
||||
@not_completed1.block!
|
||||
@not_completed1.block!
|
||||
|
||||
# Then @completed1 should have predecessors and should be blocked
|
||||
assert @not_completed1.uncompleted_predecessors?
|
||||
|
|
@ -526,20 +526,43 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert !older_created_todos.include?(todo_now)
|
||||
assert !recent_created_todos.include?(todo_old)
|
||||
end
|
||||
|
||||
|
||||
def test_notes_are_rendered_on_save
|
||||
user = @completed.user
|
||||
todo = user.todos.create(:description => "test", :context => @completed.context)
|
||||
|
||||
|
||||
assert_nil todo.notes
|
||||
assert_nil todo.rendered_notes
|
||||
|
||||
|
||||
todo.notes = "*test*"
|
||||
todo.save!
|
||||
todo.reload
|
||||
|
||||
|
||||
assert_equal "*test*", todo.notes
|
||||
assert_equal "<p><strong>test</strong></p>", todo.rendered_notes
|
||||
end
|
||||
|
||||
def test_attachments_are_removed_after_delete
|
||||
# Given a user and a todo withou any attachments
|
||||
todo = @not_completed1
|
||||
assert_equal 0, todo.attachments.count, "we start without attachments"
|
||||
assert_equal 0, todo.user.attachments.count, "the user has no attachments"
|
||||
|
||||
# When I add a file as attachment to a todo of this user
|
||||
attachment = todo.attachments.build
|
||||
attachment.file = File.open(File.join(Rails.root, 'test', 'fixtures', 'email_with_multipart.txt'))
|
||||
attachment.save!
|
||||
new_path = attachment.file.path
|
||||
|
||||
# then the attachment should be there
|
||||
assert File.exists?(new_path), "attachment should be on file system"
|
||||
assert_equal 1, todo.attachments.reload.count, "should have one attachment"
|
||||
|
||||
# When I destroy the todo
|
||||
todo.destroy!
|
||||
|
||||
# Then the attachement and file should nogt be there anymore
|
||||
assert_equal 0, todo.user.attachments.reload.count
|
||||
assert !File.exists?(new_path), "attachment should not be on file system"
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue