SlideShare a Scribd company logo
1 of 114
Download to read offline
百⼤大媒體網站
從 wordpress 到 rails 的
⼤大⼩小事
Ronald Hsu (hothero)
Technical Director, backer-founder.com
http://blog.hothero.org
@hothero
slide: http://backme.tw/ref/wp-rails
What’s the talk about?
• No diabolic tricks and wicked craft
• A year experience sharing
• Goes through our practice
• You will know more gems
• You will know what media websites care about most
• You will know how to handle larger traffic for media websites
• Nothing funny
What’s the talk about?
• No diabolic tricks and wicked craft
• A year experience sharing
• Goes through our practice
• You will know more gems
• You will know what media websites care about most
• You will know how to handle larger traffic for media websites
• Nothing funny
Backer-Founder
• First and leading crowdfunding consulting
agency in Taiwan
• Has carried out 40 projects to domestic and
abroad
• Raised over $7 million in 11 months since its
establishment in October 2014.
Backer-Founder
Backer-Founder
Backer-Founder
http://xkcd.com/323/
Backer-Founder
TNL
• A group of people who are dissatisfied with the
existing media environment and want to make a
difference.
• We aspire to build a media that provides not only
facts, but also diverse perspectives.
X
X
Our Progress & Goal
Backend

+

DB Schema
Frontend
Wordpress
• WordPress is a free and open-source content
management system (CMS) based on PHP and
MySQL.
• Features include a plugin architecture and a
template system.
• WordPress was used by more than 23.3% of the
top 10 million websites as of January 2015.
• Initial release May 27, 2003 (12 years ago)
http://www.wikiwand.com/en/WordPress
Wordpress
Wordpress
Wordpress
Wordpress
Wordpress
Wordpress
• More than 30000 commits
• 23+ contributors
• 127+ version releases
• Nearly 500,000 lines of code, which contains nearly
300,000 lines of php code
https://github.com/wordpress/wordpress
But why?
Three Main Issues
Customization

Difficulty
Few Wordpress 

Developer in T.W.
Performance
Issue
Three Main Issues
Customization

Difficulty
Few Wordpress 

Developer in T.W.
Performance
Issue
Three Main Issues
Customization

Difficulty
Few Wordpress 

Developer in T.W.
Performance
Issue
Three Main Issues
Customization

Difficulty
Few Wordpress 

Developer in T.W.
Performance
Issue
Three Main Issues
Customization

Difficulty
Few Wordpress 

Developer in T.W.
Performance
Issue
So...we start to use rails
Our Progress & Goal
Backend

+

DB Schema
Frontend
Wordpress
DB Schema
• posts, pages, custom
post types,
attachments, links,
navigation menu items,
categories, tags,
custom taxonomies,
taxonomy terms, post
metadata, widgets,
options, users,
hardcoded content,
third party content
http://goo.gl/Tbbpfr
Wordpress Structure
posts
pages
custom post types
post metadata
options
categories
users
attachments
taxonomy terms
tags
navigation menu items
widgets
custom taxonomieswp_posts wp_terms
wp_term_
taxonomy
wp_post_
meta
wp_optio
ns
wp_users
wp_links
links
Wordpress Structure
posts
pages
custom post types
post metadata
options
categories
users
attachments
taxonomy terms
tags
navigation menu items
widgets
custom taxonomieswp_posts wp_terms
wp_term_
taxonomy
wp_post_
meta
wp_optio
ns
wp_users
wp_links
links
Post

Editing
Tag/

