public
Description: Uber lightweight Merb blogging engine. Make sure you check out the feather-plugins repo as well!
Homepage:
Clone URL: git://github.com/mleung/feather.git
Click here to lend your support to: feather and make a donation at www.pledgie.com !
feather / app / models / article.rb
100644 156 lines (128 sloc) 4.884 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
class Article
  include DataMapper::Validate
  include MerbPaginate::Finders::Datamapper
  include DataMapper::Resource
  
  property :id, Integer, :key => true, :serial => true
  property :title, String, :nullable => false, :length => 255
  property :content, Text, :nullable => false
  property :created_at, DateTime
  property :published_at, DateTime
  property :user_id, Integer, :nullable => false
  property :permalink, String, :length => 255
  property :published, Boolean, :default => false
  property :formatter, String, :default => "default"
  
  validates_present :title, :key => "uniq_title"
  validates_present :content, :key => "uniq_content"
  validates_present :user_id, :key => "uniq_user_id"
  
  belongs_to :user
  
  # Core filters
  before :save, :set_published_permalink
  after :create, :set_create_activity
  after :update, :set_update_activity
  
  # Event hooks for plugins
  before :create, :fire_before_create_event
  before :update, :fire_before_update_event
  before :save, :fire_before_save_event
  after :create, :fire_after_create_event
  after :update, :fire_after_update_event
  after :save, :fire_after_save_event
  
  ##
  # This sets the published date and permalink when an article is published
  def set_published_permalink
    # Check to see if we are publishing
    if self.is_published?
      # Set the date, only if we haven't already
      self.published_at = Time.now if self.published_at.nil?
      
      # Set the permalink, only if we haven't already
      self.permalink = create_permalink
    end
    true
  end
 
  def set_create_activity
    a = Activity.new
    a.message = "Article \"#{self.title}\" created"
    a.save
  end
 
  def set_update_activity
    a = Activity.new
    a.message = "Article \"#{self.title}\" updated"
    a.save
  end
 
  def fire_before_create_event
    Hooks::Events.before_create_article(self)
  end
 
  def fire_before_update_event
    Hooks::Events.before_update_article(self) unless new_record?
  end
 
  def fire_before_save_event
    Hooks::Events.before_save_article(self)
    Hooks::Events.before_publish_article(self) if self.is_published?
  end
 
  def fire_after_create_event
    Hooks::Events.after_create_article(self)
  end
  
  def fire_after_update_event
    Hooks::Events.after_update_article(self) unless new_record?
  end
 
  def fire_after_save_event
    Hooks::Events.after_save_article(self)
    Hooks::Events.after_publish_article(self) if self.is_published?
  end
 
  def is_published?
    # We need this beacuse the values get populated from the params
    self.published == "1" || self.published
  end
  
  def create_permalink
    permalink = Configuration.current.permalink_format.gsub(/:year/,self.published_at.year.to_s)
    permalink.gsub!(/:month/,Padding::pad_single_digit(self.published_at.month))
    permalink.gsub!(/:day/,Padding::pad_single_digit(self.published_at.day))
    
    title = self.title.gsub(/\W+/, ' ') # all non-word chars to spaces
    title.strip! # ohh la la
    title.downcase! #
    title.gsub!(/\ +/, '-') # spaces to dashes, preferred separator char everywhere
    permalink.gsub!(/:title/,title)
    
    permalink
  end
 
  class << self
    ##
    # Custom finders
 
    def find_recent
      self.all(:published => true, :limit => 10, :order => [:published_at.desc])
    end
 
    def find_by_year(year)
      self.all(:published_at.like => "#{year}%", :published => true, :order => [:published_at.desc])
    end
 
    def find_by_year_month(year, month)
      month = Padding::pad_single_digit(month)
      self.all(:published_at.like => "#{year}-#{month}%", :published => true, :order => [:published_at.desc])
    end
 
    def find_by_year_month_day(year, month, day)
      month = Padding::pad_single_digit(month)
      day = Padding::pad_single_digit(day)
      self.all(:published_at.like => "#{year}-#{month}-#{day}%", :published => true, :order => [:published_at.desc])
    end
 
    def find_by_permalink(permalink)
      self.first(:permalink => permalink)
    end
 
    def get_archive_hash
      counts = repository.adapter.query("SELECT COUNT(*) as count, #{specific_date_function} FROM articles WHERE published_at IS NOT NULL AND published = 1 GROUP BY year, month ORDER BY year DESC, month DESC")
      archives = counts.map do |entry|
        {
          :name => "#{Date::MONTHNAMES[entry.month.to_i]} #{entry.year}",
          :month => entry.month.to_i,
          :year => entry.year.to_i,
          :article_count => entry.count
        }
      end
      archives
    end
 
    private
      def specific_date_function
        if Merb::Orms::DataMapper.config[:adapter] == "sqlite3"
          "strftime('%Y', published_at) as year, strftime('%m', published_at) as month"
        else
          "extract(year from published_at) as year, extract(month from published_at) as month"
        end
      end
  end
end