From 48f50f6ebe393a98db84c8dfa3e3e9b72820549e Mon Sep 17 00:00:00 2001 From: manson Date: Mon, 23 Mar 2015 15:46:14 +0800 Subject: [PATCH] update impression and add cache for page sub-parts, main-menu --- app/controllers/pages_controller.rb | 17 ++- app/helpers/application_helper.rb | 185 ++++++++++++++-------------- app/helpers/orbit_backend_helper.rb | 18 ++- app/models/orbit_observer.rb | 26 ++++ app/models/page.rb | 9 ++ app/models/sub_part.rb | 7 ++ config/application.rb | 2 + lib/orbit_model/impression.rb | 2 +- 8 files changed, 165 insertions(+), 101 deletions(-) create mode 100644 app/models/orbit_observer.rb diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 7bda6bf..498d82b 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -27,7 +27,10 @@ class PagesController < ApplicationController def home @manifest = @key page = Page.first - impressionist(page) + Thread.new do + impressionist(page) + page.inc(view_count: 1) + end OrbitHelper.set_params params,current_user OrbitHelper.set_site_locale locale render :html => render_final_page("home",page,true).html_safe @@ -110,7 +113,10 @@ class PagesController < ApplicationController layout = true end - impressionist(page) + Thread.new do + impressionist(page) + page.inc(view_count: 1) + end render :html => render_final_page("#{module_app}/#{params[:target_action]}",page,layout).html_safe else render :file => "#{Rails.root}/public/404.html", :layout => false, :status => :not_found @@ -301,11 +307,11 @@ class PagesController < ApplicationController def render_final_page(original_view=get_view,page,layout) final_html_for_render = "" + if layout parts = $mobile.blank? ? (page.page_parts rescue []) : (page.mobile_page_parts rescue []) @part_partials = {} - parts.each do |part| subparts = part.sub_parts.asc(:created_at) partials = [] @@ -326,7 +332,10 @@ class PagesController < ApplicationController if @editmode partials << "
" + render_widget_for_frontend(subpart.module,subpart.widget_method,subpart.widget_type,subpart.id.to_s) + "
" else - partials << render_widget_for_frontend(subpart.module,subpart.widget_method,subpart.widget_type,subpart.id.to_s) + widget_html = Rails.cache.fetch("subpart_#{subpart.module}_#{subpart.id.to_s}_"+I18n.locale.to_s) do + render_widget_for_frontend(subpart.module,subpart.widget_method,subpart.widget_type,subpart.id.to_s) + end + partials << widget_html end elsif subpart.kind == "text" if @editmode diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7d1f857..8764b2f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -76,94 +76,98 @@ module ApplicationHelper end def render_menu - # json_file = File.read(File.join(Rails.root, 'public', "menu.json")) - # @items = JSON.parse(json_file) - if $mobile.blank? - @pages = Page.root.sorted_published_child_pages - else - @pages = Page.root.sorted_published_child_pages_for_mobile - end + menu_html = Rails.cache.fetch(['main_menu',request.original_fullpath, I18n.locale], race_condition_ttl: 2.seconds) do + # json_file = File.read(File.join(Rails.root, 'public', "menu.json")) + # @items = JSON.parse(json_file) + if $mobile.blank? + @pages = Page.root.sorted_published_child_pages + else + @pages = Page.root.sorted_published_child_pages_for_mobile + end - def create_json(pages) - item = {} - pages.each do |page| - if page.child_page.size > 0 - if page.page_type == "page" - if $mobile.blank? - item["#{page.name}"] = {"url"=> "/#{locale.to_s}" + page.url, "children"=>create_json(page.sorted_published_child_pages), "target" => "_self"} - else - item["#{page.name}"] = {"url"=> "/#{locale.to_s}" + page.url, "children"=>create_json(page.sorted_published_child_pages_for_mobile), "target" => "_self"} + def create_json(pages) + item = {} + pages.each do |page| + if page.child_page.size > 0 + if page.page_type == "page" + if $mobile.blank? + item["#{page.name}"] = {"url"=> "/#{locale.to_s}" + page.url, "children"=>create_json(page.sorted_published_child_pages), "target" => "_self"} + else + item["#{page.name}"] = {"url"=> "/#{locale.to_s}" + page.url, "children"=>create_json(page.sorted_published_child_pages_for_mobile), "target" => "_self"} + end + elsif page.page_type == "link" + target = get_target(page.external_url) + if $mobile.blank? + item["#{page.name}"] = {"url"=> page.external_url, "children"=>create_json(page.sorted_published_child_pages), "target" => target} + else + item["#{page.name}"] = {"url"=> page.external_url, "children"=>create_json(page.sorted_published_child_pages_for_mobile), "target" => target} + end end - elsif page.page_type == "link" - target = get_target(page.external_url) - if $mobile.blank? - item["#{page.name}"] = {"url"=> page.external_url, "children"=>create_json(page.sorted_published_child_pages), "target" => target} - else - item["#{page.name}"] = {"url"=> page.external_url, "children"=>create_json(page.sorted_published_child_pages_for_mobile), "target" => target} + else + if page.page_type == "page" + item["#{page.name}"] = {"url"=> "/#{locale.to_s}" + page.url, "target" => "_self"} + elsif page.page_type == "link" + item["#{page.name}"] = {"url"=> page.external_url, "target" => get_target(page.external_url)} end end - else - if page.page_type == "page" - item["#{page.name}"] = {"url"=> "/#{locale.to_s}" + page.url, "target" => "_self"} - elsif page.page_type == "link" - item["#{page.name}"] = {"url"=> page.external_url, "target" => get_target(page.external_url)} + end + item + end + @items = create_json(@pages) + menu_file = File.open(File.join(Rails.root, 'app', 'templates', "#{@key}", "/home/menu.html.erb")) + doc = Nokogiri::HTML(menu_file, nil, "UTF-8") + menu_file.close + + temp = [] + @menus = [] + @menus_items = [] + + temp << doc.css("*[data-menu-level='0']") + temp << doc.css("*[data-menu-level='1']") + temp << doc.css("*[data-menu-level='2']") + + + temp[0] = temp[0].to_s.gsub(temp[1].to_s,"{{level}}") + temp[1] = temp[1].to_s.gsub(temp[2].to_s,"{{level}}") + temp[2] = temp[2].to_s + + + temp.each_with_index do |menu,i| + t = Nokogiri::HTML(menu, nil, "UTF-8") + a = t.css("*[data-menu-link='true']") + a[0]["href"] = "href_here" + a[0]["target"] = "target_here" + li = t.css("*[data-menu-level='#{i}'] > *") + @menus_items << li.to_html + ul = t.css("*[data-menu-level='#{i}']") + ul[0].inner_html = "{{here}}" + @menus << ul[0].to_html + end + + def create_menu(items,level) + html = "" + items.each do |key,item| + li = @menus_items[level].gsub("href_here",(item["url"] || "")) + li = li.gsub("{{link_name}}",(key || "")) + li = li.gsub("target_here",(item["target"] || "")) + li = request.original_fullpath == item['url'] ? li.gsub("{{active}}","active") : li.gsub("{{active}}","") + + if item["children"] && !item["children"].empty? + li = li.gsub("{{level}}",create_menu(item["children"],level + 1)) + else + li = li.gsub("{{level}}","") end + html = html + li end + html = @menus[level].gsub("{{here}}",html) + html = html.gsub("{{class_level}}",level.to_s) + html end - item - end - @items = create_json(@pages) - menu_file = File.open(File.join(Rails.root, 'app', 'templates', "#{@key}", "/home/menu.html.erb")) - doc = Nokogiri::HTML(menu_file, nil, "UTF-8") - menu_file.close - - temp = [] - @menus = [] - @menus_items = [] - - temp << doc.css("*[data-menu-level='0']") - temp << doc.css("*[data-menu-level='1']") - temp << doc.css("*[data-menu-level='2']") - - - temp[0] = temp[0].to_s.gsub(temp[1].to_s,"{{level}}") - temp[1] = temp[1].to_s.gsub(temp[2].to_s,"{{level}}") - temp[2] = temp[2].to_s - - - temp.each_with_index do |menu,i| - t = Nokogiri::HTML(menu, nil, "UTF-8") - a = t.css("*[data-menu-link='true']") - a[0]["href"] = "href_here" - a[0]["target"] = "target_here" - li = t.css("*[data-menu-level='#{i}'] > *") - @menus_items << li.to_html - ul = t.css("*[data-menu-level='#{i}']") - ul[0].inner_html = "{{here}}" - @menus << ul[0].to_html + h = create_menu(@items,0) + h.html_safe end - def create_menu(items,level) - html = "" - items.each do |key,item| - li = @menus_items[level].gsub("href_here",(item["url"] || "")) - li = li.gsub("{{link_name}}",(key || "")) - li = li.gsub("target_here",(item["target"] || "")) - li = request.original_fullpath == item['url'] ? li.gsub("{{active}}","active") : li.gsub("{{active}}","") - - if item["children"] && !item["children"].empty? - li = li.gsub("{{level}}",create_menu(item["children"],level + 1)) - else - li = li.gsub("{{level}}","") - end - html = html + li - end - html = @menus[level].gsub("{{here}}",html) - html = html.gsub("{{class_level}}",level.to_s) - html - end - h = create_menu(@items,0) - h.html_safe + menu_html end def render_view @@ -269,17 +273,18 @@ module ApplicationHelper doc.to_html.html_safe else unless data['impressionist'].blank? - impression = data['impressionist'].impressions.create - impression.user_id = request.session['user_id'] - impression.controller_name = params[:target_controller] - impression.action_name = params[:target_action] - impression.ip_address = request.remote_ip - impression.session_hash = request.session.id - impression.request_hash = @impressionist_hash - impression.referrer = request.referrer - impression.save - data['impressionist'].view_count = data['impressionist'].impressions.count - data['impressionist'].save + Thread.new do + impression = data['impressionist'].impressions.create + impression.user_id = request.session['user_id'] + impression.controller_name = params[:target_controller] + impression.action_name = params[:target_action] + impression.ip_address = request.remote_ip + impression.session_hash = request.session.id + impression.request_hash = @impressionist_hash + impression.referrer = request.referrer + impression.save + data['impressionist'].inc(view_count: 1) + end end wrap_elements = doc.css("*[data-list][data-level='0']") if wrap_elements.count == 0 diff --git a/app/helpers/orbit_backend_helper.rb b/app/helpers/orbit_backend_helper.rb index 438e48f..f666f00 100644 --- a/app/helpers/orbit_backend_helper.rb +++ b/app/helpers/orbit_backend_helper.rb @@ -102,23 +102,29 @@ module OrbitBackendHelper end def display_visitors(options={}) - Impression.where(options).distinct(:request_hash).count + Impression.where(options).count end def display_visitors_today - display_visitors(created_at: {'$gte' => Time.now.beginning_of_day, '$lte' => Time.now}) + display_visitors(created_at: {'$gte' => Time.now.beginning_of_day}) end def display_visitors_this_week - display_visitors(created_at: {'$gte' => Time.now-7.days, '$lte' => Time.now}) + display_visitors(created_at: {'$gte' => Time.now.beginning_of_week}) end def display_visitors_this_month - display_visitors(created_at: {'$gte' => Time.now-30.days, '$lte' => Time.now}) + visitors_this_month = Rails.cache.fetch("visitors_this_month", expires_in: 1.day) do + display_visitors(created_at: {'$gte' => Time.now.beginning_of_month}) + end + visitors_this_month end def display_visitors_this_year - display_visitors(created_at: {'$gte' => Time.now-365.days, '$lte' => Time.now}) + visitors_this_year = Rails.cache.fetch("visitors_this_year", expires_in: 1.day) do + display_visitors(created_at: {'$gte' => Time.now.beginning_of_year}) + end + visitors_this_year end def get_month_traffic @@ -231,4 +237,4 @@ module Orbit::FormBuilder def datetime_picker(method, options = {}) @template.datetime_picker(@object_name, method, objectify_options(options)) end -end \ No newline at end of file +end diff --git a/app/models/orbit_observer.rb b/app/models/orbit_observer.rb new file mode 100644 index 0000000..e1996a6 --- /dev/null +++ b/app/models/orbit_observer.rb @@ -0,0 +1,26 @@ +class OrbitObserver < Mongoid::Observer + # observe OrbitApp.get_models + observe :tag, :category + + def after_save(document) + clear_cache(document) + end + + def after_destroy(document) + clear_cache(document) + end + + def clear_cache(document) + # model_module_hash = OrbitApp.get_model_module_hash + case document.class.to_s + when 'Tag' + document.module_app.each do |module_app| + Rails.cache.delete_matched( /#{ module_app.key }/ ) + end + when 'Category' + Rails.cache.delete_matched( /#{ document.module_app.key }/ ) + else + # Rails.cache.delete_matched( /#{model_module_hash[document.class.to_s]}/ ) + end + end +end \ No newline at end of file diff --git a/app/models/page.rb b/app/models/page.rb index 539b2a7..aeea7fe 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -31,6 +31,15 @@ class Page belongs_to :parent_page, :class_name => 'Page', :inverse_of => :child_page before_create :assign_page_number + + after_save :clear_cache + after_destroy :clear_cache + + def clear_cache + I18n.available_locales.each do |locale| + Rails.cache.delete_matched( /main_menu/ ) + end + end def assign_page_number parent_page = self.parent_page diff --git a/app/models/sub_part.rb b/app/models/sub_part.rb index fb2c1e4..c2dd336 100644 --- a/app/models/sub_part.rb +++ b/app/models/sub_part.rb @@ -16,4 +16,11 @@ class SubPart belongs_to :page_part belongs_to :mobile_page_part + + after_save :clear_cache + after_destroy :clear_cache + + def clear_cache + Rails.cache.delete_matched( /#{self.id.to_s}/ ) + end end \ No newline at end of file diff --git a/config/application.rb b/config/application.rb index 126131f..ef1fd0f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -37,5 +37,7 @@ module Orbit # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # config.i18n.default_locale = :de + + config.mongoid.observers = :orbit_observer end end diff --git a/lib/orbit_model/impression.rb b/lib/orbit_model/impression.rb index e95393d..3de4ce2 100644 --- a/lib/orbit_model/impression.rb +++ b/lib/orbit_model/impression.rb @@ -4,7 +4,7 @@ module OrbitModel include Impressionist::Impressionable base.extend ClassMethods - base.is_impressionable :counter_cache => true, :column_name => :view_count, :unique => :request_hash + base.is_impressionable :counter_cache => false base.field :view_count, :type => Integer, :default => 0 end