Category
General in Post Editing
has_many
has_many
It means static
content
Post
Attachment
Revision
Page
posts
pages
custom post
attachments
navigation menu
wp_posts
But in wordpress …
wp_posts
revisions
attachments
nav menu items
But in wordpress …
• All of those we mentioned before are in
only one table.
• Also include custom post types, links,
navigation menu items!!!
post_type
•post
•page
•revision
•attachment
•nav_menu_item
•…
In Rails
1 has_many :attachments, -> { where(post_type:
2 "attachment") },
3 foreign_key:
4 "post_parent",
5 class_name:
6 "Post"
7 has_many :revisions, -> { where(post_type:
8 "revision") },
9 foreign_key:
10 "post_parent",
11 class_name: "Post"
posts
pages
custom post
types
attachments
navigation menu
items
wp_posts
Tag / Category
categories
taxonomy terms
tags
wp_terms
Wordpress DB Schema
In practice
• Category
• wp_term_taxonomy.taxonomy: category
• wp_terms.name: Politics
• Tag
• wp_term_taxonomy.taxonomy: post_tag
• wp_terms.name: FireChat
In Rails1 # models/w_post.rb
2 has_many :w_terms, through: :
3 w_term_relationships, foreign_key: "term_id"
4 has_many :w_term_relationships, foreign_key:
5 "object_id"
6 has_many :tags,
7 -> { where("#{WTermTaxonomy.table_name}.taxonomy =
'post_tag'") },
9 through: :w_terms, source: :w_term_taxonomy,
10 class_name: "WTerm"
11 has_many :categories,
12 -> { where("#{WTermTaxonomy.table_name}.taxonomy =
'category'") },
14 through: :w_terms, source: :w_term_taxonomy,
15 class_name: "WTerm"
16
17 # models/w_term_relationship.rb
18 belongs_to :w_term_taxonomy, foreign_key:
19 "term_taxonomy_id"
20 has_one :w_term, :through => :w_term_taxonomy
In Rails1 # models/w_post.rb
2 has_many :w_terms, through: :
3 w_term_relationships, foreign_key: "term_id"
4 has_many :w_term_relationships, foreign_key:
5 "object_id"
6 has_many :tags,
7 -> { where("#{WTermTaxonomy.table_name}.taxonomy =
'post_tag'") },
9 through: :w_terms, source: :w_term_taxonomy,
10 class_name: "WTerm"
11 has_many :categories,
12 -> { where("#{WTermTaxonomy.table_name}.taxonomy =
'category'") },
14 through: :w_terms, source: :w_term_taxonomy,
15 class_name: "WTerm"
16
17 # models/w_term_relationship.rb
18 belongs_to :w_term_taxonomy, foreign_key:
19 "term_taxonomy_id"
20 has_one :w_term, :through => :w_term_taxonomy
If you need to know more…
• http://codex.wordpress.org/Database_Description
• http://code.tutsplus.com/tutorials/understanding-
and-working-with-data-in-wordpress--cms-20567
And we made a gem
• wpdb_activerecord: https://github.com/hothero/
wpdb_activerecord
• It’s a ORM wrapper for the WordPress database,
using ActiveRecord.
wpdb_activerecord
1 # Gemfile
2 gem "wpdb_activerecord"
3
4 # Post
5 WPDB::Post.all # Get all posts
6 @post = WPDB::Post.find(75)
7 @post.tags
8 @post.attachments # No matter what type
9 @post.revisions
10 @post.author
11
12 # Term
13 WPDB::Term.tag # get all tags
14 WPDB::Term.category # get all categories
wpdb_activerecord -
advanced
1 # config/wpdb_activerecord.yml
2 WPDB_PREFIX: "cgjbugpbs_"
# the table of WPDB::Post is cgjbugpbs_posts, not wp_posts
4 WPDB_USER_CLASS: "WUser"
5
6 # models/w_user.rb
7 class WUser < WPDB::User
8 def hello
9 puts "world"
10 end
11 end
12
13 # usage
14 @author = WPDB::Post.find(25).author
15 @author.class_name # will get WUser, not WPDB::
16 User
17 @author.hello # world
wpdb - installation
wpdb - installation
wpdb - installation
wpdb - installation
wpdb - installation
wpdb -usage
wpdb -usage
wpdb -usage
wpdb -usage
wpdb -usage
wpdb -usage
wpdb -usage
wpdb -usage
Our Progress & Goal
Backend

+

DB Schema
Frontend
wpdb_activerecord
Server Side
Visitors
i0.wp.com/…
Cloudflare - Page Rules
And we done
pcu 6000 ⬆ NT$5000 ⬇
Monthly Data
• 7 million pageview ⬆
• 1.2 hundred million
requests ⬆
• 4 million UU ⬆
2015/02
Our Progress & Goal
Backend

+

DB Schema
Frontend
CMS Admin
Edit Flow
Media Gallery
Globalize
Cronjob
editflow.org
• Edit Flow gives you custom statuses, a calendar, editorial comments, and
more, all to make it much easier for your team to collaborate within WordPress.
• Calendar
• Custom Statuses
• Editorial Comments
• Editorial Metadata
• Notifications
• Story Budget
• User Groups
Editor Structure
Author
Senior

Editor
Chief

Editor
ready to 

review
ready to 

check
publish
Normal Flow
Editor
Edit Flow
Calendar
Custom Statuses
Notifications
Editorial Comments
• Threaded commenting in the admin for private
discussion between writers and editors.
Editorial Comments
• Use this gem: acts_as_commentable
• Polymorphic Associations
1 commentable = Post.create
2 comment = commentable.comments.create
3 comment.title = "First comment."
4 comment.comment = "This is the first comment."
5 comment.save
What’s the Polymorphic
Associations
• Assume a situation
• An employee has many pictures
• A Product has many pictures
• And each of those pictures have owned
information detail.
What’s the Polymorphic
Associations
• In general: two relationship tables to associate objects
and pictures
Employee
Product
Employee_

Relationship
employee_id
picture_id
Product_

Relationship
product_id
picture_id
Picture
What’s the Polymorphic
Associations
• Level up: an additional table to associate
Employee
Product
Object

Relationship
object_id
picture_id
Picture
What’s the Polymorphic
Associations
• Polymorphic Associations
Employee
Product
Picture
imageable_id
imageable_type
will be:
* Employee
* Product
What’s the Polymorphic
Associations
• Practice in Rails.
What’s the Polymorphic
Associations
• In migration
editflow.org
• Edit Flow gives you custom statuses, a calendar, editorial comments, and
more, all to make it much easier for your team to collaborate within WordPress.
• Calendar
• Custom Statuses
• Editorial Comments
• Editorial Metadata
• Notifications
• Story Budget
• User Groups
Story Budget
• View all of your upcoming posts in a more traditional story
budget view, and hit the print button to take it to your
planning meeting.
Search Design In General
• In general, we maybe use many conditions to match different
situation. 1 def search
2 @posts = Post.send(params[:scope])
3 if params.key?(:author_id)
4 @posts = @posts.where(author_id: params[:
5 author_id])
6 end
7 if params.key?(:post_type)
8 @posts = @posts.where(post_type: params[:
9 post_type])
10 end
11 if params.key?(:start_date) || params.key?(:
12 end_date)
13 @posts = @posts.where(updated_at: params[:
14 start_date]..params[:end_date])
15 end
16 # ...
17 end
Search Design In General
• In general, we maybe use many conditions to match different
situation. 1 def search
2 @posts = Post.send(params[:scope])
3 if params.key?(:author_id)
4 @posts = @posts.where(author_id: params[:
5 author_id])
6 end
7 if params.key?(:post_type)
8 @posts = @posts.where(post_type: params[:
9 post_type])
10 end
11 if params.key?(:start_date) || params.key?(:
12 end_date)
13 @posts = @posts.where(updated_at: params[:
14 start_date]..params[:end_date])
15 end
16 # ...
17 end
https://github.com/
activerecord-hackery/
ransack
Ransack - View Helper1 <%= search_form_for @q do |f| %>
2 # Search if the name field contains...
3 <%= f.label :name_cont %>
4 <%= f.search_field :name_cont %>
5
6 # Search if an associated articles.title
7 starts with...
8 <%= f.label :articles_title_start %>
9 <%= f.search_field :articles_title_start %>
10
11 # Attributes may be chained. Search multiple
12 attributes for one value...
13 <%= f.label :
14 name_or_description_or_email_or_articles_t
15 itle_cont %>
16 <%= f.search_field :
17 name_or_description_or_email_or_articles_t
18 itle_cont %>
19
20 <%= f.submit %>
21 <% end %>
name_cont
Ransack - View Helper1 <%= search_form_for @q do |f| %>
2 # Search if the name field contains...
3 <%= f.label :name_cont %>
4 <%= f.search_field :name_cont %>
5
6 # Search if an associated articles.title
7 starts with...
8 <%= f.label :articles_title_start %>
9 <%= f.search_field :articles_title_start %>
10
11 # Attributes may be chained. Search multiple
12 attributes for one value...
13 <%= f.label :
14 name_or_description_or_email_or_articles_t
15 itle_cont %>
16 <%= f.search_field :
17 name_or_description_or_email_or_articles_t
18 itle_cont %>
19
20 <%= f.submit %>
21 <% end %>
articles_title_start
Ransack - View Helper1 <%= search_form_for @q do |f| %>
2 # Search if the name field contains...
3 <%= f.label :name_cont %>
4 <%= f.search_field :name_cont %>
5
6 # Search if an associated articles.title
7 starts with...
8 <%= f.label :articles_title_start %>
9 <%= f.search_field :articles_title_start %>
10
11 # Attributes may be chained. Search multiple
12 attributes for one value...
13 <%= f.label :
14 name_or_description_or_email_or_articles_t
15 itle_cont %>
16 <%= f.search_field :
17 name_or_description_or_email_or_articles_t
18 itle_cont %>
19
20 <%= f.submit %>
21 <% end %>
name_or_description_or_email
_or_articles_title_cont
Ransack - Controller
1 def index
2 @q = Person.ransack(params[:q])
3 @people = @q.result(distinct: true)
4 end
Ransack - Controller
1 def index
2 @q = Person.ransack(params[:q])
3 @people = @q.result(distinct: true)
4 end
In Practice
q[status_scope]
q[author_id_eq]
q[post_type_eq]
q[author_name_cont]
q[updated_at_gteq] - q[updated_at_lteq]
editflow.org
• Edit Flow gives you custom statuses, a calendar, editorial comments, and
more, all to make it much easier for your team to collaborate within WordPress.
• Calendar
• Custom Statuses
• Editorial Comments
• Editorial Metadata
• Notifications
• Story Budget
• User Groups
User Groups
• Keep your users organized by department or function.
Editor Structure
Author
Senior

Editor
Chief

Editor
Editor
Maybe DB Schema
User Author Editor Admin
or
User
user_type
STI (Single-table inheritance)
class User < ActiveRecord::Base
end
class Author < User
enum role: [:normal, :blogger]
def publish # ex: only author can use
end
end
class Editor < User
enum role: [:editor, :senior_editor, :chief]
end
class Admin < User
end
User
type
type: rails reserved word
STI with Priority Problem
• STI is unfit for priority feature.
• Chief Editor > Senior Editor > Editor > Author
• Enum-design is more fit.
1 class User < ActiveRecord::Base
2 enum role:
[:normal, :blogger, :editor, :senior_editor, :chief]
4 end
Other parts
• Except edit-flow, there are some more features
• takeover & editing lock
• media gallery
• globalize
A situation
Author
Editor
wanna edit
takeover & editing lock
• Use this gem: message_bus
• MessageBus implements a Server to Server
channel protocol and Server to Web Client protocol
(using polling or long-polling)
• We use current_editor_id field as lock in post.
• Subscribe a channel for takeover when start editing in front-
end.
• Publish a message to the channel when someone wanna
edit.
takeover & editing lock
1 MessageBus.start();
2 MessageBus.callbackInterval = 500;
3 MessageBus.subscribe("/posts/<%= @post.id %>/takeover/request",
4 function(msg){
5 unlock_post_and_auto_save();
6 window.location = "<%= posts_path %>";
7 });
1 MessageBus.publish(“/posts/#{post.id}/takeover/request”,
username: user.name)
Channel
Media Gallery
Media Gallery - Tricks
Browsers don't allow file
uploads via XMLHttpRequest
(aka XHR) for security reasons.
General in jQuery
• Hijack the forms submit event to execute our custom
iFrame-method function
• Submit the form to the iFrame normal-style (non-AJAX)
• Copy the response content from the iFrame back into the
parent window.
http://www.alfajango.com/blog/ajax-file-uploads-with-the-iframe-method/
remotipart
• Use this gem: remotipart
• Remotipart is a Ruby on Rails gem enabling AJAX file
uploads with jQuery in Rails 3 and Rails 4 remote forms.
1 # Gemfile
2 gem "remotipart"
3
4 # js
5 //= require jquery.remotipart
Globalize
globalize
• Use this gem: globalize
• Each locale have their owned tags & revisions
1 # config/initializers/post_translation.rb
2 Post::Translation.module_eval do
3 acts_as_ordered_taggable
4 has_paper_trail only: [:content, :title, :
5 excerpt]
6 end
Mobile APP
• http://apps.thenewslens.com/
API Design In General
class ApiController < ApplicationController
def all
# get review & news type post
case params[:post_type]
when "new" # latest
when "hot" # hot
end
end
def review
case params[:post_type]
when "new"
when "hot"
end
end
end
def news
case params[:post_type]
when "new"
when "hot"
end
end
has_scope
• Use this gem: has_scope
• In model
1 class Graduation < ActiveRecord::Base
2 scope :featured, -> { where(:featured => true)
3 }
4 scope :by_degree, -> degree { where(:degree =>
5 degree) }
6 scope :by_period, -> started_at, ended_at {
7 where("started_at = ? AND ended_at = ?",
8 started_at, ended_at) }
9 end
has_scope
• You can use those named scopes as filters by declaring
them on your controller and just need to call apply_scopes
to an specific resource.
1 class GraduationsController <
2 ApplicationController
3 has_scope :featured, :type => :boolean
4 has_scope :by_degree
5 has_scope :by_period, :using => [:started_at,
6 :ended_at], :
7 type => :hash
8
9 def index
10 @graduations = apply_scopes(Graduation).all
11 end
12 end
has_scope
• You can use those named scopes as filters by declaring
them on your controller and just need to call apply_scopes
to an specific resource.
1 class GraduationsController <
2 ApplicationController
3 has_scope :featured, :type => :boolean
4 has_scope :by_degree
5 has_scope :by_period, :using => [:started_at,
6 :ended_at], :
7 type => :hash
8
9 def index
10 @graduations = apply_scopes(Graduation).all
11 end
12 end
/graduations?featured=true
has_scope
• You can use those named scopes as filters by declaring
them on your controller and just need to call apply_scopes
to an specific resource.
1 class GraduationsController <
2 ApplicationController
3 has_scope :featured, :type => :boolean
4 has_scope :by_degree
5 has_scope :by_period, :using => [:started_at,
6 :ended_at], :
7 type => :hash
8
9 def index
10 @graduations = apply_scopes(Graduation).all
11 end
12 end
/graduations?by_period[started_at]=20100701&by_period[ended_at]=20101013
has_scope
• You can use those named scopes as filters by declaring
them on your controller and just need to call apply_scopes
to an specific resource.
1 class GraduationsController <
2 ApplicationController
3 has_scope :featured, :type => :boolean
4 has_scope :by_degree
5 has_scope :by_period, :using => [:started_at,
6 :ended_at], :
7 type => :hash
8
9 def index
10 @graduations = apply_scopes(Graduation).all
11 end
12 end
/graduations?featured=true&by_degree=phd
Tragedy at the admin theme
Find out a good design
which have smooth
operating and fancy
turbolinks & pjax
• Instead of letting the browser recompile the JavaScript and
CSS between each page change, it keeps the current
page instance alive and replaces only the body (or parts
of) and the title in the head.
• Same advantages: good user experience, reduce
bandwidth and server cost
• In particular with Rails:
• more detail: http://goo.gl/Lx7mHk
# Gemfile
gem “turbolinks”
# app/assets/javascripts/
application.js
//= require tubolinks
$.pjax({url:’authors’,
container:’#main’})
if request.headers[‘X-PJAX’]
render:layout
end
rails-gem-list
• A workman must sharpen his tools if he is to do his work
well / ⼯工欲善其事,必先利其器
• We’ve done a gem: rails-gem-list
• You can go through rails-gem-list to know how to construct
your project architecture and DB schema. Just like
• acts_as_taggable
• ransack
• …
rails-gem-list
• A workman must sharpen his tools if he is to do his work
well / ⼯工欲善其事,必先利其器
• We’ve done a gem: rails-gem-list
• You can go through rails-gem-list to know how to construct
your project architecture and DB schema. Just like
• acts_as_taggable
• ransack
• …
Finally
• If you want to do a media website, you can follow edit-flow to
manage your posts.
• If your WordPress website becomes larger and larger, you can
rewrite your front-end with Rails.
• Please don’t even think to transfer the whole site from WordPress to
Rails.
• After we had spoken many topics, there are still two main parts we
didn’t present
• Server Architecture
• Data Migration
Special Thanks
X
@dlackty @ymowov
@baojjeu @st0012 @nanasyu @eugg @chentyphoon @randyhsieh @fufukwang
Contact me: hothero@backer-founder.com

More Related Content

What's hot

Even faster web sites
Even faster web sitesEven faster web sites
Even faster web sitesFelipe Lavín
 
Modular HTML & CSS Workshop
Modular HTML & CSS WorkshopModular HTML & CSS Workshop
Modular HTML & CSS WorkshopShay Howe
 
WordPress Themes Demystified
WordPress Themes DemystifiedWordPress Themes Demystified
WordPress Themes DemystifiedChris Burgess
 
CSS3: Are you experienced?
CSS3: Are you experienced?CSS3: Are you experienced?
CSS3: Are you experienced?Denise Jacobs
 
Introduction to HTML5 and CSS3 (revised)
Introduction to HTML5 and CSS3 (revised)Introduction to HTML5 and CSS3 (revised)
Introduction to HTML5 and CSS3 (revised)Joseph Lewis
 
Arizona WP - Building a WordPress Theme
Arizona WP - Building a WordPress ThemeArizona WP - Building a WordPress Theme
Arizona WP - Building a WordPress Themecertainstrings
 
Wordpress for newbies
Wordpress for newbiesWordpress for newbies
Wordpress for newbiestjessee
 
Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64Alfresco Software
 
Drupal Theme Development - DrupalCon Chicago 2011
Drupal Theme Development - DrupalCon Chicago 2011Drupal Theme Development - DrupalCon Chicago 2011
Drupal Theme Development - DrupalCon Chicago 2011Ryan Price
 
WordPress for Libraries PreConference Workshop
WordPress for Libraries PreConference WorkshopWordPress for Libraries PreConference Workshop
WordPress for Libraries PreConference WorkshopPolly Farrington
 
NewBCamp09: Turning your design into a WordPress Theme
NewBCamp09: Turning your design into a WordPress ThemeNewBCamp09: Turning your design into a WordPress Theme
NewBCamp09: Turning your design into a WordPress ThemeAdam Darowski
 
Abstractions: Fringe Accessibility
Abstractions: Fringe AccessibilityAbstractions: Fringe Accessibility
Abstractions: Fringe AccessibilityAdrian Roselli
 
Choose Your Own Adventure: SEO For Web Developers | Unified Diff
Choose Your Own Adventure: SEO For Web Developers | Unified DiffChoose Your Own Adventure: SEO For Web Developers | Unified Diff
Choose Your Own Adventure: SEO For Web Developers | Unified DiffSteve Morgan
 
建立前端開發團隊 - 2011 中華電信訓練所版
建立前端開發團隊 - 2011 中華電信訓練所版建立前端開發團隊 - 2011 中華電信訓練所版
建立前端開發團隊 - 2011 中華電信訓練所版Joseph Chiang
 

What's hot (20)

Even faster web sites
Even faster web sitesEven faster web sites
Even faster web sites
 
Modular HTML & CSS Workshop
Modular HTML & CSS WorkshopModular HTML & CSS Workshop
Modular HTML & CSS Workshop
 
WordPress Themes Demystified
WordPress Themes DemystifiedWordPress Themes Demystified
WordPress Themes Demystified
 
CSS3: Are you experienced?
CSS3: Are you experienced?CSS3: Are you experienced?
CSS3: Are you experienced?
 
Introduction to HTML5 and CSS3 (revised)
Introduction to HTML5 and CSS3 (revised)Introduction to HTML5 and CSS3 (revised)
Introduction to HTML5 and CSS3 (revised)
 
Arizona WP - Building a WordPress Theme
Arizona WP - Building a WordPress ThemeArizona WP - Building a WordPress Theme
Arizona WP - Building a WordPress Theme
 
HTML5 & CSS3 Flag
HTML5 & CSS3 FlagHTML5 & CSS3 Flag
HTML5 & CSS3 Flag
 
Meta tag creation
Meta tag creationMeta tag creation
Meta tag creation
 
Hello Drupal
Hello DrupalHello Drupal
Hello Drupal
 
Wordpress for newbies
Wordpress for newbiesWordpress for newbies
Wordpress for newbies
 
Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64
 
IBM Connection - customize it, #dd13
IBM Connection - customize it, #dd13IBM Connection - customize it, #dd13
IBM Connection - customize it, #dd13
 
Chapter11
Chapter11Chapter11
Chapter11
 
Drupal Theme Development - DrupalCon Chicago 2011
Drupal Theme Development - DrupalCon Chicago 2011Drupal Theme Development - DrupalCon Chicago 2011
Drupal Theme Development - DrupalCon Chicago 2011
 
WordPress for Libraries PreConference Workshop
WordPress for Libraries PreConference WorkshopWordPress for Libraries PreConference Workshop
WordPress for Libraries PreConference Workshop
 
NewBCamp09: Turning your design into a WordPress Theme
NewBCamp09: Turning your design into a WordPress ThemeNewBCamp09: Turning your design into a WordPress Theme
NewBCamp09: Turning your design into a WordPress Theme
 
Abstractions: Fringe Accessibility
Abstractions: Fringe AccessibilityAbstractions: Fringe Accessibility
Abstractions: Fringe Accessibility
 
Chapter5
Chapter5Chapter5
Chapter5
 
Choose Your Own Adventure: SEO For Web Developers | Unified Diff
Choose Your Own Adventure: SEO For Web Developers | Unified DiffChoose Your Own Adventure: SEO For Web Developers | Unified Diff
Choose Your Own Adventure: SEO For Web Developers | Unified Diff
 
建立前端開發團隊 - 2011 中華電信訓練所版
建立前端開發團隊 - 2011 中華電信訓練所版建立前端開發團隊 - 2011 中華電信訓練所版
建立前端開發團隊 - 2011 中華電信訓練所版
 

Similar to 2015 rubyconf - 百大媒體網站從 Wordpress 到 Rails 的大小事

Extending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHPExtending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHPrandyhoyt
 
Things you should know about WordPress (but were always too afraid to ask): W...
Things you should know about WordPress (but were always too afraid to ask): W...Things you should know about WordPress (but were always too afraid to ask): W...
Things you should know about WordPress (but were always too afraid to ask): W...Michael McNeill
 
Wordpress beyond blogging
Wordpress beyond bloggingWordpress beyond blogging
Wordpress beyond bloggingJulien Minguely
 
Choosing the Right WordPress Theme
Choosing the Right WordPress ThemeChoosing the Right WordPress Theme
Choosing the Right WordPress ThemeChris Burgess
 
NEPA BlogCon 2013 - WordPress Customization & Security
NEPA BlogCon 2013 - WordPress Customization & SecurityNEPA BlogCon 2013 - WordPress Customization & Security
NEPA BlogCon 2013 - WordPress Customization & SecurityMichelle Davies (Hryvnak)
 
WordPress Customization and Security
WordPress Customization and SecurityWordPress Customization and Security
WordPress Customization and SecurityJoe Casabona
 
WordPress
WordPressWordPress
WordPressrisager
 
WordPress Intermediate Workshop
WordPress Intermediate WorkshopWordPress Intermediate Workshop
WordPress Intermediate WorkshopThe Toolbox, Inc.
 
Starting WordPress Theme Review
Starting WordPress Theme ReviewStarting WordPress Theme Review
Starting WordPress Theme ReviewCatch Themes
 
WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1Yoav Farhi
 
WordCamp Ireland - 40 tips for WordPress Optimization
WordCamp Ireland - 40 tips for WordPress OptimizationWordCamp Ireland - 40 tips for WordPress Optimization
WordCamp Ireland - 40 tips for WordPress OptimizationJoost de Valk
 
The WordPress University 2012
The WordPress University 2012The WordPress University 2012
The WordPress University 2012Stephanie Leary
 
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to DevelopmentWordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to DevelopmentEvan Mullins
 
How to create a WordPress Site
How to create a WordPress Site How to create a WordPress Site
How to create a WordPress Site MuhammadUsaid2
 
From WordPress With Love
From WordPress With LoveFrom WordPress With Love
From WordPress With LoveUp2 Technology
 

Similar to 2015 rubyconf - 百大媒體網站從 Wordpress 到 Rails 的大小事 (20)

Extending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHPExtending & Scaling | Dallas PHP
Extending & Scaling | Dallas PHP
 
Things you should know about WordPress (but were always too afraid to ask): W...
Things you should know about WordPress (but were always too afraid to ask): W...Things you should know about WordPress (but were always too afraid to ask): W...
Things you should know about WordPress (but were always too afraid to ask): W...
 
File Upload 2015
File Upload 2015File Upload 2015
File Upload 2015
 
Wordpress beyond blogging
Wordpress beyond bloggingWordpress beyond blogging
Wordpress beyond blogging
 
WordPress Complete Tutorial
WordPress Complete TutorialWordPress Complete Tutorial
WordPress Complete Tutorial
 
Choosing the Right WordPress Theme
Choosing the Right WordPress ThemeChoosing the Right WordPress Theme
Choosing the Right WordPress Theme
 
&lt;?php + WordPress
&lt;?php + WordPress&lt;?php + WordPress
&lt;?php + WordPress
 
NEPA BlogCon 2013 - WordPress Customization & Security
NEPA BlogCon 2013 - WordPress Customization & SecurityNEPA BlogCon 2013 - WordPress Customization & Security
NEPA BlogCon 2013 - WordPress Customization & Security
 
WordPress Customization and Security
WordPress Customization and SecurityWordPress Customization and Security
WordPress Customization and Security
 
WordPress
WordPressWordPress
WordPress
 
WordPress Intermediate Workshop
WordPress Intermediate WorkshopWordPress Intermediate Workshop
WordPress Intermediate Workshop
 
Starting WordPress Theme Review
Starting WordPress Theme ReviewStarting WordPress Theme Review
Starting WordPress Theme Review
 
WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1WordPress Developers Israel Meetup #1
WordPress Developers Israel Meetup #1
 
WordCamp Ireland - 40 tips for WordPress Optimization
WordCamp Ireland - 40 tips for WordPress OptimizationWordCamp Ireland - 40 tips for WordPress Optimization
WordCamp Ireland - 40 tips for WordPress Optimization
 
The WordPress University 2012
The WordPress University 2012The WordPress University 2012
The WordPress University 2012
 
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to DevelopmentWordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
 
How to create a WordPress Site
How to create a WordPress Site How to create a WordPress Site
How to create a WordPress Site
 
WordPress Workshop
WordPress WorkshopWordPress Workshop
WordPress Workshop
 
The WordPress Way
The WordPress WayThe WordPress Way
The WordPress Way
 
From WordPress With Love
From WordPress With LoveFrom WordPress With Love
From WordPress With Love
 

More from Ronald Hsu

202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUP202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUPRonald Hsu
 
202104 technical challenging and our solutions - golang taipei
202104   technical challenging and our solutions - golang taipei202104   technical challenging and our solutions - golang taipei
202104 technical challenging and our solutions - golang taipeiRonald Hsu
 
Monolithic to microservices
Monolithic to microservicesMonolithic to microservices
Monolithic to microservicesRonald Hsu
 
What we learnt at carousell tw for golang gathering #31
What we learnt at carousell tw for golang gathering #31What we learnt at carousell tw for golang gathering #31
What we learnt at carousell tw for golang gathering #31Ronald Hsu
 
Google map slide
Google map slideGoogle map slide
Google map slideRonald Hsu
 
Inspector&j query slide
Inspector&j query slideInspector&j query slide
Inspector&j query slideRonald Hsu
 
軟體測試效能評估(By ronald)
軟體測試效能評估(By ronald)軟體測試效能評估(By ronald)
軟體測試效能評估(By ronald)Ronald Hsu
 

More from Ronald Hsu (7)

202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUP202107 - Orion introduction - COSCUP
202107 - Orion introduction - COSCUP
 
202104 technical challenging and our solutions - golang taipei
202104   technical challenging and our solutions - golang taipei202104   technical challenging and our solutions - golang taipei
202104 technical challenging and our solutions - golang taipei
 
Monolithic to microservices
Monolithic to microservicesMonolithic to microservices
Monolithic to microservices
 
What we learnt at carousell tw for golang gathering #31
What we learnt at carousell tw for golang gathering #31What we learnt at carousell tw for golang gathering #31
What we learnt at carousell tw for golang gathering #31
 
Google map slide
Google map slideGoogle map slide
Google map slide
 
Inspector&j query slide
Inspector&j query slideInspector&j query slide
Inspector&j query slide
 
軟體測試效能評估(By ronald)
軟體測試效能評估(By ronald)軟體測試效能評估(By ronald)
軟體測試效能評估(By ronald)
 

Recently uploaded

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...amber724300
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentMahmoud Rabie
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...itnewsafrica
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Nikki Chapple
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsYoss Cohen
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Karmanjay Verma
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 

Recently uploaded (20)

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career Development
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
Microsoft 365 Copilot: How to boost your productivity with AI – Part two: Dat...
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platforms
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 

2015 rubyconf - 百大媒體網站從 Wordpress 到 Rails 的大小事

  • 1. 百⼤大媒體網站 從 wordpress 到 rails 的 ⼤大⼩小事 Ronald Hsu (hothero) Technical Director, backer-founder.com http://blog.hothero.org @hothero slide: http://backme.tw/ref/wp-rails
  • 2. What’s the talk about? • No diabolic tricks and wicked craft • A year experience sharing • Goes through our practice • You will know more gems • You will know what media websites care about most • You will know how to handle larger traffic for media websites • Nothing funny
  • 3. What’s the talk about? • No diabolic tricks and wicked craft • A year experience sharing • Goes through our practice • You will know more gems • You will know what media websites care about most • You will know how to handle larger traffic for media websites • Nothing funny
  • 4. Backer-Founder • First and leading crowdfunding consulting agency in Taiwan • Has carried out 40 projects to domestic and abroad • Raised over $7 million in 11 months since its establishment in October 2014.
  • 9. TNL • A group of people who are dissatisfied with the existing media environment and want to make a difference. • We aspire to build a media that provides not only facts, but also diverse perspectives.
  • 10. X
  • 11. X
  • 12. Our Progress & Goal Backend
 +
 DB Schema Frontend
  • 13. Wordpress • WordPress is a free and open-source content management system (CMS) based on PHP and MySQL. • Features include a plugin architecture and a template system. • WordPress was used by more than 23.3% of the top 10 million websites as of January 2015. • Initial release May 27, 2003 (12 years ago) http://www.wikiwand.com/en/WordPress
  • 19. Wordpress • More than 30000 commits • 23+ contributors • 127+ version releases • Nearly 500,000 lines of code, which contains nearly 300,000 lines of php code https://github.com/wordpress/wordpress
  • 21. Three Main Issues Customization
 Difficulty Few Wordpress 
 Developer in T.W. Performance Issue
  • 22. Three Main Issues Customization
 Difficulty Few Wordpress 
 Developer in T.W. Performance Issue
  • 23. Three Main Issues Customization
 Difficulty Few Wordpress 
 Developer in T.W. Performance Issue
  • 24. Three Main Issues Customization
 Difficulty Few Wordpress 
 Developer in T.W. Performance Issue
  • 25. Three Main Issues Customization
 Difficulty Few Wordpress 
 Developer in T.W. Performance Issue
  • 26. So...we start to use rails
  • 27. Our Progress & Goal Backend
 +
 DB Schema Frontend
  • 28. Wordpress DB Schema • posts, pages, custom post types, attachments, links, navigation menu items, categories, tags, custom taxonomies, taxonomy terms, post metadata, widgets, options, users, hardcoded content, third party content http://goo.gl/Tbbpfr
  • 29. Wordpress Structure posts pages custom post types post metadata options categories users attachments taxonomy terms tags navigation menu items widgets custom taxonomieswp_posts wp_terms wp_term_ taxonomy wp_post_ meta wp_optio ns wp_users wp_links links
  • 30. Wordpress Structure posts pages custom post types post metadata options categories users attachments taxonomy terms tags navigation menu items widgets custom taxonomieswp_posts wp_terms wp_term_ taxonomy wp_post_ meta wp_optio ns wp_users wp_links links Post
 Editing Tag/
 Category
  • 31. General in Post Editing has_many has_many It means static content Post Attachment Revision Page
  • 32. posts pages custom post attachments navigation menu wp_posts But in wordpress … wp_posts revisions attachments nav menu items
  • 33. But in wordpress … • All of those we mentioned before are in only one table. • Also include custom post types, links, navigation menu items!!! post_type •post •page •revision •attachment •nav_menu_item •…
  • 34. In Rails 1 has_many :attachments, -> { where(post_type: 2 "attachment") }, 3 foreign_key: 4 "post_parent", 5 class_name: 6 "Post" 7 has_many :revisions, -> { where(post_type: 8 "revision") }, 9 foreign_key: 10 "post_parent", 11 class_name: "Post"
  • 35. posts pages custom post types attachments navigation menu items wp_posts Tag / Category categories taxonomy terms tags wp_terms
  • 37. In practice • Category • wp_term_taxonomy.taxonomy: category • wp_terms.name: Politics • Tag • wp_term_taxonomy.taxonomy: post_tag • wp_terms.name: FireChat
  • 38. In Rails1 # models/w_post.rb 2 has_many :w_terms, through: : 3 w_term_relationships, foreign_key: "term_id" 4 has_many :w_term_relationships, foreign_key: 5 "object_id" 6 has_many :tags, 7 -> { where("#{WTermTaxonomy.table_name}.taxonomy = 'post_tag'") }, 9 through: :w_terms, source: :w_term_taxonomy, 10 class_name: "WTerm" 11 has_many :categories, 12 -> { where("#{WTermTaxonomy.table_name}.taxonomy = 'category'") }, 14 through: :w_terms, source: :w_term_taxonomy, 15 class_name: "WTerm" 16 17 # models/w_term_relationship.rb 18 belongs_to :w_term_taxonomy, foreign_key: 19 "term_taxonomy_id" 20 has_one :w_term, :through => :w_term_taxonomy
  • 39. In Rails1 # models/w_post.rb 2 has_many :w_terms, through: : 3 w_term_relationships, foreign_key: "term_id" 4 has_many :w_term_relationships, foreign_key: 5 "object_id" 6 has_many :tags, 7 -> { where("#{WTermTaxonomy.table_name}.taxonomy = 'post_tag'") }, 9 through: :w_terms, source: :w_term_taxonomy, 10 class_name: "WTerm" 11 has_many :categories, 12 -> { where("#{WTermTaxonomy.table_name}.taxonomy = 'category'") }, 14 through: :w_terms, source: :w_term_taxonomy, 15 class_name: "WTerm" 16 17 # models/w_term_relationship.rb 18 belongs_to :w_term_taxonomy, foreign_key: 19 "term_taxonomy_id" 20 has_one :w_term, :through => :w_term_taxonomy
  • 40. If you need to know more… • http://codex.wordpress.org/Database_Description • http://code.tutsplus.com/tutorials/understanding- and-working-with-data-in-wordpress--cms-20567
  • 41. And we made a gem • wpdb_activerecord: https://github.com/hothero/ wpdb_activerecord • It’s a ORM wrapper for the WordPress database, using ActiveRecord.
  • 42. wpdb_activerecord 1 # Gemfile 2 gem "wpdb_activerecord" 3 4 # Post 5 WPDB::Post.all # Get all posts 6 @post = WPDB::Post.find(75) 7 @post.tags 8 @post.attachments # No matter what type 9 @post.revisions 10 @post.author 11 12 # Term 13 WPDB::Term.tag # get all tags 14 WPDB::Term.category # get all categories
  • 43. wpdb_activerecord - advanced 1 # config/wpdb_activerecord.yml 2 WPDB_PREFIX: "cgjbugpbs_" # the table of WPDB::Post is cgjbugpbs_posts, not wp_posts 4 WPDB_USER_CLASS: "WUser" 5 6 # models/w_user.rb 7 class WUser < WPDB::User 8 def hello 9 puts "world" 10 end 11 end 12 13 # usage 14 @author = WPDB::Post.find(25).author 15 @author.class_name # will get WUser, not WPDB:: 16 User 17 @author.hello # world
  • 57. Our Progress & Goal Backend
 +
 DB Schema Frontend
  • 60. And we done pcu 6000 ⬆ NT$5000 ⬇ Monthly Data • 7 million pageview ⬆ • 1.2 hundred million requests ⬆ • 4 million UU ⬆
  • 62. Our Progress & Goal Backend
 +
 DB Schema Frontend
  • 63. CMS Admin Edit Flow Media Gallery Globalize Cronjob
  • 64. editflow.org • Edit Flow gives you custom statuses, a calendar, editorial comments, and more, all to make it much easier for your team to collaborate within WordPress. • Calendar • Custom Statuses • Editorial Comments • Editorial Metadata • Notifications • Story Budget • User Groups
  • 65. Editor Structure Author Senior
 Editor Chief
 Editor ready to 
 review ready to 
 check publish Normal Flow Editor
  • 67. Editorial Comments • Threaded commenting in the admin for private discussion between writers and editors.
  • 68. Editorial Comments • Use this gem: acts_as_commentable • Polymorphic Associations 1 commentable = Post.create 2 comment = commentable.comments.create 3 comment.title = "First comment." 4 comment.comment = "This is the first comment." 5 comment.save
  • 69. What’s the Polymorphic Associations • Assume a situation • An employee has many pictures • A Product has many pictures • And each of those pictures have owned information detail.
  • 70. What’s the Polymorphic Associations • In general: two relationship tables to associate objects and pictures Employee Product Employee_
 Relationship employee_id picture_id Product_
 Relationship product_id picture_id Picture
  • 71. What’s the Polymorphic Associations • Level up: an additional table to associate Employee Product Object
 Relationship object_id picture_id Picture
  • 72. What’s the Polymorphic Associations • Polymorphic Associations Employee Product Picture imageable_id imageable_type will be: * Employee * Product
  • 75. editflow.org • Edit Flow gives you custom statuses, a calendar, editorial comments, and more, all to make it much easier for your team to collaborate within WordPress. • Calendar • Custom Statuses • Editorial Comments • Editorial Metadata • Notifications • Story Budget • User Groups
  • 76. Story Budget • View all of your upcoming posts in a more traditional story budget view, and hit the print button to take it to your planning meeting.
  • 77. Search Design In General • In general, we maybe use many conditions to match different situation. 1 def search 2 @posts = Post.send(params[:scope]) 3 if params.key?(:author_id) 4 @posts = @posts.where(author_id: params[: 5 author_id]) 6 end 7 if params.key?(:post_type) 8 @posts = @posts.where(post_type: params[: 9 post_type]) 10 end 11 if params.key?(:start_date) || params.key?(: 12 end_date) 13 @posts = @posts.where(updated_at: params[: 14 start_date]..params[:end_date]) 15 end 16 # ... 17 end
  • 78. Search Design In General • In general, we maybe use many conditions to match different situation. 1 def search 2 @posts = Post.send(params[:scope]) 3 if params.key?(:author_id) 4 @posts = @posts.where(author_id: params[: 5 author_id]) 6 end 7 if params.key?(:post_type) 8 @posts = @posts.where(post_type: params[: 9 post_type]) 10 end 11 if params.key?(:start_date) || params.key?(: 12 end_date) 13 @posts = @posts.where(updated_at: params[: 14 start_date]..params[:end_date]) 15 end 16 # ... 17 end https://github.com/ activerecord-hackery/ ransack
  • 79. Ransack - View Helper1 <%= search_form_for @q do |f| %> 2 # Search if the name field contains... 3 <%= f.label :name_cont %> 4 <%= f.search_field :name_cont %> 5 6 # Search if an associated articles.title 7 starts with... 8 <%= f.label :articles_title_start %> 9 <%= f.search_field :articles_title_start %> 10 11 # Attributes may be chained. Search multiple 12 attributes for one value... 13 <%= f.label : 14 name_or_description_or_email_or_articles_t 15 itle_cont %> 16 <%= f.search_field : 17 name_or_description_or_email_or_articles_t 18 itle_cont %> 19 20 <%= f.submit %> 21 <% end %> name_cont
  • 80. Ransack - View Helper1 <%= search_form_for @q do |f| %> 2 # Search if the name field contains... 3 <%= f.label :name_cont %> 4 <%= f.search_field :name_cont %> 5 6 # Search if an associated articles.title 7 starts with... 8 <%= f.label :articles_title_start %> 9 <%= f.search_field :articles_title_start %> 10 11 # Attributes may be chained. Search multiple 12 attributes for one value... 13 <%= f.label : 14 name_or_description_or_email_or_articles_t 15 itle_cont %> 16 <%= f.search_field : 17 name_or_description_or_email_or_articles_t 18 itle_cont %> 19 20 <%= f.submit %> 21 <% end %> articles_title_start
  • 81. Ransack - View Helper1 <%= search_form_for @q do |f| %> 2 # Search if the name field contains... 3 <%= f.label :name_cont %> 4 <%= f.search_field :name_cont %> 5 6 # Search if an associated articles.title 7 starts with... 8 <%= f.label :articles_title_start %> 9 <%= f.search_field :articles_title_start %> 10 11 # Attributes may be chained. Search multiple 12 attributes for one value... 13 <%= f.label : 14 name_or_description_or_email_or_articles_t 15 itle_cont %> 16 <%= f.search_field : 17 name_or_description_or_email_or_articles_t 18 itle_cont %> 19 20 <%= f.submit %> 21 <% end %> name_or_description_or_email _or_articles_title_cont
  • 82. Ransack - Controller 1 def index 2 @q = Person.ransack(params[:q]) 3 @people = @q.result(distinct: true) 4 end
  • 83. Ransack - Controller 1 def index 2 @q = Person.ransack(params[:q]) 3 @people = @q.result(distinct: true) 4 end
  • 85. editflow.org • Edit Flow gives you custom statuses, a calendar, editorial comments, and more, all to make it much easier for your team to collaborate within WordPress. • Calendar • Custom Statuses • Editorial Comments • Editorial Metadata • Notifications • Story Budget • User Groups
  • 86. User Groups • Keep your users organized by department or function.
  • 88. Maybe DB Schema User Author Editor Admin or User user_type
  • 89. STI (Single-table inheritance) class User < ActiveRecord::Base end class Author < User enum role: [:normal, :blogger] def publish # ex: only author can use end end class Editor < User enum role: [:editor, :senior_editor, :chief] end class Admin < User end User type type: rails reserved word
  • 90. STI with Priority Problem • STI is unfit for priority feature. • Chief Editor > Senior Editor > Editor > Author • Enum-design is more fit. 1 class User < ActiveRecord::Base 2 enum role: [:normal, :blogger, :editor, :senior_editor, :chief] 4 end
  • 91. Other parts • Except edit-flow, there are some more features • takeover & editing lock • media gallery • globalize
  • 93. takeover & editing lock • Use this gem: message_bus • MessageBus implements a Server to Server channel protocol and Server to Web Client protocol (using polling or long-polling)
  • 94. • We use current_editor_id field as lock in post. • Subscribe a channel for takeover when start editing in front- end. • Publish a message to the channel when someone wanna edit. takeover & editing lock 1 MessageBus.start(); 2 MessageBus.callbackInterval = 500; 3 MessageBus.subscribe("/posts/<%= @post.id %>/takeover/request", 4 function(msg){ 5 unlock_post_and_auto_save(); 6 window.location = "<%= posts_path %>"; 7 }); 1 MessageBus.publish(“/posts/#{post.id}/takeover/request”, username: user.name) Channel
  • 96. Media Gallery - Tricks Browsers don't allow file uploads via XMLHttpRequest (aka XHR) for security reasons.
  • 97. General in jQuery • Hijack the forms submit event to execute our custom iFrame-method function • Submit the form to the iFrame normal-style (non-AJAX) • Copy the response content from the iFrame back into the parent window. http://www.alfajango.com/blog/ajax-file-uploads-with-the-iframe-method/
  • 98. remotipart • Use this gem: remotipart • Remotipart is a Ruby on Rails gem enabling AJAX file uploads with jQuery in Rails 3 and Rails 4 remote forms. 1 # Gemfile 2 gem "remotipart" 3 4 # js 5 //= require jquery.remotipart
  • 100. globalize • Use this gem: globalize • Each locale have their owned tags & revisions 1 # config/initializers/post_translation.rb 2 Post::Translation.module_eval do 3 acts_as_ordered_taggable 4 has_paper_trail only: [:content, :title, : 5 excerpt] 6 end
  • 102. API Design In General class ApiController < ApplicationController def all # get review & news type post case params[:post_type] when "new" # latest when "hot" # hot end end def review case params[:post_type] when "new" when "hot" end end end def news case params[:post_type] when "new" when "hot" end end
  • 103. has_scope • Use this gem: has_scope • In model 1 class Graduation < ActiveRecord::Base 2 scope :featured, -> { where(:featured => true) 3 } 4 scope :by_degree, -> degree { where(:degree => 5 degree) } 6 scope :by_period, -> started_at, ended_at { 7 where("started_at = ? AND ended_at = ?", 8 started_at, ended_at) } 9 end
  • 104. has_scope • You can use those named scopes as filters by declaring them on your controller and just need to call apply_scopes to an specific resource. 1 class GraduationsController < 2 ApplicationController 3 has_scope :featured, :type => :boolean 4 has_scope :by_degree 5 has_scope :by_period, :using => [:started_at, 6 :ended_at], : 7 type => :hash 8 9 def index 10 @graduations = apply_scopes(Graduation).all 11 end 12 end
  • 105. has_scope • You can use those named scopes as filters by declaring them on your controller and just need to call apply_scopes to an specific resource. 1 class GraduationsController < 2 ApplicationController 3 has_scope :featured, :type => :boolean 4 has_scope :by_degree 5 has_scope :by_period, :using => [:started_at, 6 :ended_at], : 7 type => :hash 8 9 def index 10 @graduations = apply_scopes(Graduation).all 11 end 12 end /graduations?featured=true
  • 106. has_scope • You can use those named scopes as filters by declaring them on your controller and just need to call apply_scopes to an specific resource. 1 class GraduationsController < 2 ApplicationController 3 has_scope :featured, :type => :boolean 4 has_scope :by_degree 5 has_scope :by_period, :using => [:started_at, 6 :ended_at], : 7 type => :hash 8 9 def index 10 @graduations = apply_scopes(Graduation).all 11 end 12 end /graduations?by_period[started_at]=20100701&by_period[ended_at]=20101013
  • 107. has_scope • You can use those named scopes as filters by declaring them on your controller and just need to call apply_scopes to an specific resource. 1 class GraduationsController < 2 ApplicationController 3 has_scope :featured, :type => :boolean 4 has_scope :by_degree 5 has_scope :by_period, :using => [:started_at, 6 :ended_at], : 7 type => :hash 8 9 def index 10 @graduations = apply_scopes(Graduation).all 11 end 12 end /graduations?featured=true&by_degree=phd
  • 108. Tragedy at the admin theme Find out a good design which have smooth operating and fancy
  • 109. turbolinks & pjax • Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body (or parts of) and the title in the head. • Same advantages: good user experience, reduce bandwidth and server cost • In particular with Rails: • more detail: http://goo.gl/Lx7mHk # Gemfile gem “turbolinks” # app/assets/javascripts/ application.js //= require tubolinks $.pjax({url:’authors’, container:’#main’}) if request.headers[‘X-PJAX’] render:layout end
  • 110.
  • 111. rails-gem-list • A workman must sharpen his tools if he is to do his work well / ⼯工欲善其事,必先利其器 • We’ve done a gem: rails-gem-list • You can go through rails-gem-list to know how to construct your project architecture and DB schema. Just like • acts_as_taggable • ransack • …
  • 112. rails-gem-list • A workman must sharpen his tools if he is to do his work well / ⼯工欲善其事,必先利其器 • We’ve done a gem: rails-gem-list • You can go through rails-gem-list to know how to construct your project architecture and DB schema. Just like • acts_as_taggable • ransack • …
  • 113. Finally • If you want to do a media website, you can follow edit-flow to manage your posts. • If your WordPress website becomes larger and larger, you can rewrite your front-end with Rails. • Please don’t even think to transfer the whole site from WordPress to Rails. • After we had spoken many topics, there are still two main parts we didn’t present • Server Architecture • Data Migration
  • 114. Special Thanks X @dlackty @ymowov @baojjeu @st0012 @nanasyu @eugg @chentyphoon @randyhsieh @fufukwang Contact me: hothero@backer-founder.com