{"id":51808,"date":"2009-02-11T20:27:00","date_gmt":"2009-02-11T20:27:00","guid":{"rendered":"\/2009\/04\/02\/blog-plugin-tutorial-for-ruby-on-rails"},"modified":"2009-08-30T00:37:50","modified_gmt":"2009-08-30T00:37:50","slug":"blog-plugin-tutorial-for-ruby-on-rails","status":"publish","type":"post","link":"http:\/\/pullmonkey.com\/2009\/02\/11\/blog-plugin-tutorial-for-ruby-on-rails\/","title":{"rendered":"Blog plugin tutorial for Ruby on Rails"},"content":{"rendered":"
Update:<\/b> Bloggity does not require the Engines plugin to run if you are using Rails 2.3 or above (where the Engines plugin is baked in). -- Noted below by Bill.
\n
Update:<\/b> Added the plugin to github - simple_blog<\/a>. It is not production ready or really all that usable quite yet.<\/p>\nOk, so this a rant and I am sorry for that - but as simple as it is, I have been looking for a blog plugin lately. The problem with the plugins I find is that I don't want to have to deal with the engines plugin or have the controllers, models, views, etc ... all extracted into my applications code. I want it all external (hence a plugin) but let it be minimally configurable.<\/p>\n
So in my recent search for a blog plugin for rails, I came across two that look very useful, but each with their flaws:
\n1) bloget<\/a> - Everything is extracted to my code space. Why? Yes, I realize that it is most likely because I will want to override things, but get out of my space and keep to yourself! \ud83d\ude42
\nProvide me a way to override things that I would need to (there really shouldn't be too many), after all it is ruby.
\n2) bloggity<\/a> - Uses the engines plugin! I have nothing against the engines plugin (I think it is well written and documented) but for a freaking blog plugin?!? Why? <\/p>\nIs there a third option?
\nGlad you asked - yes, there is a third option - I hate to say it, but do it right! There's your third option.
\nOk, but really, if there is a third option (a third plugin), I would love to hear about it.<\/p>\n
Ok, so all that to lead up to a little plugin tutorial? Well, it got your attention didn't it?<\/p>\n
Starting from scratch<\/h1>\n
Ok, I guess I will start from scratch. So let's get started.<\/p>\n
Creating a plugin<\/h2>\n
\n\n\n1\r\n<\/tt>2\r\n<\/tt>3\r\n<\/tt>4\r\n<\/tt>5<\/strong>\r\n<\/tt>6\r\n<\/tt>7\r\n<\/tt>8\r\n<\/tt>9\r\n<\/tt>10<\/strong>\r\n<\/tt>11\r\n<\/tt>12\r\n<\/tt>13\r\n<\/tt>14\r\n<\/tt><\/pre>\n<\/td>\n\npullmonkey$<\/span> .\/script\/generate plugin simple_blog\r\n<\/tt> create vendor\/plugins\/simple_blog\/lib\r\n<\/tt> create vendor\/plugins\/simple_blog\/tasks\r\n<\/tt> create vendor\/plugins\/simple_blog\/test\r\n<\/tt> create vendor\/plugins\/simple_blog\/README<\/span>\r\n<\/tt> create vendor\/plugins\/simple_blog\/MIT<\/span>-LICENSE<\/span>\r\n<\/tt> create vendor\/plugins\/simple_blog\/Rakefile<\/span>\r\n<\/tt> create vendor\/plugins\/simple_blog\/init.rb\r\n<\/tt> create vendor\/plugins\/simple_blog\/install.rb\r\n<\/tt> create vendor\/plugins\/simple_blog\/uninstall.rb\r\n<\/tt> create vendor\/plugins\/simple_blog\/lib\/simple_blog.rb\r\n<\/tt> create vendor\/plugins\/simple_blog\/tasks\/simple_blog_tasks.rake\r\n<\/tt> create vendor\/plugins\/simple_blog\/test\/simple_blog_test.rb\r\n<\/tt> create vendor\/plugins\/simple_blog\/test\/test_helper.rb\r\n<\/tt><\/pre>\n<\/td>\n<\/tr>\n<\/table>\nCreate the app directories for your plugin<\/h2>\n\n\n\n1\r\n<\/tt>2\r\n<\/tt>3\r\n<\/tt>4\r\n<\/tt>5<\/strong>\r\n<\/tt>6\r\n<\/tt>7\r\n<\/tt>8\r\n<\/tt>9\r\n<\/tt>10<\/strong>\r\n<\/tt><\/pre>\n<\/td>\n\npullmonkey$<\/span> cd vendor\/plugins\/simple_blog\/ # pretty important<\/span>\r\n<\/tt>pullmonkey$<\/span> ls\r\n<\/tt>init.rb install.rb lib MIT<\/span>-LICENSE<\/span> Rakefile<\/span> README<\/span> tasks test uninstall.rb\r\n<\/tt>pullmonkey$<\/span> mkdir app\r\n<\/tt>pullmonkey$<\/span> mkdir -p app\/models\r\n<\/tt>pullmonkey$<\/span> mkdir -p app\/controllers\r\n<\/tt>pullmonkey$<\/span> mkdir -p app\/views\r\n<\/tt>pullmonkey$<\/span> mkdir -p app\/helpers\r\n<\/tt>pullmonkey$<\/span> ls app\/\r\n<\/tt>controllers helpers models views\r\n<\/tt><\/pre>\n<\/td>\n<\/tr>\n<\/table>\nWell that was easy, so let's move on.<\/p>\n <\/p>\n Models, Views, Controllers and Helpers - Living as one in my plugin<\/h1>\nModels<\/h2>\nOk, so we have a clear path for where our models, controllers, views, and helpers should live, right? \nFor simplicity, let's just have a post and comment model - you have all seen this a billion times.<\/p>\n Models: vendor\/plugins\/simple_blog\/app\/models\/post.rb<\/h3>\n\n\n\n1\r\n<\/tt>2\r\n<\/tt>3\r\n<\/tt><\/pre>\n<\/td>\n\nclass<\/span> Post<\/span> < ActiveRecord<\/span>::Base<\/span>\r\n<\/tt> has_many :comments<\/span>\r\n<\/tt>end<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/table>\nModels: vendor\/plugins\/simple_blog\/app\/models\/comment.rb<\/h3>\n\n\n\n1\r\n<\/tt>2\r\n<\/tt>3\r\n<\/tt><\/pre>\n<\/td>\n\nclass<\/span> Comment<\/span> < ActiveRecord<\/span>::Base<\/span>\r\n<\/tt> belongs_to :post<\/span>\r\n<\/tt>end<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/table>\nAnd there you have it. \nSo what do you do to tell your rails application about your models? \nSimple - inside vendor\/plugins\/simple_blog\/init.rb - add these lines<\/p>\n \n\n\n1\r\n<\/tt>2\r\n<\/tt>3\r\n<\/tt><\/pre>\n<\/td>\n\nmodel_path = File<\/span>.join(directory, '<\/span>app<\/span>'<\/span><\/span>, '<\/span>models<\/span>'<\/span><\/span>)\r\n<\/tt>$LOAD_PATH<\/span> << model_path\r\n<\/tt>ActiveSupport<\/span>::Dependencies<\/span>.load_paths << model_path<\/pre>\n<\/td>\n<\/tr>\n<\/table>\nOk, so let's test it out.<\/h3>\nStep 1 - we will need some default migrations for the model to use. \nPost migration:<\/p>\n \n\n\n1\r\n<\/tt>2\r\n<\/tt>3\r\n<\/tt>4\r\n<\/tt>5<\/strong>\r\n<\/tt>6\r\n<\/tt>7\r\n<\/tt>8\r\n<\/tt>9\r\n<\/tt>10<\/strong>\r\n<\/tt>11\r\n<\/tt>12\r\n<\/tt>13\r\n<\/tt>14\r\n<\/tt>15<\/strong>\r\n<\/tt><\/pre>\n<\/td>\n\npullmonkey$<\/span> .\/script\/generate migration post\r\n<\/tt># This is what mine looks like<\/span>\r\n<\/tt>class<\/span> Post<\/span> < ActiveRecord<\/span>::Migration<\/span>\r\n<\/tt> def<\/span> self<\/span>.up\r\n<\/tt> create_table :posts<\/span> do<\/span> |t|\r\n<\/tt> t.string :subject<\/span>\r\n<\/tt> t.text :body<\/span>\r\n<\/tt> t.timestamps\r\n<\/tt> end<\/span>\r\n<\/tt> end<\/span>\r\n<\/tt>\r\n<\/tt> def<\/span> self<\/span>.down\r\n<\/tt> drop_table :posts<\/span>\r\n<\/tt> end<\/span>\r\n<\/tt>end<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/table>\nAnd then the comment migration:<\/p>\n \n\n\n1\r\n<\/tt>2\r\n<\/tt>3\r\n<\/tt>4\r\n<\/tt>5<\/strong>\r\n<\/tt>6\r\n<\/tt>7\r\n<\/tt>8\r\n<\/tt>9\r\n<\/tt>10<\/strong>\r\n<\/tt>11\r\n<\/tt>12\r\n<\/tt>13\r\n<\/tt>14\r\n<\/tt><\/pre>\n<\/td>\n\npullmonkey$<\/span> .\/script\/generate migration comment\r\n<\/tt># This is what mine looks like<\/span>\r\n<\/tt> def<\/span> self<\/span>.up\r\n<\/tt> create_table :comments<\/span> do<\/span> |t|\r\n<\/tt> t.string :username<\/span>\r\n<\/tt> t.text :body<\/span>\r\n<\/tt> t.references :post<\/span>\r\n<\/tt> t.timestamps\r\n<\/tt> end<\/span>\r\n<\/tt> end<\/span>\r\n<\/tt>\r\n<\/tt> def<\/span> self<\/span>.down\r\n<\/tt> drop_table :comments<\/span>\r\n<\/tt> end<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/table>\nRun the migrations:<\/p>\n \n\n\n\r\n<\/tt><\/pre>\n<\/td>\n\n | | | | | | | | | | | | | | | |