Single document site
When the website consists of static data, it is possible to save all data into a single MongoDB document. This way, it is possible to define hundreds of small sites on a single rails instance almost instantly with as little overhead as possible. It also shouldn't be too hard to implement caching logic and thus get very fast responses for such system.
dc_process_default_request action will of course not be adequate for processing web request, so we need to create a new process default request action and point *path route to it. DRG CMS already provides dc_single_sitedoc_request action for this purpose. If you choose to use it, replace *path route in routes.rb with this line:
The action includes the following assumptions:
- all data is saved into dc_site document
- design must also be defined in dc_site document
- web page data is saved into dc_parts embedded documents
- value ''document'' in div_id field of dc_part document indicates documents that form site menu
- name field of dc_part defines menu link caption
- link field of dc_part defines site page link
- dc_part_renderer.rb defines two render methods required to render web page data. single_sitedoc_menu will render web site menu and single_sitedoc will render page data.
Action source code:
session[:edit_mode] ||= 0
@site = dc_get_site
# @site is not defined. render 404 error
return dc_render_404('Site!') unless @site
dc_set_options(@site.settings)
# HOMEPAGE. When no parameters is set
params[:path] = @site.homepage_link if params[:path].nil?
@parts = @site.dc_parts
@part = @parts.find_by(link: params[:path])
return dc_render_404('Part!') unless @part
@page_title = "#{@site.page_title} #{@part.name}"
@js, @css = '', ''
layout = session[:edit_mode] > 0 ? 'cms' : @site.site_layout
if @site.rails_view.blank?
design = '<%= dc_page_top %>' + @site.design + '<%= dc_page_bottom %>'
render(inline: design, layout: layout)
else
render @site.rails_view, layout: layout
end
end
Action code is a striped down version of default request process code. The program searches for site document and returns an error if the site document is not found. After that, settings are initialized. If path is not set, homepage document link is determined by homepage_link field.
After that, internal parts are assigned to site dc_parts documents and finally a document with link defined by path parameter is searched. Again if not found error is returned.
After that, page_title is defined, JavaScript and CSS variables are initialized, and Rails layout is determined. With all this data, it's time to render Rails view. If view is defined as design code, some additional code is added and design is rendered inline. If a view is defined in a file, the Rails view file is rendered.
Design code, which doesn't require explanation:
id="site-top"
href="http://www.mysite.com/" alt="logo" src="/files/logo.jpg"
id="site-name" Site name
<%= dc_render(:dc_part, method: 'single_sitedoc_menu', menu_div: 'menu-name') %>
id="body"<%= dc_render(:dc_part, method: 'single_sitedoc') %>
id="footer"<%= dc_render(:dc_part, method: 'single_sitedoc', div_id: 'footer') %>
dc_part_renderer.rb contains two render methods which are used to render web page data.
First, single_sitedoc method, is used to render page data content:
# if div_id option specified search for part with this div_id.
# This can be used to render footer or header of site.
part = if @opts[:div_id]
@parent.parts.find_by(div_id: @opts[:div_id])
else
@parent.part
end
# part not found. Render error message.
return "Part #{@opts[:div_id]} not found!" if part.nil?
# prepare edit parameters
@opts[:editparams].merge!(id: part, ids: @parent.site._id, formname: 'dc_part',
table: "dc_site;dc_part", record_div_id: 'document' )
render_particle(part, @opts)
end
Second, single_sitedoc_menu method, is used to render web site menu:
# prepare div markup
menu_div = @opts[:menu_div] ? "id=#{@opts[:menu_div]}" : ''
html = "<div #{menu_div}><ul>\n"
# collect all dc_part documents which make menu
@parent.parts.where(div_id: 'document').order_by(order: 1).each do |part|
# mark selected item
selected = (part == @parent.part) ? 'class="menu-selected"' : ''
html << "<li #{selected}>#{ @parent.link_to(part.name, part.link ) }</li>\n"
end
html << "</ul></div>\n"
end
As you can see, It is easy to create your own request process action controller and render data on a web page. You are not bound by models (collections) defined in DRG CMS. Go ahead and define your own models and use them for saving your website data and enjoy simplicity of entering data with DRG Forms.