Topic: Archiving Blog Posts :: My attempt at a tutorial

I have been working on writing my own blog software for my blog at http://www.nu2rails.com because while wordpress is great it's a lot more than what I need in my blogger. While I was working I decided that I wanted to be able to create archives by month and year and after some thought I came up with the best way I could.

What I wanted:
1.) I wanted the first article created in a certain month to start he archiving for that month
2.) I wanted to add articles to the current months archive
3.) I wanted to easily be able to display a full list of archived months
4.) I wanted to make sure that archives from June/2008 wouldn't get confused with archives from June/2009 if the blog lasts that long.

What I didn't want:
1.) I didn't want an archive created if there were no posts for that month.
2.) I didn't want to have to manually create an archive each month
3.) I didn't want to have to make a whole bunch of unnecessary database calls

What I did:

First I generated a scaffold of and Archive model

ruby script/generate scaffold Archive month:string year:string

Then when that was all done I opened the migration that was created and added a column to the my Posts table (Where all my blog posts are stored) to reference a row in the Archives table.
I also added the "month" and "year" columns as indexes.

here is my migration:

class CreateArchives < ActiveRecord::Migration
  def self.up
    create_table :archives do |t|
      t.string :month
      t.string :year

      t.timestamps
    end
   
    add_column :posts, :archive_id, :integer
    add_index "archives", "month"
    add_index "archives", "year"
  end

  def self.down
    drop_table :archives
  end
end


Once that was done I opened my archive.rb model and added an has_many association to the posts model

archive.rb

class Archive < ActiveRecord::Base
  # Model Associations
  has_many :posts
end

Then in the post model is where the magic happens. First thing was to add a belongs_to association to the archive model

belongs_to :archive

After that I wanted the creation of an archive or the addition to an archive automatic. So I made a small method that does just that.

def make_archive
  if @a = Archive.find_by_month(Time.now.strftime('%B'))
    self.archive_id = @a.id
  else
    @a = Archive.create(:month => Time.now.strftime('%B'), :year => Time.now.strftime('%Y'))
    self.archive_id = @a.id
  end
end

Then I simply added that as a before filter in the post.rb model file and bang... it worked.
Here is my full post.rb file so you can see how it's set up.

Post.rb

class Post < ActiveRecord::Base
  # Model Associations
  has_and_belongs_to_many :categories
  belongs_to :archive
  belongs_to :user
  has_many :comments
 
  # Make sure all the info we need is there
  validates_presence_of :title
  validates_presence_of :body
 
  # Before it saves let's see if there is an archive for this month, if not add one.
  before_save :make_archive
 
protected
  # Method to add an existing archive or create a new one.
  def make_archive
    if @a = Archive.find_by_month(Time.now.strftime('%B'))
      self.archive_id = @a.id
    else
      @a = Archive.create(:month => Time.now.strftime('%B'), :year => Time.now.strftime('%Y'))
      self.archive_id = @a.id
    end
  end
end

And that's how I implemented the automatic archiving of my blog posts. I'm not sure that it's the most railsy way to do this but it's the best I could think of. I hope this helps someone and if there is a better way to do this I would appreciate letting me know as I'm still pretty new.

Happy Coding smile
Mitchell

Re: Archiving Blog Posts :: My attempt at a tutorial

Thanks Mitchell,

Great idea - thanks for the tutorial.

I've been looking for a good Blog example that has Categories...

Would you be willing to share the complete code ?

Cheers, DaveP

Re: Archiving Blog Posts :: My attempt at a tutorial

I wouldn't call what my blog (that's not done yet) great by any means but I can get it up for download a little later. I'll post a link once it's up and ready.

Re: Archiving Blog Posts :: My attempt at a tutorial

Thanks for that...

I'm, sure it will be fine for a newbie like me !!!

regards, DaveP

Re: Archiving Blog Posts :: My attempt at a tutorial

Hey Dave you can download what I have so far at http://nu2rails.com/download/blog.tar.gz
It isn't complete and I don't have any test written yet so don't consider it a functional script that I would recommend using on a live site. Just to make sure. This Code Is Not Stable For A Live Site. If You Use It You Do So At Your Own Risk. I Am Not Liable.

Re: Archiving Blog Posts :: My attempt at a tutorial

Thanks for organising that so quickly.

If I have any questions I'll post back here....

It is purely educational.

Cheers, Dave

Re: Archiving Blog Posts :: My attempt at a tutorial

OK, I created a new rails project with the same name ( blog ).

Copied over the app folder & also the routes.rb file, the vendors plugins & the migrations.

The only difference is I'm using the default sqlite3 database instead of MySQL.

Did a rake db:migrate, which created the tables fine.

But when I browse to the localhost:3000 I get the following error.

>>>> Quote
NameError

uninitialized constant ApplicationController::AuthenticatedSystem

RAILS_ROOT: E:/ruby/RailsApps/blog
Application Trace | Framework Trace | Full Trace

e:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:478:in `const_missing'
app/controllers/application.rb:12

Any ideas ?
cheers, Dave

Re: Archiving Blog Posts :: My attempt at a tutorial

Looks like it's not including the "AuthenticatedSystem.rb" from the lib directory. Might want to check and make sure it's there.

Re: Archiving Blog Posts :: My attempt at a tutorial

Yep, missed the files in lib - thanks...

In browsing the code I see the make_archive method, but I don't understand exactly what is going on here...

If you could explain it I would be most appreciative...

I don't see where @a comes from ?

regards, Dave

  # Before it saves let's see if there is an archive for this month, if not add one.
  before_save :make_archive
 
protected
  # Method to add an existing archive or create a new one.
  def make_archive
    if @a = Archive.find_by_month(Time.now.strftime('%B'))
      self.archive_id = @a.id
    else
      @a = Archive.create(:month => Time.now.strftime('%B'), :year => Time.now.strftime('%Y'))
      self.archive_id = @a.id
    end
  end
end

Re: Archiving Blog Posts :: My attempt at a tutorial

Also what is the secret handshake to login to Admin for the first time ?
I see there are no default users.
cheers, Dave

Re: Archiving Blog Posts :: My attempt at a tutorial

def make_archive
    # If there is already an archive for the current month store it in @a
    if @a = Archive.find_by_month(Time.now.strftime('%B'))
      # Since we already have an archive for the current month the set the
      # archive_id field of the post to the one we set to @a
      self.archive_id = @a.id
    else
      # If there isn't already and archive for the current month Create one
      @a = Archive.create(:month => Time.now.strftime('%B'), :year => Time.now.strftime('%Y'))
      # Then set the archive_id of the post to the archive we just created.
      self.archive_id = @a.id
    end
  end
end

Re: Archiving Blog Posts :: My attempt at a tutorial

OK, forgot about signup, so I went there, but now I get the following error:

NoMethodError in UsersController#create

undefined method `validates_uqniqueness_of' for Role(id: integer, name: string):Class

RAILS_ROOT: E:/ruby/RailsApps/blog
Application Trace | Framework Trace | Full Trace

e:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1532:in `method_missing'
app/models/role.rb:6
app/models/user.rb:78:in `default_role'
app/controllers/users_controller.rb:15:in `create'

Re: Archiving Blog Posts :: My attempt at a tutorial

The admin isn't funcitional and doesn't do anything at the moment. To get it to work you can create a role called admin and create a user then in the roles_users id put the user id in the user_id column and put the id of the admin role into the role_id field Like I said it's not completed but so there probably won't be a default. I'm writing this for my own site not necassarily for release so I haven't made previsions for an auto generated admin account.

Re: Archiving Blog Posts :: My attempt at a tutorial

That's because there isn't a role called user created in the roles database