2007-03-30 04:36:52 +00:00
|
|
|
class Project < ActiveRecord::Base
|
2009-04-18 23:50:12 +02:00
|
|
|
has_many :todos, :dependent => :delete_all, :include => [:context,:tags]
|
2011-01-01 18:55:53 +01:00
|
|
|
|
|
|
|
|
# TODO: remove these scopes. Can be replaced by the named scopes on the todo relation
|
2009-04-19 00:18:12 +02:00
|
|
|
has_many :not_done_todos,
|
|
|
|
|
:include => [:context,:tags,:project],
|
|
|
|
|
:class_name => 'Todo',
|
|
|
|
|
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
|
|
|
|
:conditions => ["todos.state = ?", 'active']
|
2009-04-18 23:50:12 +02:00
|
|
|
has_many :not_done_todos_including_hidden,
|
|
|
|
|
:include => [:context,:tags,:project],
|
|
|
|
|
:class_name => 'Todo',
|
|
|
|
|
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
|
|
|
|
:conditions => ["(todos.state = ? OR todos.state = ?)", 'active', 'project_hidden']
|
2009-04-19 00:18:12 +02:00
|
|
|
has_many :done_todos,
|
|
|
|
|
:include => [:context,:tags,:project],
|
|
|
|
|
:class_name => 'Todo',
|
|
|
|
|
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
|
|
|
|
:conditions => ["todos.state = ?", 'completed']
|
2009-04-18 23:50:12 +02:00
|
|
|
has_many :deferred_todos,
|
|
|
|
|
:include => [:context,:tags,:project],
|
|
|
|
|
:class_name => 'Todo',
|
|
|
|
|
:conditions => ["todos.state = ? ", "deferred"],
|
|
|
|
|
:order => "show_from"
|
2009-05-20 02:06:42 +02:00
|
|
|
has_many :pending_todos,
|
|
|
|
|
:include => [:context,:tags,:project],
|
|
|
|
|
:class_name => 'Todo',
|
|
|
|
|
:conditions => ["todos.state = ? ", "pending"],
|
|
|
|
|
:order => "show_from"
|
2009-04-18 23:50:12 +02:00
|
|
|
|
2007-03-30 04:36:52 +00:00
|
|
|
has_many :notes, :dependent => :delete_all, :order => "created_at DESC"
|
2010-04-04 18:20:07 +02:00
|
|
|
has_many :recurring_todos
|
2009-04-18 23:50:12 +02:00
|
|
|
|
2008-06-17 01:13:25 -04:00
|
|
|
belongs_to :default_context, :class_name => "Context", :foreign_key => "default_context_id"
|
2007-03-30 04:36:52 +00:00
|
|
|
belongs_to :user
|
2008-11-29 15:35:17 +01:00
|
|
|
|
|
|
|
|
named_scope :active, :conditions => { :state => 'active' }
|
|
|
|
|
named_scope :hidden, :conditions => { :state => 'hidden' }
|
|
|
|
|
named_scope :completed, :conditions => { :state => 'completed'}
|
2011-01-01 18:55:53 +01:00
|
|
|
named_scope :uncompleted, :conditions => ["NOT state = ?", 'completed']
|
2007-03-30 04:36:52 +00:00
|
|
|
|
2010-10-31 21:27:13 +08:00
|
|
|
validates_presence_of :name
|
|
|
|
|
validates_length_of :name, :maximum => 255
|
2010-11-09 15:51:21 +01:00
|
|
|
validates_uniqueness_of :name, :scope => "user_id"
|
2010-10-31 21:27:13 +08:00
|
|
|
validates_does_not_contain :name, :string => ','
|
2007-03-30 04:36:52 +00:00
|
|
|
|
|
|
|
|
acts_as_list :scope => 'user_id = #{user_id} AND state = \'#{state}\''
|
|
|
|
|
acts_as_state_machine :initial => :active, :column => 'state'
|
|
|
|
|
extend NamePartFinder
|
2009-04-18 23:50:12 +02:00
|
|
|
#include Tracks::TodoList
|
2007-03-30 04:36:52 +00:00
|
|
|
|
|
|
|
|
state :active
|
|
|
|
|
state :hidden, :enter => :hide_todos, :exit => :unhide_todos
|
2008-09-21 18:03:35 -07:00
|
|
|
state :completed, :enter => Proc.new { |p| p.completed_at = Time.zone.now }, :exit => Proc.new { |p| p.completed_at = nil }
|
2007-03-30 04:36:52 +00:00
|
|
|
|
|
|
|
|
event :activate do
|
|
|
|
|
transitions :to => :active, :from => [:hidden, :completed]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
event :hide do
|
|
|
|
|
transitions :to => :hidden, :from => [:active, :completed]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
event :complete do
|
|
|
|
|
transitions :to => :completed, :from => [:active, :hidden]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
attr_protected :user
|
|
|
|
|
attr_accessor :cached_note_count
|
|
|
|
|
|
|
|
|
|
def self.null_object
|
|
|
|
|
NullProject.new
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.feed_options(user)
|
|
|
|
|
{
|
2010-11-09 10:47:09 +01:00
|
|
|
:title => I18n.t('models.project.feed_title'),
|
|
|
|
|
:description => I18n.t('models.project.feed_description', :username => user.display_name)
|
2007-03-30 04:36:52 +00:00
|
|
|
}
|
|
|
|
|
end
|
2007-04-06 03:30:20 +00:00
|
|
|
|
2007-03-30 04:36:52 +00:00
|
|
|
def hide_todos
|
|
|
|
|
todos.each do |t|
|
|
|
|
|
unless t.completed? || t.deferred?
|
|
|
|
|
t.hide!
|
|
|
|
|
t.save
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def unhide_todos
|
|
|
|
|
todos.each do |t|
|
|
|
|
|
if t.project_hidden?
|
|
|
|
|
t.unhide!
|
|
|
|
|
t.save
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def note_count
|
|
|
|
|
cached_note_count || notes.count
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
alias_method :original_default_context, :default_context
|
|
|
|
|
|
|
|
|
|
def default_context
|
|
|
|
|
original_default_context.nil? ? Context.null_object : original_default_context
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# would prefer to call this method state=(), but that causes an endless loop
|
|
|
|
|
# as a result of acts_as_state_machine calling state=() to update the attribute
|
|
|
|
|
def transition_to(candidate_state)
|
|
|
|
|
case candidate_state.to_sym
|
|
|
|
|
when current_state
|
|
|
|
|
return
|
|
|
|
|
when :hidden
|
|
|
|
|
hide!
|
|
|
|
|
when :active
|
|
|
|
|
activate!
|
|
|
|
|
when :completed
|
|
|
|
|
complete!
|
|
|
|
|
end
|
|
|
|
|
end
|
2007-10-03 03:05:34 +00:00
|
|
|
|
|
|
|
|
def name=(value)
|
|
|
|
|
self[:name] = value.gsub(/\s{2,}/, " ").strip
|
|
|
|
|
end
|
2007-11-04 23:06:46 +00:00
|
|
|
|
|
|
|
|
def new_record_before_save?
|
|
|
|
|
@new_record_before_save
|
|
|
|
|
end
|
|
|
|
|
|
2007-03-30 04:36:52 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
class NullProject
|
|
|
|
|
|
|
|
|
|
def hidden?
|
|
|
|
|
false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def nil?
|
|
|
|
|
true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def id
|
|
|
|
|
nil
|
|
|
|
|
end
|
|
|
|
|
|
2009-04-19 00:18:12 +02:00
|
|
|
end
|