Component Development Tutorial
Version
This document applies to Rubricks-0.5.x
Introduction
Premise knowledge
You need the following knowledge to read this tutorial.
- Ruby
- Ruby on Rails(Here in after we call 'Rails')
- Basic administration of Rubricks
Preparation
Please refer to Install Guide and prepare your development environment.
What is a component?
A component in Ruburicks is a unit which supplies extended functionality. You can use these ones combined.
+Image01 Component Architecture
Hello World
First of all, we make "Hello World" component and understand the atmosphere of the component development.
+Image02 Hello World Component
Generator
Ruburicks has generator to aid component development. You can generate skeletons of the component.
+List01 Format of rubricks_component generator
ruby script/generate rubricks_controller [component_name/controller_name] [action_name_list]
Note: You can specify more than one action_name by using comma.
+List02 Generate HelloWorld Component
> ruby script/generate rubricks_component hello_world greet main
create components/hello_world
create components/hello_world/greet
create components/hello_world/languages
create components/hello_world/_install
create components/hello_world/_install/db
create components/hello_world/_install/images
create components/hello_world/greet_controller.rb
create components/hello_world/greet_helper.rb
create components/hello_world/greet/main.rhtml
create components/hello_world/languages/japanese.rb
create components/hello_world/languages/english.rb
create components/hello_world/_install/component_info.rb
create components/hello_world/_install/db/001_hello_world_schema.rb
create components/hello_world/_install/images/hello_world.gif
create components/hello_world/_install/images/hello_world_active.gif
created install/hello_world.rzip
== HelloWorldSchema: migrating ================================================
== HelloWorldSchema: migrated (0.0000s) =======================================
installed hello_world
The controller and view are generated for hello_wold component.
Implementation of the controller
You don't need to modify this controller if you wanna display only 'Hello World'. But in this tutorial, let's try adding current time with 'Hello World'. Please modify generated greet controller as follow.
+List03 /components/hello_world/greet_controller.rb
class HelloWorld::GreetController < ApplicationController
define_page
uses_component_template_root
def main
@time = Time.now.to_s.toutf8
end
Implementation of the view
It is same as general view of the Rails mostly, except that only part of the page is necessary.
+List04 /components/hello_world/greet/main.rhtml
Hello World<br> The current time is <%= @time %>
Operation check
Implementation of the Hello World is completed. Let's boot WEBrick and access.
Making news component
From this section, get into more detailed explanation through actual component development by developping the news component.
Specification
Functions of the news component are as follows.
- Display 'Post News' and 'Refer News' menu.
- User can post news.
- Posted news is displayed in news block.
Design of the application
A table is needed to save posted news used by the news component. Start up MySQL and create news_item table.
+List05 SQL for news items table
CREATE TABLE news_items ( id INTEGER UNSIGNED NOT NULL DEFAULT null AUTO_INCREMENT, /* ID */ title VARCHAR(192) NOT NULL, /* Title */ rubricks_user_id INTEGER(10) NOT NULL, /* Poster ID */ article TEXT NOT NULL, /* News */ created_at DATETIME NOT NULL, /* Last Modified Date */ PRIMARY KEY(id) ) TYPE=InnoDB;
Implementation of basic functions
Generate skelton
+List06 Generate News Component
> ruby script/generate rubricks_component news post main
create components/news
create components/news/post
create components/news/languages
create components/news/_install
create components/news/_install/db
create components/news/_install/images
create components/news/post_controller.rb
create components/news/post_helper.rb
create components/news/post/main.rhtml
create components/news/languages/japanese.rb
create components/news/languages/english.rb
create components/news/_install/component_info.rb
create components/news/_install/db/001_news_schema.rb
create components/news/_install/images/news.gif
create components/news/_install/images/news_active.gif
created install/news.rzip
== NewsSchema: migrating ======================================================
== NewsSchema: migrated (0.0000s) =============================================
installed news
Implementation of the model
Next step is the creation of the model to access news item table.
+List07 Format of rubricks_model generator
ruby script/generate rubricks_model [component_name] [model_name]
+List08 Generate model
> ruby script/generate rubricks_model news news_item
exists components/news
create components/news/news_item.rb
Add index controller
Create controller to view news by using generate command.
+List09 Format of rubricks_controller generator
ruby script/generate rubricks_controller [component_name] [controller_name] [action_name_list]
+List10 Add index controller
> ruby script/generate rubricks_controller news index main block
exists components/news
create components/news/index
create components/news/index/main.rhtml
create components/news/index/block.rhtml
create components/news/index_controller.rb
create components/news/index_helper.rb
Implementation of posting news
+List11 /components/news/post_controller.rb
class News::PostController < ApplicationController
define_page
uses_component_template_root
# Display news post form
def main
@news_items = News::NewsItem.new
end
# Save posted news to DB
def create
news_item = News::NewsItem.new(params[:news_item])
# Add user ID to news
news_item.rubricks_user_id = current_user.id
# Save posted news
if news_item.save
flash[:notice] = "Posted."
end
# Display news post form
render :action => 'main'
end
end
+List12 /components/news/post/main.rhtml
<h1>Post News</h1>
<%= @flash[:notice] if @flash[:notice] %>
<%= form_main_tag :url => {:action => 'create'} %>
<table style="width:100%">
<tr>
<th colspan=2>Posting Item</th>
</tr>
<tr>
<td style="width:20%;">Title</th>
<td style="width:80%;">
<%= text_field 'news_item', 'title', :size => 32 %>
</td>
</tr>
<tr>
<td>Article</td>
<td><%= text_area 'news_item', 'article', :cols => 70, :rows => 4 %></td>
</tr>
<tr>
<td style="padding-right:20px; text-align:right;" colspan=2>
<%= submit_tag "Post" %>
</td>
</tr>
</table>
<%= end_form_tag %>
Implementation of listing news
+List13 /components/news/index_controller.rb
class News::IndexController < ApplicationController
define_page
uses_component_template_root
# Display News List
def main
@pages, @news_items = paginate(
:'/news/news_item',
:per_page => 20,
:order => 'created_at DESC'
)
end
def block
end
end
+List14 /components/news/index_helper.rb
module News::IndexHelper
# Get poster's name
def news_author(news)
# Get guest name from general setting if posted by guest user.
# Get poster's name from DB if other case.
if news.rubricks_user_id == RubricksUser::GUEST_USER_ID
RubricksConfig.get('guest_display')
else
RubricksUser.find(news.rubricks_user_id).name
end
end
# Get formatted post date.
def news_publish_date(news)
news.created_at.strftime("%Y/%m/%d")
end
end
+List15 /components/news/index/main.rhtml
<h1>News List</h1>
<% for news_item in @news_items %>
<table border=1>
<tr>
<th colspan=2><%= news_item.title %></th>
</tr>
<tr>
<td><%= news_author(news_item) %></td>
<td><%= news_publish_date(news_item) %></td>
</tr>
<tr>
<td colspan=3><%= news_item.article %></td>
</tr>
</table>
<br>
<% end %>
<%= pagination_remote_links(@pages) %>
Add menu
Add menu by using rubricks_menu generator.
+List16 Format of rubricks_menu generator
ruby script/generate rubricks_menu [component_name] [controller_name] [action_name]
+List17 Add menu
> ruby script/generate rubricks_menu news index
created Menu item
Operation check
News component came to operate at least. Let's boot WEBrick and access.
Left problems
- Add news block
- Apply theme
- For making to several languages
- Make it distributable
Add news block
Add the block where has the title and updated date of news.
Implementation of news block
+List18 /components/news/index_controller.rb
class News::IndexController < ApplicationController
define_page
uses_component_template_root
# Display News List
def main
@pages, @news_items = paginate(
:'/news/news_item',
:per_page => 20,
:order => 'created_at DESC'
)
end
def block
@news_items = News::NewsItem.find(:all, :order => 'created_at DESC', :limit => 5)
end
end
+List19 /components/news/index/block.rhtml
<table>
<% @news_items.each do |news_item| %>
<tr>
<td><%= news_item.title %></td>
<td><%= news_publish_date(news_item) %></td>
</tr>
<% end %>
<tr>
<td colspan=2 >
<%= link_to_main hl("[_News_Title_List]"),:url => {:controller => '/news/index', :action => 'main'} %>
</td>
</tr>
</table>
Add news block
Add news block by using rubricks_block generator.
+List20 Format of rubricks_block generator
ruby script/generate rubricks_block [block_title] [component_name] [controller_name] [action_name]
+LIst21 Add news block
> ruby script/generate rubricks_block News news index block
created Block.
created Block views.
Apply theme
Rubricks has the theme that composes the screen design. All components can put in order by specifying the defined class. Please see the Design Guide?.
+List22 /components/news/post/main.rhtml
<div class="rubricks_general_frame_borderless">
<h1 class="rubricks_general_title_borderless">Post News</h1>
<%= @flash[:notice] if @flash[:notice] %>
<%= form_main_tag :url => {:action => 'create'} %>
<table class="rubricks_general_table1" style="width:100%">
<tr class="rubricks_general_table1_title">
<th class="rubricks_general_table1_cell_borderless" colspan=2>Posting Item</th>
</tr>
<tr class="rubricks_general_table1_even">
<td class="rubricks_general_table1_cell_bordered" style="width:20%;">Title</th>
<td class="rubricks_general_table1_cell_bordered" style="width:80%;">
<%= text_field 'news_item', 'title', :size => 32 %>
</td>
</tr>
<tr class="rubricks_general_table1_even">
<td class="rubricks_general_table1_cell_bordered">Article</td>
<td class="rubricks_general_table1_cell_bordered"><%= text_area 'news_item', 'article', :cols => 70, :rows => 4 %></td>
</tr>
<tr class="rubricks_general_table1_footer">
<td class="rubricks_general_table1_cell_borderless" style="padding-right:20px; text-align:right;" colspan=2>
<%= submit_tag "Post", :class => 'submit' %>
</td>
</tr>
</table>
<%= end_form_tag %>
</div>
For making to several languages
Rubricks has mechanism of the internationalization. The messages are defined in languages file, and write them at the view. Then, let's make title of news post internationalized at this tutorial. Please internationalize other messages similarly.
+List23 /components/news/languages/english.rb
module RubricksLanguage
def define_lang
@lang['_News_Title'] = 'News'
@lang['_News_Component_Description'] = ''
@lang['_News_Menu'] = 'News'
@lang['_News_Title_Post'] = 'News Post'
end
end
+List24 /components/news/languages/japanese.rb
module RubricksLanguage
def define_lang
@lang['_News_Title'] = 'News'
@lang['_News_Component_Description'] = ''
@lang['_News_Menu'] = 'News'
@lang['_News_Title_Post'] = 'ニュース投稿'
end
end
+List25 /components/news/post/main.rhtml
<div class="rubricks_general_frame_borderless">
<h1 class="rubricks_general_title_borderless"><%= hl('[_News_Title_Post]') %></h1>
<%= @flash[:notice] if @flash[:notice] %>
<%= form_main_tag :url => {:action => 'create'} %>
<table class="rubricks_general_table1" style="width:100%">
<tr class="rubricks_general_table1_title">
<th class="rubricks_general_table1_cell_borderless" colspan=2>Posting Item</th>
</tr>
<tr class="rubricks_general_table1_even">
<td class="rubricks_general_table1_cell_bordered" style="width:20%;">Title</th>
<td class="rubricks_general_table1_cell_bordered" style="width:80%;">
<%= text_field 'news_item', 'title', :size => 32 %>
</td>
</tr>
<tr class="rubricks_general_table1_even">
<td class="rubricks_general_table1_cell_bordered">Article</td>
<td class="rubricks_general_table1_cell_bordered"><%= text_area 'news_item', 'article', :cols => 70, :rows => 4 %></td>
</tr>
<tr class="rubricks_general_table1_footer">
<td class="rubricks_general_table1_cell_borderless" style="padding-right:20px; text-align:right;" colspan=2>
<%= submit_tag "Post", :class => 'submit' %>
</td>
</tr>
</table>
<%= end_form_tag %>
</div>
Make it distributable
When the component is distributed, you may make some files as follow and compress them into the RZIP.
- _install/component_info.rb
- _install/installation_script.rb
- _install/db/001_news_schema.rb
- _install/images/news.gif
- _install/images/news_active.gif
Component information
About details, please refer to the Component Infomation?.
+List26 Format of rubricks_component_info generator
ruby script/generate rubricks_component_info [component_name]
List27 Make component information
> ruby script/generate rubricks_component_info news
exists components/news
exists components/news/_install
exists components/news/_install/db
overwrite components/news/_install/component_info.rb? [Ynaq] a
forcing rubricks_component_info
force components/news/_install/component_info.rb
Make schema
It follows the rule of Migration.
+List28 /components/news/_install/db/001_news_schema.rb
class NewsSchema < ActiveRecord::Migration
def self.up
create_table "news_items", :force => true do |t|
t.column "title", :string, :limit => 192, :default => "", :null => false
t.column "rubricks_user_id", :integer, :limit => 10, :default => 0, :null => false
t.column "article", :text, :default => "", :null => false
t.column "created_at", :datetime, :null => false
end
end
def self.down
drop_table :news_items
end
end
Make rzip file
Make rzip using rzip script. "news.rzip" will be at current directory.
+List29 Make rzip file
> ruby script/rzip news
Install
Let's try to install news component as follow.
- Back up news directory
- Login as admin and uninstall current news component
- Put news.rzip into RAILS_ROOT/install
- Login as admin and install news.rzip
Appendix
Attachments
- component_development_tutorial_en_001.png (8.8 kB) - added by uta on 10/30/06 19:31:21.
- component_development_tutorial_en_002.png (34.7 kB) - added by uta on 10/30/06 19:31:25.
