public
Description: railscasts.com in open source goodness!
Homepage: http://railscasts.com
Clone URL: git://github.com/ryanb/railscasts.git
railscasts / app / models / episode.rb
100644 126 lines (102 sloc) 3.209 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
class Episode < ActiveRecord::Base
  has_many :comments, :dependent => :destroy
  has_many :taggings, :dependent => :destroy
  has_many :tags, :through => :taggings
  has_many :downloads, :dependent => :destroy
  
  acts_as_list
  
  named_scope :published, lambda { {:conditions => ['published_at <= ?', Time.now.utc]} }
  named_scope :unpublished, lambda { {:conditions => ['published_at > ?', Time.now.utc]} }
  named_scope :recent, :order => 'position DESC'
  
  validates_presence_of :published_at, :name
  validates_associated :downloads, :on => :update # create automatically handles validation
  
  before_create :set_permalink
  after_update :save_downloads
  
  # sometimes ThinkingSphinx isn't loaded for rake tasks
  if respond_to? :define_index
    define_index do
      indexes :name
      indexes position, :sortable => true
      indexes description
      indexes notes
      indexes comments.content, :as => :comment_content
      indexes tags(:name), :as => :tag_names
    
      has published_at
    end
  end
  
  def self.search_published(query)
    if APP_CONFIG['thinking_sphinx']
      search(query, :conditions => { :published_at => 0..Time.now.utc.to_i },
                    :field_weights => { :name => 20, :description => 15, :notes => 5, :tag_names => 10 })
    else
      published.primitive_search(query)
    end
  rescue ThinkingSphinx::ConnectionError => e
    APP_CONFIG['thinking_sphinx'] = false
    raise e
  end
  
  def self.primitive_search(query)
    find(:all, :conditions => primitive_search_conditions(query))
  end
  
  def published_month
    published_at.beginning_of_month
  end
  
  def mov
    downloads.find_by_format('mov')
  end
  
  def m4v
    downloads.find_by_format('m4v')
  end
  
  def tag_names=(names)
    self.tags = Tag.with_names(names.split(/\s+/))
  end
  
  def tag_names
    tags.map(&:name).join(' ')
  end
  
  def to_param
    [position, permalink].join('-')
  end
  
  def last_published?
    self == self.class.published.last
  end
  
  def new_download_attributes=(download_attributes)
    download_attributes.each do |attributes|
      downloads.build(attributes)
    end
  end
  
  def existing_download_attributes=(download_attributes)
    downloads.reject(&:new_record?).each do |download|
      attributes = download_attributes[download.id.to_s]
      if attributes
        download.attributes = attributes
      else
        downloads.delete(download)
      end
    end
  end
  
  def duration
    if seconds
      min, sec = *seconds.divmod(60)
      [min, sec.to_s.rjust(2, '0')].join(':')
    end
  end
  
  def duration=(duration)
    min, sec = *duration.split(':').map(&:to_i)
    self.seconds = min*60 + sec
  end
  
  private
  
  def self.primitive_search_conditions(query)
    query.split(/\s+/).map do |word|
      '(' + %w[name description notes].map { |col| "#{col} LIKE #{sanitize('%' + word.to_s + '%')}" }.join(' OR ') + ')'
    end.join(' AND ')
  end
  
  def save_downloads
    if downloads.loaded?
      downloads.each do |download|
        download.save(false)
      end
    end
  end
  
  def set_permalink
    self.permalink = name.downcase.gsub(/[^0-9a-z]+/, ' ').strip.gsub(' ', '-') if name
  end
end