Merge branch 'ldap' of github.com:Rulingcom/orbit into ldap
This commit is contained in:
		
						commit
						f1941f1fc5
					
				
							
								
								
									
										1
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										1
									
								
								Gemfile
								
								
								
								
							|  | @ -34,6 +34,7 @@ gem 'sprockets' | ||||||
| gem 'tinymce-rails' | gem 'tinymce-rails' | ||||||
| gem 'therubyracer' if RUBY_PLATFORM.downcase.include?("linux") | gem 'therubyracer' if RUBY_PLATFORM.downcase.include?("linux") | ||||||
| 
 | 
 | ||||||
|  | gem "impressionist", :require => "impressionist", :path => "vendor/impressionist" | ||||||
| 
 | 
 | ||||||
| # Gems used only for assets and not required | # Gems used only for assets and not required | ||||||
| # in production environments by default. | # in production environments by default. | ||||||
|  |  | ||||||
|  | @ -7,6 +7,13 @@ GIT | ||||||
|       activesupport (>= 3.0.0) |       activesupport (>= 3.0.0) | ||||||
|       railties (>= 3.0.0) |       railties (>= 3.0.0) | ||||||
| 
 | 
 | ||||||
|  | PATH | ||||||
|  |   remote: vendor/impressionist | ||||||
|  |   specs: | ||||||
|  |     impressionist (1.1.1) | ||||||
|  |       httpclient (~> 2.2) | ||||||
|  |       nokogiri (~> 1.5) | ||||||
|  | 
 | ||||||
| GEM | GEM | ||||||
|   remote: http://rubygems.org/ |   remote: http://rubygems.org/ | ||||||
|   specs: |   specs: | ||||||
|  | @ -92,6 +99,7 @@ GEM | ||||||
|     hike (1.2.1) |     hike (1.2.1) | ||||||
|     hoe (2.16.1) |     hoe (2.16.1) | ||||||
|       rake (~> 0.8) |       rake (~> 0.8) | ||||||
|  |     httpclient (2.2.5) | ||||||
|     i18n (0.6.0) |     i18n (0.6.0) | ||||||
|     jquery-rails (1.0.19) |     jquery-rails (1.0.19) | ||||||
|       railties (~> 3.0) |       railties (~> 3.0) | ||||||
|  | @ -277,6 +285,7 @@ DEPENDENCIES | ||||||
|   exception_notification |   exception_notification | ||||||
|   execjs |   execjs | ||||||
|   factory_girl_rails |   factory_girl_rails | ||||||
|  |   impressionist! | ||||||
|   jquery-rails |   jquery-rails | ||||||
|   jquery-ui-rails |   jquery-ui-rails | ||||||
|   kaminari! |   kaminari! | ||||||
|  |  | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | // JavaScript Document
 | ||||||
|  | 
 | ||||||
|  | // can copy code to any of ur desired javascsript 
 | ||||||
|  | 
 | ||||||
|  | //extended jquery to search fast.
 | ||||||
|  | $.extend($.expr[':'], { | ||||||
|  | 	'containsi': function (elem, i, match, array) { | ||||||
|  | 		return (elem.textContent || elem.innerText || '').toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0; | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | var interval,sval; | ||||||
|  | $(document).ready(function(){ | ||||||
|  | 	$("#user_filter").keyup(function(e){ | ||||||
|  | 		if((e.which>96 && e.which<123) || (e.which>64 && e.which<92) || (e.which == 32) || (e.which == 8)){  | ||||||
|  | 			sval = $(this).val(); | ||||||
|  | 			$(".checkbox").popover("hide"); | ||||||
|  | 			$("div.checkblock").hide(); | ||||||
|  | 			clearInterval(interval); | ||||||
|  | 			interval = setInterval(waitForSearch,1000); | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
|  | var waitForSearch = function(){ | ||||||
|  | 	if(sval){ | ||||||
|  | 		var totalfoundbyname = $("div#users_checkbox_ary label.member-name:containsi("+sval+")").length | ||||||
|  | 		if(totalfoundbyname!=0){ | ||||||
|  | 			$("div#users_checkbox_ary label.member-name:containsi("+sval+")").parent().parent().show();				 | ||||||
|  | 		}else if(totalfoundbyname==0){ | ||||||
|  | 			$("div#users_checkbox_ary div.for_unit:containsi("+sval+")").parent().show(); | ||||||
|  | 		}	 | ||||||
|  | 	}else{ | ||||||
|  | 		$(".checkbox").popover('hide');	 | ||||||
|  | 		$("div.checkblock").show(); | ||||||
|  | 	} | ||||||
|  | 	clearInterval(interval); | ||||||
|  | } | ||||||
|  | @ -7,6 +7,7 @@ class Admin::DashboardsController < ApplicationController | ||||||
|   def index |   def index | ||||||
|   	@module_app_contents, @module_app_contents_total = get_module_app_count('bulletin', 'news_bulletin', 'page_context', 'web_link') |   	@module_app_contents, @module_app_contents_total = get_module_app_count('bulletin', 'news_bulletin', 'page_context', 'web_link') | ||||||
|   	@recent_updated = get_recently_updated('bulletin', 'news_bulletin', 'page_context', 'web_link') |   	@recent_updated = get_recently_updated('bulletin', 'news_bulletin', 'page_context', 'web_link') | ||||||
|  |     @most_visited = get_most_visited('bulletin', 'news_bulletin', 'page_context') | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   protected |   protected | ||||||
|  | @ -36,4 +37,17 @@ class Admin::DashboardsController < ApplicationController | ||||||
|   	sorted_objects[0..9] |   	sorted_objects[0..9] | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   def get_most_visited(*args) | ||||||
|  |     a = {} | ||||||
|  |     args.each do |module_app| | ||||||
|  |       module_app_class = module_app.classify.constantize | ||||||
|  |       objects = module_app_class.order_by(:view_count, :desc).limit(10) | ||||||
|  |       objects.each do |object| | ||||||
|  |         a.merge!(object => object.view_count) if object.view_count > 0 | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |     sorted_objects = a.sort {|a,b| b[1]<=>a[1]} | ||||||
|  |     sorted_objects[0..9] | ||||||
|  |   end | ||||||
|  |    | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,9 +1,7 @@ | ||||||
| class Admin::ObjectAuthsNewInterfaceController < OrbitBackendController | class Admin::ObjectAuthsNewInterfaceController < OrbitBackendController | ||||||
|   include OrbitCoreLib::PermissionUnility |   include OrbitCoreLib::PermissionUnility | ||||||
|   layout "new_admin" |  | ||||||
|   before_filter :force_order |  | ||||||
| 
 | 
 | ||||||
|   layout "new_admin" |   before_filter :force_order | ||||||
|    |    | ||||||
|    |    | ||||||
|   def setting |   def setting | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ class PagesController < ApplicationController | ||||||
|   def index |   def index | ||||||
|     @item = Page.find_by_name('home') |     @item = Page.find_by_name('home') | ||||||
|     if @item |     if @item | ||||||
|  |       impressionist(@item) | ||||||
|       render_page |       render_page | ||||||
|     else |     else | ||||||
|       render :text => 'You need a home page' |       render :text => 'You need a home page' | ||||||
|  | @ -17,11 +18,12 @@ class PagesController < ApplicationController | ||||||
|     #begin   |     #begin   | ||||||
|       @item = Item.first(:conditions => {:path => params[:page_name]}) |       @item = Item.first(:conditions => {:path => params[:page_name]}) | ||||||
|       if @item && @item.is_published && (@item.enabled_for.nil? ? true : @item.enabled_for.include?(I18n.locale.to_s)) |       if @item && @item.is_published && (@item.enabled_for.nil? ? true : @item.enabled_for.include?(I18n.locale.to_s)) | ||||||
|  |         impressionist(@item) | ||||||
|         case @item._type |         case @item._type | ||||||
|           when 'Page'     |           when 'Page'     | ||||||
|             render_page |             render_page | ||||||
|           when 'Link' |           when 'Link' | ||||||
|              redirect_to "http://#{@item[:url]}" |             redirect_to @item[:url] | ||||||
|         end |         end | ||||||
|       else |       else | ||||||
|         render :file => "#{Rails.root}/public/404.html", :status => :not_found |         render :file => "#{Rails.root}/public/404.html", :status => :not_found | ||||||
|  | @ -55,11 +57,7 @@ class PagesController < ApplicationController | ||||||
|     |     | ||||||
|    def get_item |    def get_item | ||||||
|       module_app = ModuleApp.first(:conditions => {:key => params[:app_name]}) |       module_app = ModuleApp.first(:conditions => {:key => params[:app_name]}) | ||||||
|       # if params[:category_id] |  | ||||||
|       #   @item = Item.first(:conditions => {:module_app_id => module_app.id, :app_frontend_url => params[:app_action], :category => params[:category_id]})   |  | ||||||
|       # else  |  | ||||||
|       @item = Item.first(:conditions => {:module_app_id => module_app.id, :app_frontend_url => params[:app_action]}) |       @item = Item.first(:conditions => {:module_app_id => module_app.id, :app_frontend_url => params[:app_action]}) | ||||||
|       # end |  | ||||||
|    end |    end | ||||||
|    |    | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,7 +1,8 @@ | ||||||
| class SessionsController < Devise::SessionsController | class SessionsController < Devise::SessionsController | ||||||
|   prepend_before_filter :require_no_authentication, :only => [ :new, :create ] |   prepend_before_filter :require_no_authentication, :only => [ :new, :create ] | ||||||
|   include Devise::Controllers::InternalHelpers |   include Devise::Controllers::InternalHelpers | ||||||
| 
 |   MiddleSiteConnection.establish | ||||||
|  |   NccuLdapConnection.establish | ||||||
| 
 | 
 | ||||||
|   # POST /resource/sign_in |   # POST /resource/sign_in | ||||||
|   def create  |   def create  | ||||||
|  | @ -10,42 +11,52 @@ class SessionsController < Devise::SessionsController | ||||||
|     login_password = params[:user][:password] |     login_password = params[:user][:password] | ||||||
|     login_uid = params[:user][:nccu_ldap_uid] |     login_uid = params[:user][:nccu_ldap_uid] | ||||||
|     result = false |     result = false | ||||||
|     ldap = Net::LDAP.new |  | ||||||
|     #ldap.port = '8001' |  | ||||||
|     #ldap.host = '127.0.0.1' |  | ||||||
|      ldap.port = '389'  |  | ||||||
|      ldap.host = '140.119.166.23'  |  | ||||||
|     ldap_filter = "(uid=#{login_uid})" |     ldap_filter = "(uid=#{login_uid})" | ||||||
|     ldap_base = 'ou=People,dc=nccu,dc=edu,dc=tw' |     if $nccu_ldap_connection.bind | ||||||
|     ldap.authenticate("cn=uccn,ou=profile,dc=nccu,dc=edu,dc=tw","nccu2ucc")  |         logger.info "=LDAP Binded password ok..." | ||||||
|     if ldap.bind && login_password!='' #need to block password empty |         result =check_auth_with_ldap(login_uid,login_password)  | ||||||
|         result = ldap.bind_as(:base => ldap_base,:filter => ldap_filter,:password=> login_password) |         if result && login_password!='' | ||||||
|         if result  |           logger.info "==LDAP  password passed..." | ||||||
|           nccu_id = get_nccu_id_from_mid_site(login_uid) |           nccu_id = get_nccu_id_from_mid_site(login_uid) | ||||||
|           resource =  nccu_id.nil? ? nil : (User.first(conditions:{ nccu_id: nccu_id })) |           resource =  nccu_id.nil? ? nil : (User.first(conditions:{ nccu_id: nccu_id })) | ||||||
|            # resource = env['warden'].authenticate!(:check_nccu_ldap) |            # resource = env['warden'].authenticate!(:check_nccu_ldap) | ||||||
|            # resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new") |            # resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new") | ||||||
|            set_flash_message(:notice, :signed_in) if is_navigational_format? |            set_flash_message(:notice, :signed_in) if is_navigational_format? | ||||||
|            if (resource.nil? || nccu_id.nil?) |            if (resource.nil? || nccu_id.nil?) | ||||||
|  |              logger.error "===LDAP passed local block... resource:#{resource.inspect}\n nccu_id:#{nccu_id} \t login_uid:#{login_uid}" | ||||||
|              flash[:notice] = t('devise.failure.ldap_pass_but_account_not_in_orbit') |              flash[:notice] = t('devise.failure.ldap_pass_but_account_not_in_orbit') | ||||||
|              render :action => "new" |              render :action => "new" | ||||||
|            else |            else | ||||||
|  |              logger.info "===ALL passed" | ||||||
|              resource_name = resource._type.downcase |              resource_name = resource._type.downcase | ||||||
|              sign_in(resource_name, resource) |              sign_in(resource_name, resource) | ||||||
|              respond_with resource, :location => redirect_location(resource_name, resource) |              respond_with resource, :location => redirect_location(resource_name, resource) | ||||||
|            end |            end | ||||||
|  |            elsif resource = User.first(conditions:{email: login_uid}) | ||||||
|  | 
 | ||||||
|  |              resource_name = resource._type.downcase | ||||||
|  |              sign_in(resource_name, resource) | ||||||
|  |              respond_with resource, :location => redirect_location(resource_name, resource) | ||||||
|         else |         else | ||||||
|  |           logger.error "==password LDAP fail..." | ||||||
|           flash[:notice] = t('devise.failure.ldap_invalid') |           flash[:notice] = t('devise.failure.ldap_invalid') | ||||||
|           render :action => "new"  |           render :action => "new"  | ||||||
|         end |         end | ||||||
|       else |       else | ||||||
|  |         logger.error "=LDAP fail..." | ||||||
|         flash[:notice] = t('devise.failure.ldap_connection_failed') |         flash[:notice] = t('devise.failure.ldap_connection_failed') | ||||||
|         render :action => "new" |         render :action => "new" | ||||||
|       end |       end | ||||||
|  |         logger.info "=======End Debugging======" | ||||||
|     end |     end | ||||||
| private   | private   | ||||||
|  |   def check_auth_with_ldap(login_uid,login_password) | ||||||
|  |     ldap_filter = "(uid=#{login_uid})" | ||||||
|  |     $nccu_ldap_connection.bind_as(:base => NccuLdapConnection::BASE,:filter => ldap_filter,:password=> login_password) rescue false | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   def get_nccu_id_from_mid_site(ldap_id) |   def get_nccu_id_from_mid_site(ldap_id) | ||||||
|     nccu_id = MID_CLIENT.query("SELECT nccu_id FROM rss_aaldap_view WHERE ldap_id='#{ldap_id}' LIMIT 1").first['nccu_id'] rescue nil |     nccu_id = $mid_site_connection.query("SELECT nccu_id FROM rss_aaldap_view WHERE ldap_id='#{ldap_id}' LIMIT 1").first['nccu_id'] rescue nil | ||||||
|         #  |         #  | ||||||
|         # if  nccu_id.nil? |         # if  nccu_id.nil? | ||||||
|         #   #show_error  |         #   #show_error  | ||||||
|  | @ -53,7 +64,7 @@ private | ||||||
|         #   #should return? |         #   #should return? | ||||||
|         # end |         # end | ||||||
|         # # User.first(conditions: {  }) |         # # User.first(conditions: {  }) | ||||||
|         # rss_pautlst_ut = MID_CLIENT.query("SELECT * FROM rss_pautlst_ut WHERE nccu_id='#{nccu_id}' LIMIT 1").first rescue nil |         # rss_pautlst_ut = $mid_site_connection.query("SELECT * FROM rss_pautlst_ut WHERE nccu_id='#{nccu_id}' LIMIT 1").first rescue nil | ||||||
|         # # rss_paunit = client.query("SELECT * FROM rss_paunit  LIMIT 1").first rescue nil |         # # rss_paunit = client.query("SELECT * FROM rss_paunit  LIMIT 1").first rescue nil | ||||||
|         # user = User.find_or_create_by(:nccu_id => nccu_id) |         # user = User.find_or_create_by(:nccu_id => nccu_id) | ||||||
|         #  p user |         #  p user | ||||||
|  |  | ||||||
|  | @ -3,26 +3,26 @@ module Admin::DashboardHelper | ||||||
| 	def get_link(title) | 	def get_link(title) | ||||||
| 		case title | 		case title | ||||||
| 			when 'bulletin' | 			when 'bulletin' | ||||||
| 				panel_announcement_back_end_bulletins_path | 				panel_announcement_front_end_bulletins_path | ||||||
| 			when 'news_bulletin' | 			when 'news_bulletin' | ||||||
| 				panel_news_back_end_news_bulletins_path | 				panel_news_front_end_news_bulletins_path | ||||||
| 			when'page_context' | 			when'page_context' | ||||||
| 				panel_page_content_back_end_page_contexts_path | 				panel_page_content_front_end_page_contexts_path | ||||||
| 			when'web_link' | 			when'web_link' | ||||||
| 				panel_web_resource_back_end_web_links_path | 				panel_web_resource_front_end_web_links_path | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| 	def get_link_to_object(object) | 	def get_link_to_object(object) | ||||||
| 		case object._type.underscore | 		case object._type.underscore | ||||||
| 			when 'bulletin' | 			when 'bulletin' | ||||||
| 				panel_announcement_back_end_bulletin_path(object) | 				panel_announcement_front_end_bulletin_path(object) | ||||||
| 			when 'news_bulletin' | 			when 'news_bulletin' | ||||||
| 				panel_news_back_end_news_bulletin_path(object) | 				panel_news_front_end_news_bulletin_path(object) | ||||||
| 			when'page_context' | 			when'page_context' | ||||||
| 				panel_page_content_back_end_page_context_path(object) | 				panel_page_content_front_end_page_context_path(object) | ||||||
| 			when'web_link' | 			when'web_link' | ||||||
| 				panel_web_resource_back_end_web_link_path(object) | 				panel_web_resource_front_end_web_link_path(object) | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -96,7 +96,6 @@ module ApplicationHelper | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def visible_for_controllers(*controller_names) |   def visible_for_controllers(*controller_names) | ||||||
|     puts controller_names |  | ||||||
|     (controller_names.include?(controller.controller_name) || controller_names.include?(request.fullpath)) ? '' : 'hide' |     (controller_names.include?(controller.controller_name) || controller_names.include?(request.fullpath)) ? '' : 'hide' | ||||||
|   end |   end | ||||||
|    |    | ||||||
|  | @ -173,4 +172,28 @@ module ApplicationHelper | ||||||
|     locale.to_sym == I18n.locale ? 'active in': '' |     locale.to_sym == I18n.locale ? 'active in': '' | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   def dislpay_view_count(object) | ||||||
|  |     "#{t(:view_count)}: #{object.view_count}" | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def display_visitors(options={}) | ||||||
|  |     Impression.where(options).distinct(:session_hash).count | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def display_visitors_today | ||||||
|  |     display_visitors(created_at: {'$gte' => Date.today.beginning_of_day, '$lte' => Date.today.end_of_day}) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def display_visitors_this_week | ||||||
|  |     display_visitors(created_at: {'$gte' => Date.today.beginning_of_week, '$lte' => Date.today.end_of_week}) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def display_visitors_this_month | ||||||
|  |     display_visitors(created_at: {'$gte' => Date.today.beginning_of_month, '$lte' => Date.today.end_of_month}) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def display_visitors_this_year | ||||||
|  |     display_visitors(created_at: {'$gte' => Date.today.beginning_of_year, '$lte' => Date.today.end_of_year}) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,12 +1,15 @@ | ||||||
| class NccuCalendar  | class NccuCalendar  | ||||||
|   require 'open-uri' |   require 'open-uri' | ||||||
|  |   require 'tempfile'   | ||||||
|  | 
 | ||||||
|   @queue = :high |   @queue = :high | ||||||
| 
 | 
 | ||||||
|   def self.perform() |   def self.perform() | ||||||
|   File.open(File.join(Rails.root, 'public/static', 'nccu_calendar.rss'),'w') do |file| |   temp_file = Tempfile.new('new_cal')   | ||||||
|     file << open('http://events.nccu.edu.tw/Feed').read |   temp_file << open('http://events.nccu.edu.tw/Month').read | ||||||
|     CronMail.time_check("NCCU Calendar synced").deliver | 
 | ||||||
|   end |    FileUtils.mv(temp_file, File.join(Rails.root, 'public/static', 'nccu_calendar.xml')) | ||||||
|  | 
 | ||||||
|     puts "NccuCalendar Synced" |     puts "NccuCalendar Synced" | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| class AdBanner | class AdBanner | ||||||
|   include OrbitCoreLib::ObjectAuthable |  | ||||||
|   include Mongoid::Document |   include Mongoid::Document | ||||||
|   include Mongoid::Timestamps |   include Mongoid::Timestamps | ||||||
|   include Mongoid::MultiParameterAttributes |   include Mongoid::MultiParameterAttributes | ||||||
|  |   include OrbitCoreLib::ObjectAuthable | ||||||
|    |    | ||||||
|   field :title |   field :title | ||||||
|   field :transition_msec,type: Integer |   field :transition_msec,type: Integer | ||||||
|  |  | ||||||
|  | @ -2,10 +2,20 @@ class Link < Item | ||||||
|    |    | ||||||
|   field :url |   field :url | ||||||
|    |    | ||||||
|   validates_presence_of :url |   validates :url, :presence => true, :format => /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/ix | ||||||
|  | 
 | ||||||
|  | 	before_validation :add_http | ||||||
| 
 | 
 | ||||||
|   def link |   def link | ||||||
|     ApplicationController.helpers.link_to(self.name, self.url) |     ApplicationController.helpers.link_to(self.name, self.url) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   protected | ||||||
|  | 
 | ||||||
|  | 	def add_http | ||||||
|  | 	  unless self.url[/^http?s:\/\//] | ||||||
|  | 	    self.url = 'http://' + self.url | ||||||
|  | 	  end | ||||||
|  | 	end | ||||||
|  |      | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,10 +1,14 @@ | ||||||
| class Page < Item | class Page < Item | ||||||
|  |   include Impressionist::Impressionable | ||||||
|  |    | ||||||
|  |   is_impressionable :counter_cache => { :column_name => :view_count } | ||||||
|    |    | ||||||
|   field :content |   field :content | ||||||
|   field :app_frontend_url |   field :app_frontend_url | ||||||
|   field :theme_id, :type => BSON::ObjectId, :default => nil |   field :theme_id, :type => BSON::ObjectId, :default => nil | ||||||
|   field :category |   field :category | ||||||
|   field :tag |   field :tag | ||||||
|  |   field :view_count, :type => Integer, :default => 0 | ||||||
|    |    | ||||||
|   belongs_to :design |   belongs_to :design | ||||||
|   belongs_to :module_app |   belongs_to :module_app | ||||||
|  |  | ||||||
|  | @ -380,49 +380,7 @@ | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="item element"> |      | ||||||
|         <h3><i class="icons-"></i><a href=""><%= t(:traffic) %></a></h3> |  | ||||||
|         <div class="detail w-a h-a"> |  | ||||||
|             <p class="totle"><span><%= t(:total_visitors) %></span>438,913</p> |  | ||||||
|             <table class="table table-striped"> |  | ||||||
|                 <thead> |  | ||||||
|                     <tr> |  | ||||||
|                         <th><%= t(:item) %></th> |  | ||||||
|                         <th class="span2"><%= t(:data) %></th> |  | ||||||
|                     </tr> |  | ||||||
|                 </thead> |  | ||||||
|             </table> |  | ||||||
|             <div class="detal-list my_scroll"> |  | ||||||
|                 <div class="scrollbar"> |  | ||||||
|                     <div class="track"> |  | ||||||
|                         <div class="thumb"> |  | ||||||
|                             <div class="end"></div> |  | ||||||
|                         </div> |  | ||||||
|                     </div> |  | ||||||
|                 </div> |  | ||||||
|                 <div class="viewport"> |  | ||||||
|                     <div class="overview"> |  | ||||||
|                         <table class="table table-striped"> |  | ||||||
|                             <tbody> |  | ||||||
|                                 <tr> |  | ||||||
|                                     <td>Visitors Today</td> |  | ||||||
|                                     <td>2,304</td> |  | ||||||
|                                 </tr> |  | ||||||
|                                 <tr> |  | ||||||
|                                     <td>Visitors This Month</td> |  | ||||||
|                                     <td>783</td> |  | ||||||
|                                 </tr> |  | ||||||
|                                 <tr> |  | ||||||
|                                     <td>Visitor This Tear</td> |  | ||||||
|                                     <td>45</td> |  | ||||||
|                                 </tr> |  | ||||||
|                             </tbody> |  | ||||||
|                         </table> |  | ||||||
|                     </div> |  | ||||||
|                 </div> |  | ||||||
|             </div> |  | ||||||
|         </div> |  | ||||||
|     </div> |  | ||||||
|     <div class="item element"> |     <div class="item element"> | ||||||
|         <h3><i class="icons-"></i><a href=""><%= t(:site_info) %></a></h3> |         <h3><i class="icons-"></i><a href=""><%= t(:site_info) %></a></h3> | ||||||
|         <div class="detail noStatistics w-b h-a"> |         <div class="detail noStatistics w-b h-a"> | ||||||
|  | @ -481,6 +439,56 @@ | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|     </div> --> |     </div> --> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     <div class="item element"> | ||||||
|  |         <h3><i class="icons-"></i><%= t(:traffic) %></h3> | ||||||
|  |         <div class="detail w-a h-a"> | ||||||
|  |             <p class="totle"><span><%= t(:total_visitors) %></span><%= display_visitors %></p> | ||||||
|  |             <table class="table table-striped"> | ||||||
|  |                 <thead> | ||||||
|  |                     <tr> | ||||||
|  |                         <th><%= t(:item) %></th> | ||||||
|  |                         <th class="span2"><%= t(:data) %></th> | ||||||
|  |                     </tr> | ||||||
|  |                 </thead> | ||||||
|  |             </table> | ||||||
|  |             <div class="detal-list my_scroll"> | ||||||
|  |                 <div class="scrollbar"> | ||||||
|  |                     <div class="track"> | ||||||
|  |                         <div class="thumb"> | ||||||
|  |                             <div class="end"></div> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="viewport"> | ||||||
|  |                     <div class="overview"> | ||||||
|  |                         <table class="table table-striped"> | ||||||
|  |                             <tbody> | ||||||
|  |                                 <tr> | ||||||
|  |                                     <td><%= t(:visitors_today) %></td> | ||||||
|  |                                     <td><%= display_visitors_today %></td> | ||||||
|  |                                 </tr> | ||||||
|  |                                 <tr> | ||||||
|  |                                     <td><%= t(:visitors_this_week) %></td> | ||||||
|  |                                     <td><%= display_visitors_this_week %></td> | ||||||
|  |                                 </tr> | ||||||
|  |                                 <tr> | ||||||
|  |                                     <td><%= t(:visitors_this_month) %></td> | ||||||
|  |                                     <td><%= display_visitors_this_month %></td> | ||||||
|  |                                 </tr> | ||||||
|  |                                 <tr> | ||||||
|  |                                     <td><%= t(:visitors_this_year) %></td> | ||||||
|  |                                     <td><%= display_visitors_this_year %></td> | ||||||
|  |                                 </tr> | ||||||
|  |                             </tbody> | ||||||
|  |                         </table> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|     <div class="item element"> |     <div class="item element"> | ||||||
|         <h3><i class="icons-"></i><%= t(:recent_update) %></h3> |         <h3><i class="icons-"></i><%= t(:recent_update) %></h3> | ||||||
|         <div class="detail noStatistics w-b h-a"> |         <div class="detail noStatistics w-b h-a"> | ||||||
|  | @ -517,4 +525,43 @@ | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  | 
 | ||||||
|  |     <div class="item element"> | ||||||
|  |         <h3><i class="icons-"></i><%= t(:most_visited_page) %></h3> | ||||||
|  |         <div class="detail noStatistics w-b h-a"> | ||||||
|  |             <table class="table table-striped"> | ||||||
|  |                 <thead> | ||||||
|  |                     <tr> | ||||||
|  |                         <th><%= t(:title) %></th> | ||||||
|  |                         <th class="span2"><%= t(:module) %></th> | ||||||
|  |                         <th class="span2"><%= t(:hits) %></th> | ||||||
|  |                     </tr> | ||||||
|  |                 </thead> | ||||||
|  |             </table> | ||||||
|  |             <div class="detal-list my_scroll"> | ||||||
|  |                 <div class="scrollbar"> | ||||||
|  |                     <div class="track"> | ||||||
|  |                         <div class="thumb"> | ||||||
|  |                             <div class="end"></div> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="viewport"> | ||||||
|  |                     <div class="overview"> | ||||||
|  |                         <table class="table table-striped"> | ||||||
|  |                             <tbody> | ||||||
|  |                                 <% @most_visited.each do |object| %> | ||||||
|  |                                     <tr> | ||||||
|  |                                         <td><%= link_to ((object[0].title[I18n.locale] rescue nil) || (object[0].page.i18n_variable[I18n.locale] rescue nil)), get_link_to_object(object[0]) %></td> | ||||||
|  |                                         <td class="span2"><%= link_to t("dashboard.#{object[0]._type.underscore}"), get_link(object[0]._type.underscore) %></td> | ||||||
|  |                                         <td class="span2"><%= object[1] %></td> | ||||||
|  |                                     </tr> | ||||||
|  |                                 <% end %> | ||||||
|  |                             </tbody> | ||||||
|  |                         </table> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
| </div> | </div> | ||||||
										
											Binary file not shown.
										
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | # Use this hook to configure impressionist parameters | ||||||
|  | Impressionist.setup do |config| | ||||||
|  |   # Define ORM. Could be :active_record (default) and :mongo_mapper | ||||||
|  |   # config.orm = :active_record | ||||||
|  |   config.orm = :mongoid | ||||||
|  | end | ||||||
|  | @ -1,14 +1,21 @@ | ||||||
| #encoding: utf-8 | #encoding: utf-8 | ||||||
| 
 |  | ||||||
| require 'mysql2' | require 'mysql2' | ||||||
| 
 | 
 | ||||||
|  | $mid_site_connection | ||||||
| 
 | 
 | ||||||
| mid_host = {  | module  MiddleSiteConnection | ||||||
|  | 
 | ||||||
|  |   @mid_host = {  | ||||||
|     :host => 'mruling.nccu.edu.tw',  #mruling.nccu.edu.tw or 127.0.0.1 |     :host => 'mruling.nccu.edu.tw',  #mruling.nccu.edu.tw or 127.0.0.1 | ||||||
|     :port => 3306, #3306 or 8005 |     :port => 3306, #3306 or 8005 | ||||||
|   :username => "root", |     :username => "rulingcom", | ||||||
|   :password => "a3G6yWd9", |     :password => "5w3iJQ9OJQMGhJibKP6YQje8", | ||||||
|     :database => "RSS23_NCCU_MIDDLE", |     :database => "RSS23_NCCU_MIDDLE", | ||||||
|     :encoding => "UTF8" |     :encoding => "UTF8" | ||||||
|   } |   } | ||||||
| MID_CLIENT = Mysql2::Client.new(mid_host) | 
 | ||||||
|  |   def self.establish | ||||||
|  |     $mid_site_connection = Mysql2::Client.new(@mid_host) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  | end | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | #encoding: utf-8 | ||||||
|  | require 'mysql2' | ||||||
|  | 
 | ||||||
|  | $nccu_ldap_connection | ||||||
|  | 
 | ||||||
|  | module  NccuLdapConnection | ||||||
|  |   BASE = 'ou=People,dc=nccu,dc=edu,dc=tw' | ||||||
|  | 
 | ||||||
|  |   @ldap_host = {  | ||||||
|  |     :host => '127.0.0.1',  #140.119.166.23 or 127.0.0.1 | ||||||
|  |     :port => 8001, #389 or 8001 | ||||||
|  |  #   :filter => "(uid=#{login_uid})", | ||||||
|  |  #   :base => "ou=People,dc=nccu,dc=edu,dc=tw", | ||||||
|  |     :authenticate_info => "cn=uccn,ou=profile,dc=nccu,dc=edu,dc=tw", | ||||||
|  |     :authenticate_pwd => "nccu2ucc" | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   def self.establish | ||||||
|  |     $nccu_ldap_connection = Net::LDAP.new | ||||||
|  |     $nccu_ldap_connection.port = @ldap_host[:port] | ||||||
|  |     $nccu_ldap_connection.host = @ldap_host[:host] | ||||||
|  |     $nccu_ldap_connection.authenticate(@ldap_host[:authenticate_info],@ldap_host[:authenticate_pwd])  | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  | end | ||||||
|  | @ -42,6 +42,7 @@ en: | ||||||
|   sure?: Are you sure? |   sure?: Are you sure? | ||||||
|   update: Update |   update: Update | ||||||
|   view: View |   view: View | ||||||
|  |   view_count: View count | ||||||
|   yes_: "Yes" |   yes_: "Yes" | ||||||
| 
 | 
 | ||||||
|   all_content: All Content |   all_content: All Content | ||||||
|  | @ -67,6 +68,11 @@ en: | ||||||
|   total_visitors: Total Visitors |   total_visitors: Total Visitors | ||||||
|   traffic: Traffic |   traffic: Traffic | ||||||
| 
 | 
 | ||||||
|  |   visitors_today: Today's visitors | ||||||
|  |   visitors_this_week: This week's visitors | ||||||
|  |   visitors_this_month: This month's visitors | ||||||
|  |   visitors_this_year: This year's visitors | ||||||
|  | 
 | ||||||
|   admin: |   admin: | ||||||
|     access: |     access: | ||||||
|       denied: |       denied: | ||||||
|  |  | ||||||
|  | @ -39,11 +39,12 @@ zh_tw: | ||||||
|   sure?: 您肯定嗎? |   sure?: 您肯定嗎? | ||||||
|   update: 更新 |   update: 更新 | ||||||
|   view: 檢視 |   view: 檢視 | ||||||
|  |   view_count: 查看次數 | ||||||
|   yes_: "Yes" |   yes_: "Yes" | ||||||
| 
 | 
 | ||||||
|   all_content: 全部內容有: |   all_content: 全部內容有 | ||||||
|   all_file: 全部檔案有: |   all_file: 全部檔案有 | ||||||
|   all_member: 成員總數: |   all_member: 成員總數 | ||||||
|   content: 內容 |   content: 內容 | ||||||
|   data: 數據 |   data: 數據 | ||||||
|   file: 檔案 |   file: 檔案 | ||||||
|  | @ -61,9 +62,14 @@ zh_tw: | ||||||
|   site_name: 網站名稱 |   site_name: 網站名稱 | ||||||
|   statistics: 統計 |   statistics: 統計 | ||||||
|   title: 標題 |   title: 標題 | ||||||
|   total_visitors: 造訪次數: |   total_visitors: 造訪次數 | ||||||
|   traffic: 流量 |   traffic: 流量 | ||||||
| 
 | 
 | ||||||
|  |   visitors_today: 今日造訪 | ||||||
|  |   visitors_this_week: 本星期造訪 | ||||||
|  |   visitors_this_month: 本月造訪 | ||||||
|  |   visitors_this_year: 今年造訪 | ||||||
|  | 
 | ||||||
|   admin: |   admin: | ||||||
|     access: |     access: | ||||||
|       denied: |       denied: | ||||||
|  |  | ||||||
|  | @ -27,7 +27,8 @@ module ParserCommon | ||||||
|     res << "_#{i}" if i |     res << "_#{i}" if i | ||||||
|     res << " active" if (current_page.id.eql?(page.id) || current_page.descendant_of?(page)) |     res << " active" if (current_page.id.eql?(page.id) || current_page.descendant_of?(page)) | ||||||
|     res << "'>" |     res << "'>" | ||||||
|     res << "<a href='/#{edit ? admin_page_path(page.id) : page.path}'><span>#{page.i18n_variable[I18n.locale]}</span></a>" |     root = "/" | ||||||
|  |     res << "<a href='#{edit ? root + admin_page_path(page.id) : (page._type.eql?('Page') ? root + page.path : page.url)}'><span>#{page.i18n_variable[I18n.locale]}</span></a>" | ||||||
|     if page.visible_children.size > 0 && current <= menu.levels |     if page.visible_children.size > 0 && current <= menu.levels | ||||||
|       res << "<span class='dot'></span>" |       res << "<span class='dot'></span>" | ||||||
|       res << menu_level(page, current_page, current + 1, menu, edit) |       res << menu_level(page, current_page, current + 1, menu, edit) | ||||||
|  | @ -119,7 +120,8 @@ module ParserCommon | ||||||
|         res << "<ul class='list'>" |         res << "<ul class='list'>" | ||||||
|         menu_page.visible_children.each do |child| |         menu_page.visible_children.each do |child| | ||||||
|           res << "<li class='#{page.id.eql?(child.id) ? 'active' : nil}'>" |           res << "<li class='#{page.id.eql?(child.id) ? 'active' : nil}'>" | ||||||
|           res << "<a href='/#{edit ? admin_page_path(child.id) : child.path}'>#{child.i18n_variable[I18n.locale]}</a>" |           root = "/" | ||||||
|  |           res << "<a href='#{edit ? root + admin_page_path(child.id) : (child._type.eql?('Page') ? root + child.path : child.url)}'>#{child.i18n_variable[I18n.locale]}</a>" | ||||||
|           res << "</li>" |           res << "</li>" | ||||||
|         end |         end | ||||||
|         res << "</ul>" |         res << "</ul>" | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| # encoding: utf-8  | # encoding: utf-8  | ||||||
| # require 'ruby-debug' | # require 'ruby-debug' | ||||||
|  | require "#{Rails.root}/config/initializers/middle_site_connection" | ||||||
| 
 | 
 | ||||||
| namespace :mid_site do | namespace :mid_site do | ||||||
|   desc "mid_site Rake task" |   desc "mid_site Rake task" | ||||||
|  | @ -8,7 +9,7 @@ namespace :mid_site do | ||||||
|   admin_role = nil |   admin_role = nil | ||||||
|   sub_role = nil |   sub_role = nil | ||||||
|   test_account_ldap_id ='139716' |   test_account_ldap_id ='139716' | ||||||
| 
 |  MiddleSiteConnection.establish | ||||||
|    |    | ||||||
|   task :sync => :environment do |   task :sync => :environment do | ||||||
|     info_profile = Info.first(conditions: {:key => 'profile'}) |     info_profile = Info.first(conditions: {:key => 'profile'}) | ||||||
|  | @ -27,8 +28,8 @@ namespace :mid_site do | ||||||
|       sub_role |       sub_role | ||||||
|     end |     end | ||||||
|      |      | ||||||
|     users_from_mid = MID_CLIENT.query("SELECT #{attr_from_mid.join(',')} FROM rss_pautlst_ut  WHERE posgrp_cod IN (#{officer_posgrp_code.join(',')})")  |     users_from_mid = $mid_site_connection.query("SELECT #{attr_from_mid.join(',')} FROM rss_pautlst_ut  WHERE posgrp_cod IN (#{officer_posgrp_code.join(',')})")  | ||||||
|     ut_data_from_mid = MID_CLIENT.query("SELECT ut_odr, ut_cod, up_ut_cod, ut_chi_m, ut_eng_m FROM rss_paunit WHERE ut_tpe =  '1' AND ut_grp !=  '3' AND up_ut_cod !=  'F00' ORDER BY ut_odr, ut_cod")    |     ut_data_from_mid = $mid_site_connection.query("SELECT ut_odr, ut_cod, up_ut_cod, ut_chi_m, ut_eng_m FROM rss_paunit WHERE ut_tpe =  '1' AND ut_grp !=  '3' AND up_ut_cod !=  'F00' ORDER BY ut_odr, ut_cod")    | ||||||
|     remote_list = users_from_mid.collect{|t| t["nccu_id"]} |     remote_list = users_from_mid.collect{|t| t["nccu_id"]} | ||||||
|      |      | ||||||
|     #remove delete user sho has been deleted at remote first |     #remove delete user sho has been deleted at remote first | ||||||
|  | @ -72,7 +73,7 @@ namespace :mid_site do | ||||||
|     # admin_role = Role.find_or_create_by( key: 'administrator') |     # admin_role = Role.find_or_create_by( key: 'administrator') | ||||||
|     # sub_role = admin_role.sub_roles.find_or_create_by(:key => 'computer_center') |     # sub_role = admin_role.sub_roles.find_or_create_by(:key => 'computer_center') | ||||||
|      |      | ||||||
|     user_from_mid = MID_CLIENT.query("SELECT #{attr_from_mid.join(',')} FROM rss_pautlst_ut  WHERE posgrp_cod IN (#{officer_posgrp_code.join(',')}) AND nccu_id = '#{admins_nccu_id}' limit 1")     |     user_from_mid = $mid_site_connection.query("SELECT #{attr_from_mid.join(',')} FROM rss_pautlst_ut  WHERE posgrp_cod IN (#{officer_posgrp_code.join(',')}) AND nccu_id = '#{admins_nccu_id}' limit 1")     | ||||||
|     admin_at_mid =  user_from_mid.first |     admin_at_mid =  user_from_mid.first | ||||||
|     user_first_name = admin_at_mid["psn_nam"].size > 3 ? admin_at_mid["psn_nam"][3..-1] : admin_at_mid["psn_nam"][1..-1] |     user_first_name = admin_at_mid["psn_nam"].size > 3 ? admin_at_mid["psn_nam"][3..-1] : admin_at_mid["psn_nam"][1..-1] | ||||||
|     user_last_name =  admin_at_mid["psn_nam"].size  > 3 ? admin_at_mid["psn_nam"][1..2] : admin_at_mid["psn_nam"][0] |     user_last_name =  admin_at_mid["psn_nam"].size  > 3 ? admin_at_mid["psn_nam"][1..2] : admin_at_mid["psn_nam"][0] | ||||||
|  | @ -95,7 +96,7 @@ namespace :mid_site do | ||||||
|     # sub_role = admin_role.sub_roles.find_or_create_by(:key => 'computer_center') |     # sub_role = admin_role.sub_roles.find_or_create_by(:key => 'computer_center') | ||||||
|     info_profile = Info.first(conditions: {:key => 'profile'}) |     info_profile = Info.first(conditions: {:key => 'profile'}) | ||||||
|      |      | ||||||
|     user_from_mid = MID_CLIENT.query("SELECT #{attr_from_mid.join(',')} FROM rss_pautlst_ut  WHERE  nccu_id = '#{admins_nccu_id}' limit 1")     |     user_from_mid = $mid_site_connection.query("SELECT #{attr_from_mid.join(',')} FROM rss_pautlst_ut  WHERE  nccu_id = '#{admins_nccu_id}' limit 1")     | ||||||
|     admin_at_mid =  user_from_mid.first |     admin_at_mid =  user_from_mid.first | ||||||
|     user_first_name = admin_at_mid["psn_nam"].size > 3 ? admin_at_mid["psn_nam"][3..-1] : admin_at_mid["psn_nam"][1..-1] |     user_first_name = admin_at_mid["psn_nam"].size > 3 ? admin_at_mid["psn_nam"][3..-1] : admin_at_mid["psn_nam"][1..-1] | ||||||
|     user_last_name =  admin_at_mid["psn_nam"].size  > 3 ? admin_at_mid["psn_nam"][1..2] : admin_at_mid["psn_nam"][0] |     user_last_name =  admin_at_mid["psn_nam"].size  > 3 ? admin_at_mid["psn_nam"][1..2] : admin_at_mid["psn_nam"][0] | ||||||
|  |  | ||||||
|  | @ -1,64 +0,0 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> |  | ||||||
|   <title>國立政治大學校園活動行事曆</title> |  | ||||||
|   <link rel="alternate" href="http://events.nccu.edu.tw/" /> |  | ||||||
|   <subtitle>本日最新活動</subtitle> |  | ||||||
|   <dc:language>zh-tw</dc:language> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-「框」住瞬間「框」住世界</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2901&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/01-101/05/08 00:00-23:59</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-環友世界</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2902&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/01-101/05/10 00:00-23:59</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-從政大看台灣</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2903&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/01-101/05/10 08:00-22:00</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-美食嘉年華</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2905&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/08-101/05/10 12:00-14:00</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-「原,夜」晚會</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2906&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/08 19:00-21:00</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-開幕式</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2907&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/08 12:10-13:30</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>職場講座「數位文本實務課程」</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2874&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/04/24-101/05/15 12:20-13:50</summary> |  | ||||||
|   </entry> |  | ||||||
| </feed> |  | ||||||
| 
 |  | ||||||
|  | @ -2,63 +2,303 @@ | ||||||
| <feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> | <feed xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> | ||||||
|   <title>國立政治大學校園活動行事曆</title> |   <title>國立政治大學校園活動行事曆</title> | ||||||
|   <link rel="alternate" href="http://events.nccu.edu.tw/" /> |   <link rel="alternate" href="http://events.nccu.edu.tw/" /> | ||||||
|   <subtitle>本日最新活動</subtitle> |   <subtitle>本月最新活動</subtitle> | ||||||
|   <dc:language>zh-tw</dc:language> |   <dc:language>zh-tw</dc:language> | ||||||
|   <entry> |   <entry> | ||||||
|     <title>2012年世界狂歡節-「框」住瞬間「框」住世界</title> |     <title>「系際盃拔河賽」活動</title> | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2901&key2=20120508" /> |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2944&key2=20120515" /> | ||||||
|     <author> |     <author> | ||||||
|       <name /> |       <name /> | ||||||
|     </author> |     </author> | ||||||
|     <summary type="text">101/05/01-101/05/08 00:00-23:59</summary> |     <summary type="text">101/05/14-101/05/16 12:00-14:00</summary> | ||||||
|   </entry> |   </entry> | ||||||
|   <entry> |   <entry> | ||||||
|     <title>2012年世界狂歡節-環友世界</title> |     <title>LEXUS百萬挑戰賽校園巡迴說明會</title> | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2902&key2=20120508" /> |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2927&key2=20120515" /> | ||||||
|     <author> |     <author> | ||||||
|       <name /> |       <name /> | ||||||
|     </author> |     </author> | ||||||
|     <summary type="text">101/05/01-101/05/10 00:00-23:59</summary> |     <summary type="text">101/05/15 12:00-12:45</summary> | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-從政大看台灣</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2903&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/01-101/05/10 08:00-22:00</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-美食嘉年華</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2905&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/08-101/05/10 12:00-14:00</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-「原,夜」晚會</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2906&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/08 19:00-21:00</summary> |  | ||||||
|   </entry> |  | ||||||
|   <entry> |  | ||||||
|     <title>2012年世界狂歡節-開幕式</title> |  | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2907&key2=20120508" /> |  | ||||||
|     <author> |  | ||||||
|       <name /> |  | ||||||
|     </author> |  | ||||||
|     <summary type="text">101/05/08 12:10-13:30</summary> |  | ||||||
|   </entry> |   </entry> | ||||||
|   <entry> |   <entry> | ||||||
|     <title>職場講座「數位文本實務課程」</title> |     <title>職場講座「數位文本實務課程」</title> | ||||||
|     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2874&key2=20120508" /> |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2874&key2=20120515" /> | ||||||
|     <author> |     <author> | ||||||
|       <name /> |       <name /> | ||||||
|     </author> |     </author> | ||||||
|     <summary type="text">101/04/24-101/05/15 12:20-13:50</summary> |     <summary type="text">101/04/24-101/05/15 12:20-13:50</summary> | ||||||
|   </entry> |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>「系際盃拔河賽」活動</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2944&key2=20120516" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/14-101/05/16 12:00-14:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>85週年校慶運動會</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2945&key2=20120517" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/17-101/05/18 08:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>85週年校慶運動會</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2945&key2=20120518" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/17-101/05/18 08:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>2012年福祿貝爾恩物親子戲遊成長團體(上午)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2833&key2=20120519" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/04/07-101/06/02 09:00-11:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>2012年福祿貝爾恩物親子戲遊成長團體(下午)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2834&key2=20120519" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/04/07-101/06/09 14:00-16:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>商學院羽球賽</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2946&key2=20120520" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/20 08:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>期末舞展/彩排</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2928&key2=20120522" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">政治大學熱舞社17th成果發表 《i》6:30入場</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>期末舞展/彩排</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2928&key2=20120523" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">政治大學熱舞社17th成果發表 《i》6:30入場</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>★特優TA教學觀摩(不動產投資與市場分析)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2932&key2=20120524" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/24 12:10-13:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>文化講座「破戒:關於『色•戒』的實與虛」</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2875&key2=20120524" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/24 12:20-14:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>團隊導向學習(TBL)及Campus Pasck研習工作坊</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2941&key2=20120525" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/25 12:00-14:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>青春活力校園展演(歌仔戲):《馴夫記》</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2942&key2=20120525" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/25 19:00-21:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>國際交流足球聯賽</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2948&key2=20120526" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/26 08:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>政大盃桌球賽</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2949&key2=20120526" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/26 08:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>2012年福祿貝爾恩物親子戲遊成長團體(上午)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2833&key2=20120526" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/04/07-101/06/02 09:00-11:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>五院盃羽球賽</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2947&key2=20120526" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/26 09:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>TOEIC英語測驗校園考</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2872&key2=20120526" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/26 09:30-12:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>2012年福祿貝爾恩物親子戲遊成長團體(下午)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2834&key2=20120526" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/04/07-101/06/09 14:00-16:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>期末公演</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2736&key2=20120526" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">2012/5/26  13:00入場  13:30開始</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>傳播學院媒體參訪(二)壹電視</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2916&key2=20120530" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/30 14:00-16:30</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>國樂講座—國樂演奏會【故鄉情】</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2897&key2=20120530" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/05/30 19:30-21:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>2012年福祿貝爾恩物親子戲遊成長團體(上午)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2833&key2=20120602" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/04/07-101/06/02 09:00-11:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>100學年畢業典禮</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2405&key2=20120602" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/02 09:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>100學年度文學院研究所畢業生撥穗典禮</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2937&key2=20120602" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/02 10:00-11:30</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>100學年度文學院大學部畢業生撥穗典禮</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2958&key2=20120602" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/02 12:00-13:30</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>2012年福祿貝爾恩物親子戲遊成長團體(下午)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2834&key2=20120602" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/04/07-101/06/09 14:00-16:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>往內在旅行,尋覓你的人格風景</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2961&key2=20120603" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/03 09:00-16:30</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>政大講座論壇:東亞模式的民法典?(蘇永欽講座教授)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2962&key2=20120604" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/04 10:10-11:50</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>國際學院運動會</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2951&key2=20120609" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/09 08:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>IELTS雅思校園考</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2871&key2=20120609" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/09 09:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>政橄隊慶</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2952&key2=20120609" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/09 11:00-18:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>傳院頂大計畫「與未來對話:新的使用者體驗」交流會</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2939&key2=20120609" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/09 13:00-17:30</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>2012年福祿貝爾恩物親子戲遊成長團體(下午)</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2834&key2=20120609" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/04/07-101/06/09 14:00-16:00</summary> | ||||||
|  |   </entry> | ||||||
|  |   <entry> | ||||||
|  |     <title>商院盃排球賽</title> | ||||||
|  |     <link rel="alternate" href="http://events.nccu.edu.tw/more.do?key=2954&key2=20120610" /> | ||||||
|  |     <author> | ||||||
|  |       <name /> | ||||||
|  |     </author> | ||||||
|  |     <summary type="text">101/06/10 08:00-17:00</summary> | ||||||
|  |   </entry> | ||||||
| </feed> | </feed> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ class Panel::Announcement::FrontEnd::BulletinsController < OrbitWidgetController | ||||||
|       preview_content |       preview_content | ||||||
|     else |     else | ||||||
|       @bulletin = Bulletin.can_display.where(_id: params[:id]).first |       @bulletin = Bulletin.can_display.where(_id: params[:id]).first | ||||||
|  |       impressionist(@bulletin) | ||||||
|       get_categorys |       get_categorys | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,9 @@ class Bulletin | ||||||
|   include Mongoid::Document |   include Mongoid::Document | ||||||
|   include Mongoid::Timestamps |   include Mongoid::Timestamps | ||||||
|   include Mongoid::MultiParameterAttributes |   include Mongoid::MultiParameterAttributes | ||||||
|  |   include Impressionist::Impressionable | ||||||
|  | 
 | ||||||
|  |   is_impressionable :counter_cache => { :column_name => :view_count } | ||||||
| 
 | 
 | ||||||
|   has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy |   has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy | ||||||
|   has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy |   has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy | ||||||
|  | @ -23,6 +26,7 @@ class Bulletin | ||||||
|   field :is_pending, :type => Boolean, :default => true  |   field :is_pending, :type => Boolean, :default => true  | ||||||
|   field :is_rejected, :type => Boolean, :default => false  |   field :is_rejected, :type => Boolean, :default => false  | ||||||
| 
 | 
 | ||||||
|  |   field :view_count, :type => Integer, :default => 0 | ||||||
|    |    | ||||||
|   field :not_checked_reason |   field :not_checked_reason | ||||||
|    |    | ||||||
|  |  | ||||||
|  | @ -99,12 +99,6 @@ | ||||||
| 							<% end %> | 							<% end %> | ||||||
| 						<% end %> | 						<% end %> | ||||||
| 					</p> | 					</p> | ||||||
| 		           	<span class="label label-tags">Default<a href><i class="icon-remove icon-white"></i></a></span> |  | ||||||
| 		           	<span class="label label-tags">Default<a href><i class="icon-remove icon-white"></i></a></span> |  | ||||||
| 		           	<span class="label label-tags">Default<a href><i class="icon-remove icon-white"></i></a></span> |  | ||||||
| 		           	<span class="label label-tags">Default<a href><i class="icon-remove icon-white"></i></a></span> |  | ||||||
| 		            <hr> |  | ||||||
| 					<input type="text" class="input-xlarge"> |  | ||||||
| 				</div> | 				</div> | ||||||
| 		</div>  | 		</div>  | ||||||
|   	<% if params[:action] != 'new' %> |   	<% if params[:action] != 'new' %> | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| 		<span class="date"><%= @bulletin.postdate %></span> | 		<span class="date"><%= @bulletin.postdate %></span> | ||||||
| 		 |  | 		 |  | ||||||
| 		<a href="" class="unit"><%= User.find(@bulletin.create_user_id).sub_roles.collect{|t| t.key}.join(" ") rescue '' %></a> | 		<a href="" class="unit"><%= User.find(@bulletin.create_user_id).sub_roles.collect{|t| t.key}.join(" ") rescue '' %></a> | ||||||
|  | 		<span><%= dislpay_view_count(@bulletin) %></span> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| <div class="news_image"> | <div class="news_image"> | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ class Panel::News::FrontEnd::NewsBulletinsController < OrbitWidgetController | ||||||
|       preview_content |       preview_content | ||||||
|     else |     else | ||||||
|       @news_bulletin = NewsBulletin.can_display.where(_id: params[:id]).first |       @news_bulletin = NewsBulletin.can_display.where(_id: params[:id]).first | ||||||
|  |       impressionist(@news_bulletin) | ||||||
|       get_categorys |       get_categorys | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  | @ -4,6 +4,9 @@ class NewsBulletin | ||||||
|   include Mongoid::Document |   include Mongoid::Document | ||||||
|   include Mongoid::Timestamps |   include Mongoid::Timestamps | ||||||
|   include Mongoid::MultiParameterAttributes   |   include Mongoid::MultiParameterAttributes   | ||||||
|  |   include Impressionist::Impressionable | ||||||
|  | 
 | ||||||
|  |   is_impressionable :counter_cache => { :column_name => :view_count } | ||||||
| 
 | 
 | ||||||
|   has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy |   has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy | ||||||
|   has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy |   has_one :subtitle, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy | ||||||
|  | @ -23,6 +26,7 @@ class NewsBulletin | ||||||
|   field :is_pending, :type => Boolean, :default => true  |   field :is_pending, :type => Boolean, :default => true  | ||||||
|   field :is_rejected, :type => Boolean, :default => false  |   field :is_rejected, :type => Boolean, :default => false  | ||||||
| 
 | 
 | ||||||
|  |   field :view_count, :type => Integer, :default => 0 | ||||||
|    |    | ||||||
|   field :not_checked_reason |   field :not_checked_reason | ||||||
|    |    | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| 		<span class="date"><%= @news_bulletin.postdate %></span> | 		<span class="date"><%= @news_bulletin.postdate %></span> | ||||||
| 		 |  | 		 |  | ||||||
| 		<a href="" class="unit"><%= @news_bulletin.unit_list_for_anc.title[I18n.locale] rescue '' %></a> | 		<a href="" class="unit"><%= @news_bulletin.unit_list_for_anc.title[I18n.locale] rescue '' %></a> | ||||||
|  | 		<span><%= dislpay_view_count(@news_bulletin) %></span> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| <div class="news_image"> | <div class="news_image"> | ||||||
|  |  | ||||||
|  | @ -6,9 +6,9 @@ class Panel::PageContent::FrontEnd::PageContextsController < OrbitWidgetControll | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def index |   def index | ||||||
| 	 |  | ||||||
|     # @page_context = PageContext.where("page_id" => params[:page_id], :archived => false) |     # @page_context = PageContext.where("page_id" => params[:page_id], :archived => false) | ||||||
|     @page_context = PageContext.first(conditions: { page_id: params[:page_id], :archived => false }) |     @page_context = PageContext.first(conditions: { page_id: params[:page_id], :archived => false }) | ||||||
|  |     impressionist(@page_context) | ||||||
|      |      | ||||||
|     respond_to do |format| |     respond_to do |format| | ||||||
|       format.html # index.html.erb |       format.html # index.html.erb | ||||||
|  |  | ||||||
|  | @ -4,15 +4,17 @@ class PageContext | ||||||
|   include Mongoid::Document |   include Mongoid::Document | ||||||
|   include Mongoid::Timestamps |   include Mongoid::Timestamps | ||||||
|   include Mongoid::MultiParameterAttributes |   include Mongoid::MultiParameterAttributes | ||||||
| 
 |   include Impressionist::Impressionable | ||||||
|   include OrbitCoreLib::ObjectAuthable |   include OrbitCoreLib::ObjectAuthable | ||||||
| 
 | 
 | ||||||
|  |   is_impressionable :counter_cache => { :column_name => :view_count } | ||||||
| 
 | 
 | ||||||
|   has_one :context, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy |   has_one :context, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy | ||||||
| 
 | 
 | ||||||
|   field :create_user_id |   field :create_user_id | ||||||
|   field :update_user_id |   field :update_user_id | ||||||
|   field :version, :type => Integer , :default => 0 |   field :version, :type => Integer , :default => 0 | ||||||
|  |   field :view_count, :type => Integer, :default => 0 | ||||||
|    |    | ||||||
|   field :archived, :type => Boolean, :default => false |   field :archived, :type => Boolean, :default => false | ||||||
|   # field :current, :type => Boolean, :default => false |   # field :current, :type => Boolean, :default => false | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| 
 |  | ||||||
| <tr id="<%= dom_id page_context %>" class="with_action"> | <tr id="<%= dom_id page_context %>" class="with_action"> | ||||||
| 	<td> | 	<td> | ||||||
| 					<%= page_context.page.path %> | 		<%= page_context.page.path %></br> | ||||||
|  | 		<%= page_context.page.i18n_variable[I18n.locale] %> | ||||||
| 		<div class="quick-edit"> | 		<div class="quick-edit"> | ||||||
| 			<ul class="nav nav-pills hide"> | 			<ul class="nav nav-pills hide"> | ||||||
| 				<%if is_manager? || is_admin? ||  page_context.authed_users(:edit).include?(current_user)%> | 				<%if is_manager? || is_admin? ||  page_context.authed_users(:edit).include?(current_user)%> | ||||||
|  |  | ||||||
|  | @ -6,3 +6,5 @@ | ||||||
| <h1 class="h1"><%= @page_context.page.i18n_variable[I18n.locale] rescue nil %></h1> | <h1 class="h1"><%= @page_context.page.i18n_variable[I18n.locale] rescue nil %></h1> | ||||||
| 
 | 
 | ||||||
| <div class="page_content"><%= @page_context.context[I18n.locale].html_safe rescue nil %></div> | <div class="page_content"><%= @page_context.context[I18n.locale].html_safe rescue nil %></div> | ||||||
|  | 
 | ||||||
|  | <div><%= dislpay_view_count(@page_context) %></div> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | *~ | ||||||
|  | /coverage | ||||||
|  | /pkg | ||||||
|  | /rdoc | ||||||
|  | /test_app/db/schema.rb | ||||||
|  | /test_app/db/migrate/*_create_impressions_table.rb | ||||||
|  | /test_app/doc | ||||||
|  | /test_app/test | ||||||
|  | /test_app/vendor | ||||||
|  | Gemfile.lock | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | --color | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | before_install: gem install bundler | ||||||
|  | before_script: "cd test_app && bundle install && ./script/rails generate impressionist && bundle exec rake db:migrate && cd .." | ||||||
|  | language: ruby | ||||||
|  | rvm: | ||||||
|  |   - rbx-18mode | ||||||
|  |   - rbx-19mode | ||||||
|  |   - jruby-18mode | ||||||
|  |   - 1.8.7 | ||||||
|  |   - 1.9.2 | ||||||
|  |   - 1.9.3 | ||||||
|  |   - ruby-head | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | == 0.4.0 (2011-06-03) | ||||||
|  | * Fix postgres bug | ||||||
|  | * New impression count method that accepts options for filter, start_date and end_date | ||||||
|  | * Add referrer to Impression model.  YOU MUST RUN THE UPGRADE MIGRATION IF YOU ARE UPGRADING FROM 0.3.0 | ||||||
|  | * UPGRADE MIGRATION = impressionist/upgrade_migrations/version_0_4_0.rb | ||||||
|  | * NOTE IF YOU ARE UPGRADING FROM 0.2.5 OR BELOW, YOU MUST RUN BOTH UPGRADE MIGRATIONS | ||||||
|  | 
 | ||||||
|  | == 0.3.0 (2011-03-06) | ||||||
|  | * added session_hash to impression model | ||||||
|  | * migration template updated to add session_hash | ||||||
|  | * new count instance method for impressionable model - unique_impression_count_session | ||||||
|  | * NOTE: if you are upgrading from 0.2.5, then run the migration in the 'upgrade_migrations' dir | ||||||
|  | 
 | ||||||
|  | == 0.2.5 (2011-02-17) | ||||||
|  | * New model method - @widget.unique_impression_count_ip  - This gives you unique impression account filtered by IP (and in turn request_hash since they have same IPs) | ||||||
|  | * @widget.unique_impression_count now uses request_hash.  This was incorrectly stated in the README, since it was using ip_address.  The README is correct as a result of the method change. | ||||||
|  | 
 | ||||||
|  | == 0.2.4 (2011-02-17) | ||||||
|  | * Fix issue #1 - action_name and controller_name were not being logged for impressionist method inside action | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | source 'https://rubygems.org' | ||||||
|  | 
 | ||||||
|  | platforms :jruby do | ||||||
|  |   gem 'activerecord-jdbcsqlite3-adapter' | ||||||
|  |   gem 'jdbc-sqlite3' | ||||||
|  |   gem 'jruby-openssl' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | platforms :ruby, :mswin, :mingw do | ||||||
|  |   # gem 'sqlite3' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | gemspec | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | Copyright (c) 2011 cowboycoded | ||||||
|  | 
 | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining | ||||||
|  | a copy of this software and associated documentation files (the | ||||||
|  | "Software"), to deal in the Software without restriction, including | ||||||
|  | without limitation the rights to use, copy, modify, merge, publish, | ||||||
|  | distribute, sublicense, and/or sell copies of the Software, and to | ||||||
|  | permit persons to whom the Software is furnished to do so, subject to | ||||||
|  | the following conditions: | ||||||
|  | 
 | ||||||
|  | The above copyright notice and this permission notice shall be | ||||||
|  | included in all copies or substantial portions of the Software. | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||||
|  | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||||
|  | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||||
|  | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||||
|  | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||||
|  | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||||
|  | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||||
|  | @ -0,0 +1,198 @@ | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | [](http://travis-ci.org/charlotte-ruby/impressionist) | ||||||
|  | 
 | ||||||
|  | impressionist | ||||||
|  | ============= | ||||||
|  | 
 | ||||||
|  | A lightweight plugin that logs impressions per action or manually per model | ||||||
|  | 
 | ||||||
|  | -------------------------------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | What does this thing do? | ||||||
|  | ------------------------ | ||||||
|  | Logs an impression... and I use that term loosely.  It can log page impressions | ||||||
|  | (technically action impressions), but it is not limited to that. You can log | ||||||
|  | impressions multiple times per request.  And you can also attach it to a model. | ||||||
|  | The goal of this project is to provide customizable stats that are immediately | ||||||
|  | accessible in your application as opposed to using Google Analytics and pulling | ||||||
|  | data using their API.  You can attach custom messages to impressions.  No | ||||||
|  | reporting yet.. this thingy just creates the data. | ||||||
|  | 
 | ||||||
|  | What about bots? | ||||||
|  | ---------------- | ||||||
|  | They are ignored.  1200 known bots have been added to the ignore list as of | ||||||
|  | February 1, 2011.  Impressionist uses this list: | ||||||
|  | http://www.user-agents.org/allagents.xml | ||||||
|  | 
 | ||||||
|  | Installation | ||||||
|  | ------------ | ||||||
|  | Add it to your Gemfile | ||||||
|  | 
 | ||||||
|  |     gem 'impressionist' | ||||||
|  | 
 | ||||||
|  | Install with Bundler | ||||||
|  | 
 | ||||||
|  |     bundle install | ||||||
|  | 
 | ||||||
|  | Generate the impressions table migration | ||||||
|  | 
 | ||||||
|  |     rails g impressionist | ||||||
|  | 
 | ||||||
|  | Run the migration | ||||||
|  | 
 | ||||||
|  |     rake db:migrate | ||||||
|  | 
 | ||||||
|  | The following fields are provided in the migration: | ||||||
|  | 
 | ||||||
|  |     t.string   "impressionable_type"  # model type: Widget | ||||||
|  |     t.integer  "impressionable_id"    # model instance ID: @widget.id | ||||||
|  |     t.integer  "user_id"              # automatically logs @current_user.id | ||||||
|  |     t.string   "controller_name"      # logs the controller name | ||||||
|  |     t.string   "action_name"          # logs the action_name | ||||||
|  |     t.string   "view_name"            # TODO: log individual views (as well as partials and nested partials) | ||||||
|  |     t.string   "request_hash"         # unique ID per request, in case you want to log multiple impressions and group them | ||||||
|  |     t.string   "session_hash"         # logs the rails session | ||||||
|  |     t.string   "ip_address"           # request.remote_ip | ||||||
|  |     t.string   "referrer"             # request.referer | ||||||
|  |     t.string   "message"              # custom message you can add | ||||||
|  |     t.datetime "created_at"           # I am not sure what this is.... Any clue? | ||||||
|  |     t.datetime "updated_at"           # never seen this one before either....  Your guess is as good as mine?? | ||||||
|  | 
 | ||||||
|  | Usage | ||||||
|  | ----- | ||||||
|  | 
 | ||||||
|  | 1. Log all actions in a controller | ||||||
|  | 
 | ||||||
|  |         WidgetsController < ApplicationController | ||||||
|  |           impressionist | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  | 2. Specify actions you want logged in a controller | ||||||
|  | 
 | ||||||
|  |         WidgetsController < ApplicationController | ||||||
|  |           impressionist :actions=>[:show,:index] | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  | 3. Make your models impressionable.  This allows you to attach impressions to | ||||||
|  |    an AR model instance.  Impressionist will automatically log the Model name | ||||||
|  |    (based on action_name) and the id (based on params[:id]), but in order to | ||||||
|  |    get the count of impressions (example: @widget.impression_count), you will | ||||||
|  |    need to make your model impressionalble | ||||||
|  | 
 | ||||||
|  |         class Widget < ActiveRecord::Base | ||||||
|  |           is_impressionable | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  | 4. Log an impression per model instance in your controller.  Note that it is | ||||||
|  |    not necessary to specify "impressionist" (usage #1) in the top of you | ||||||
|  |    controller if you are using this method.  If you add "impressionist" to the | ||||||
|  |    top of your controller and also use this method in your action, it will | ||||||
|  |    result in 2 impressions being logged (but associated with one request_hash) | ||||||
|  | 
 | ||||||
|  |         def show | ||||||
|  |           @widget = Widget.find | ||||||
|  |           impressionist(@widget,message:"wtf is a widget?") #message is optional | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  | 5. Get unique impression count from a model.  This groups impressions by | ||||||
|  |    request_hash, so if you logged multiple impressions per request, it will | ||||||
|  |    only count them one time.  This unique impression count will not filter out | ||||||
|  |    unique users, only unique requests | ||||||
|  | 
 | ||||||
|  |         @widget.impressionist_count | ||||||
|  |         @widget.impressionist_count(:start_date=>"2011-01-01",:end_date=>"2011-01-05") | ||||||
|  |         @widget.impressionist_count(:start_date=>"2011-01-01")  #specify start date only, end date = now | ||||||
|  | 
 | ||||||
|  | 6. Get the unique impression count from a model filtered by IP address.  This | ||||||
|  |    in turn will give you impressions with unique request_hash, since rows with | ||||||
|  |    the same request_hash will have the same IP address. | ||||||
|  | 
 | ||||||
|  |         @widget.impressionist_count(:filter=>:ip_address) | ||||||
|  | 
 | ||||||
|  | 7. Get the unique impression count from a model filtered by session hash.  Same | ||||||
|  |    as #6 regarding request hash.  This may be more desirable than filtering by | ||||||
|  |    IP address depending on your situation, since filtering by IP may ignore | ||||||
|  |    visitors that use the same IP.  The downside to this filtering is that a | ||||||
|  |    user could clear session data in their browser and skew the results. | ||||||
|  | 
 | ||||||
|  |         @widget.impressionist_count(:filter=>:session_hash) | ||||||
|  | 
 | ||||||
|  | 8. Get total impression count.  This may return more than 1 impression per http | ||||||
|  |    request, depending on how you are logging impressions | ||||||
|  | 
 | ||||||
|  |         @widget.impressionist_count(:filter=>:all) | ||||||
|  | 
 | ||||||
|  | Logging impressions for authenticated users happens automatically.  If you have | ||||||
|  | a current_user helper or use @current_user in your before_filter to set your | ||||||
|  | authenticated user, current_user.id will be written to the user_id field in the | ||||||
|  | impressions table. | ||||||
|  | 
 | ||||||
|  | Adding a counter cache | ||||||
|  | ---------------------- | ||||||
|  | Impressionist makes it easy to add a `counter_cache` column to your model. The | ||||||
|  | most basic configuration looks like: | ||||||
|  | 
 | ||||||
|  |     is_impressionable :counter_cache => true | ||||||
|  | 
 | ||||||
|  | This will automatically increment the `impressions_count` column in the | ||||||
|  | included model. Note: You'll need to add that column to your model. If you'd | ||||||
|  | like specific a different column name, you can: | ||||||
|  | 
 | ||||||
|  |     is_impressionable :counter_cache => { :column_name => :my_column } | ||||||
|  | 
 | ||||||
|  | If you'd like to include only unique impressions in your count: | ||||||
|  | 
 | ||||||
|  |     is_impressionable :counter_cache => { :column_name => :my_column, :unique => true } | ||||||
|  | 
 | ||||||
|  | What if I only want to record unique impressions? | ||||||
|  | ------------------------------------------------- | ||||||
|  | Maybe you only care about unique impressions and would like to avoid | ||||||
|  | unnecessary database records. You can specify conditions for recording | ||||||
|  | impressions in your controller: | ||||||
|  | 
 | ||||||
|  |     # only record impression if the request has a unique combination of type, id, and session | ||||||
|  |     impressionist :unique => [:impressionable_type, :impressionable_id, :session_hash] | ||||||
|  | 
 | ||||||
|  |     # only record impression if the request has a unique combination of controller, action, and session | ||||||
|  |     impressionist :unique => [:controller_name, :action_name, :session_hash] | ||||||
|  | 
 | ||||||
|  |     # only record impression if session is unique | ||||||
|  |     impressionist :unique => [:session_hash] | ||||||
|  | 
 | ||||||
|  | Or you can use the `impressionist` method directly: | ||||||
|  | 
 | ||||||
|  |     impressionist(impressionable, "some message", :unique => [:session_hash]) | ||||||
|  | 
 | ||||||
|  | Development Roadmap | ||||||
|  | ------------------- | ||||||
|  | * Automatic impression logging in views.  For example, log initial view, and | ||||||
|  |   any partials called from initial view | ||||||
|  | * Customizable black list for user-agents or IP addresses.  Impressions will be | ||||||
|  |   ignored.  Web admin as part of the Engine. | ||||||
|  | * Reporting engine | ||||||
|  | * AB testing integration | ||||||
|  | 
 | ||||||
|  | Contributing to impressionist | ||||||
|  | ----------------------------- | ||||||
|  | * Check out the latest master to make sure the feature hasn't been implemented | ||||||
|  |   or the bug hasn't been fixed yet | ||||||
|  | * Check out the issue tracker to make sure someone already hasn't requested it | ||||||
|  |   and/or contributed it | ||||||
|  | * Fork the project | ||||||
|  | * Start a feature/bugfix branch | ||||||
|  | * Commit and push until you are happy with your contribution | ||||||
|  | * Make sure to add rpsec tests for it. Patches or features without tests will | ||||||
|  |   be ignored.  Also, try to write better tests than I do ;-) | ||||||
|  | * If adding engine controller or view functionality, use HAML and Inherited | ||||||
|  |   Resources. | ||||||
|  | * All testing is done inside a small Rails app (test_app).  You will find specs | ||||||
|  |   within this app. | ||||||
|  | 
 | ||||||
|  | Contributors | ||||||
|  | ------------ | ||||||
|  | * [johnmcaliley](https://github.com/johnmcaliley) | ||||||
|  | * [coryschires](https://github.com/coryschires) | ||||||
|  | * [georgmittendorfer](https://github.com/georgmittendorfer) | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2011 John McAliley. See LICENSE.txt for further details. | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | require 'bundler/setup' | ||||||
|  | require 'rspec/core/rake_task' | ||||||
|  | 
 | ||||||
|  | Bundler::GemHelper.install_tasks | ||||||
|  | 
 | ||||||
|  | RSpec::Core::RakeTask.new do |task| | ||||||
|  |   task.rspec_opts = "-I ./test_app/spec" | ||||||
|  |   task.pattern = "./test_app/spec/**/*_spec.rb" | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | task :test => :spec | ||||||
|  | task :default => :spec | ||||||
|  | 
 | ||||||
|  | namespace :impressionist do | ||||||
|  |   require File.dirname(__FILE__) + "/lib/impressionist/bots" | ||||||
|  | 
 | ||||||
|  |   desc "output the list of bots from http://www.user-agents.org/" | ||||||
|  |   task :bots do | ||||||
|  |     p Impressionist::Bots.consume | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,103 @@ | ||||||
|  | require 'digest/sha2' | ||||||
|  | 
 | ||||||
|  | module ImpressionistController | ||||||
|  |   module ClassMethods | ||||||
|  |     def impressionist(opts={}) | ||||||
|  |       before_filter { |c| c.impressionist_subapp_filter(opts[:actions], opts[:unique])} | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   module InstanceMethods | ||||||
|  |     def self.included(base) | ||||||
|  |       base.before_filter :impressionist_app_filter | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def impressionist(obj,message=nil,opts={}) | ||||||
|  |       unless bypass | ||||||
|  |         if obj.respond_to?("impressionable?") | ||||||
|  |           if unique_instance?(obj, opts[:unique]) | ||||||
|  |             obj.impressions.create(associative_create_statement({:message => message})) | ||||||
|  |           end | ||||||
|  |         else | ||||||
|  |           # we could create an impression anyway. for classes, too. why not? | ||||||
|  |           raise "#{obj.class.to_s} is not impressionable!" | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def impressionist_app_filter | ||||||
|  |       @impressionist_hash = Digest::SHA2.hexdigest(Time.now.to_f.to_s+rand(10000).to_s) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def impressionist_subapp_filter(actions=nil,unique_opts=nil) | ||||||
|  |       unless bypass | ||||||
|  |         actions.collect!{|a|a.to_s} unless actions.blank? | ||||||
|  |         if (actions.blank? || actions.include?(action_name)) && unique?(unique_opts) | ||||||
|  |           Impression.create(direct_create_statement) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     private | ||||||
|  | 
 | ||||||
|  |     def bypass | ||||||
|  |       Impressionist::Bots.bot?(request.user_agent) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def unique_instance?(impressionable, unique_opts) | ||||||
|  |       return unique_opts.blank? || !impressionable.impressions.where(unique_query(unique_opts)).exists? | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def unique?(unique_opts) | ||||||
|  |       return unique_opts.blank? || !Impression.where(unique_query(unique_opts)).exists? | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     # creates the query to check for uniqueness | ||||||
|  |     def unique_query(unique_opts) | ||||||
|  |       full_statement = direct_create_statement | ||||||
|  |       # reduce the full statement to the params we need for the specified unique options | ||||||
|  |       unique_opts.reduce({}) do |query, param| | ||||||
|  |         query[param] = full_statement[param] | ||||||
|  |         query | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     # creates a statment hash that contains default values for creating an impression via an AR relation. | ||||||
|  |     def associative_create_statement(query_params={}) | ||||||
|  |       query_params.reverse_merge!( | ||||||
|  |         :controller_name => controller_name, | ||||||
|  |         :action_name => action_name, | ||||||
|  |         :user_id => user_id, | ||||||
|  |         :request_hash => @impressionist_hash, | ||||||
|  |         :session_hash => session_hash, | ||||||
|  |         :ip_address => request.remote_ip, | ||||||
|  |         :referrer => request.referer | ||||||
|  |         ) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     # creates a statment hash that contains default values for creating an impression. | ||||||
|  |     def direct_create_statement(query_params={}) | ||||||
|  |       query_params.reverse_merge!( | ||||||
|  |         :impressionable_type => controller_name.singularize.camelize, | ||||||
|  |         :impressionable_id=> params[:id] | ||||||
|  |         ) | ||||||
|  |       associative_create_statement(query_params) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def session_hash | ||||||
|  |       # # careful: request.session_options[:id] encoding in rspec test was ASCII-8BIT | ||||||
|  |       # # that broke the database query for uniqueness. not sure if this is a testing only issue. | ||||||
|  |       # str = request.session_options[:id] | ||||||
|  |       # logger.debug "Encoding: #{str.encoding.inspect}" | ||||||
|  |       # # request.session_options[:id].encode("ISO-8859-1") | ||||||
|  |       request.session_options[:id] | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     #use both @current_user and current_user helper | ||||||
|  |     def user_id | ||||||
|  |       user_id = @current_user ? @current_user.id : nil rescue nil | ||||||
|  |       user_id = current_user ? current_user.id : nil rescue nil if user_id.blank? | ||||||
|  |       user_id | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | class Impression | ||||||
|  |   belongs_to :impressionable, :polymorphic=>true | ||||||
|  | end | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,64 @@ | ||||||
|  | module Impressionist | ||||||
|  |   module Impressionable | ||||||
|  |     extend ActiveSupport::Concern | ||||||
|  | 
 | ||||||
|  |     module ClassMethods | ||||||
|  |       attr_accessor :impressionist_cache_options | ||||||
|  |       @impressionist_cache_options = nil | ||||||
|  | 
 | ||||||
|  |       def impressionist_counter_cache_options | ||||||
|  |         if @impressionist_cache_options | ||||||
|  |           options = { :column_name => :impressions_count, :unique => false } | ||||||
|  |           options.merge!(@impressionist_cache_options) if @impressionist_cache_options.is_a?(Hash) | ||||||
|  |           options | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       def impressionist_counter_caching? | ||||||
|  |         impressionist_counter_cache_options.present? | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       def counter_caching? | ||||||
|  |         ::ActiveSupport::Deprecation.warn("#counter_caching? is deprecated; please use #impressionist_counter_caching? instead") | ||||||
|  |         impressionist_counter_caching? | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def impressionable? | ||||||
|  |       true | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def impressionist_count(options={}) | ||||||
|  |       # options.reverse_merge!(:filter=>:request_hash, :start_date=>nil, :end_date=>Time.now) | ||||||
|  |       # imps = options[:start_date].blank? ? impressions : impressions.where("created_at>=? and created_at<=?",options[:start_date],options[:end_date]) | ||||||
|  |       # options[:filter] == :all ? imps.count : imps.count(options[:filter], :distinct => true) | ||||||
|  |       options.reverse_merge!(:filter => :request_hash, :start_date => nil, :end_date => Time.now) | ||||||
|  |       imps = options[:start_date].blank? ? impressions : impressions.where(:created_at.gte => options[:start_date], :created_at.lte => options[:end_date]) | ||||||
|  |       options[:filter] == :all ? imps.count : imps.distinct(options[:filter]).count | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def update_impressionist_counter_cache | ||||||
|  |       cache_options = self.class.impressionist_counter_cache_options | ||||||
|  |       column_name = cache_options[:column_name].to_sym | ||||||
|  |       count = cache_options[:unique] ? impressionist_count(:filter => :ip_address) : impressionist_count | ||||||
|  |       update_attribute(column_name, count) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     # OLD METHODS - DEPRECATE IN V0.5 | ||||||
|  |     def impression_count(start_date=nil,end_date=Time.now) | ||||||
|  |       impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=>:all}) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def unique_impression_count(start_date=nil,end_date=Time.now) | ||||||
|  |       impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=> :request_hash}) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def unique_impression_count_ip(start_date=nil,end_date=Time.now) | ||||||
|  |       impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=> :ip_address}) | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     def unique_impression_count_session(start_date=nil,end_date=Time.now) | ||||||
|  |       impressionist_count({:start_date=>start_date, :end_date=>end_date, :filter=> :session_hash}) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | # encoding: utf-8 | ||||||
|  | require File.expand_path('../lib/impressionist/version', __FILE__) | ||||||
|  | 
 | ||||||
|  | Gem::Specification.new do |s| | ||||||
|  |   s.add_dependency 'httpclient', '~> 2.2' | ||||||
|  |   s.add_dependency 'nokogiri', '~> 1.5' | ||||||
|  |   s.add_development_dependency 'capybara' | ||||||
|  |   s.add_development_dependency 'rake', '>= 0.9' | ||||||
|  |   s.add_development_dependency 'rails', '~>3.1' | ||||||
|  |   s.add_development_dependency 'rdoc', '>= 2.4.2' | ||||||
|  |   s.add_development_dependency 'rspec-rails' | ||||||
|  |   s.add_development_dependency 'simplecov' | ||||||
|  |   s.add_development_dependency 'sqlite3' | ||||||
|  |   s.add_development_dependency 'systemu' | ||||||
|  |   s.authors = ["johnmcaliley"] | ||||||
|  |   s.description = "Log impressions from controller actions or from a model" | ||||||
|  |   s.email = "john.mcaliley@gmail.com" | ||||||
|  |   s.files = `git ls-files`.split("\n") | ||||||
|  |   s.homepage = "https://github.com/charlotte-ruby/impressionist" | ||||||
|  |   s.licenses = ["MIT"] | ||||||
|  |   s.name = "impressionist" | ||||||
|  |   s.require_paths = ["lib"] | ||||||
|  |   s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if s.respond_to? :required_rubygems_version= | ||||||
|  |   s.summary = "Easy way to log impressions" | ||||||
|  |   s.test_files = `git ls-files -- test_app/*`.split("\n") | ||||||
|  |   s.version = Impressionist::VERSION | ||||||
|  | end | ||||||
							
								
								
									
										21
									
								
								vendor/impressionist/lib/generators/active_record/impressionist_generator.rb
								
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										21
									
								
								vendor/impressionist/lib/generators/active_record/impressionist_generator.rb
								
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | module ActiveRecord | ||||||
|  |   module Generators | ||||||
|  |     class ImpressionistGenerator < Rails::Generators::Base | ||||||
|  |       include Rails::Generators::Migration | ||||||
|  |       source_root File.join(File.dirname(__FILE__), 'templates') | ||||||
|  | 
 | ||||||
|  |       def self.next_migration_number(dirname) | ||||||
|  |         sleep 1 | ||||||
|  |         if ActiveRecord::Base.timestamped_migrations | ||||||
|  |           Time.now.utc.strftime("%Y%m%d%H%M%S") | ||||||
|  |         else | ||||||
|  |           "%.3d" % (current_migration_number(dirname) + 1) | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       def create_migration_file | ||||||
|  |         migration_template 'create_impressions_table.rb', 'db/migrate/create_impressions_table.rb' | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
							
								
								
									
										30
									
								
								vendor/impressionist/lib/generators/active_record/templates/create_impressions_table.rb
								
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										30
									
								
								vendor/impressionist/lib/generators/active_record/templates/create_impressions_table.rb
								
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | class CreateImpressionsTable < ActiveRecord::Migration | ||||||
|  |   def self.up | ||||||
|  |     create_table :impressions, :force => true do |t| | ||||||
|  |       t.string :impressionable_type | ||||||
|  |       t.integer :impressionable_id | ||||||
|  |       t.integer :user_id | ||||||
|  |       t.string :controller_name | ||||||
|  |       t.string :action_name | ||||||
|  |       t.string :view_name | ||||||
|  |       t.string :request_hash | ||||||
|  |       t.string :ip_address | ||||||
|  |       t.string :session_hash | ||||||
|  |       t.text :message | ||||||
|  |       t.text :referrer | ||||||
|  |       t.timestamps | ||||||
|  |     end | ||||||
|  |     add_index :impressions, [:impressionable_type, :message, :impressionable_id], :name => "impressionable_type_message_index", :unique => false | ||||||
|  |     add_index :impressions, [:impressionable_type, :impressionable_id, :request_hash], :name => "poly_request_index", :unique => false | ||||||
|  |     add_index :impressions, [:impressionable_type, :impressionable_id, :ip_address], :name => "poly_ip_index", :unique => false | ||||||
|  |     add_index :impressions, [:impressionable_type, :impressionable_id, :session_hash], :name => "poly_session_index", :unique => false | ||||||
|  |     add_index :impressions, [:controller_name,:action_name,:request_hash], :name => "controlleraction_request_index", :unique => false | ||||||
|  |     add_index :impressions, [:controller_name,:action_name,:ip_address], :name => "controlleraction_ip_index", :unique => false | ||||||
|  |     add_index :impressions, [:controller_name,:action_name,:session_hash], :name => "controlleraction_session_index", :unique => false | ||||||
|  |     add_index :impressions, :user_id | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def self.down | ||||||
|  |     drop_table :impressions | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | module Impressionist | ||||||
|  |   module Generators | ||||||
|  |     class ImpressionistGenerator < Rails::Generators::Base | ||||||
|  |       hook_for :orm | ||||||
|  |       source_root File.expand_path('../templates', __FILE__) | ||||||
|  | 
 | ||||||
|  |       def copy_config_file | ||||||
|  |         template 'impression.rb', 'config/initializers/impression.rb' | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | module MongoMapper | ||||||
|  |   module Generators | ||||||
|  |     class ImpressionistGenerator < Rails::Generators::Base | ||||||
|  |       # Empty for now, need it for generating the config file without | ||||||
|  |       # triggering other ORM's generators. | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | module Mongoid | ||||||
|  |   module Generators | ||||||
|  |     class ImpressionistGenerator < Rails::Generators::Base | ||||||
|  |       # Empty for now, need it for generating the config file without | ||||||
|  |       # triggering other ORM's generators. | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | # Use this hook to configure impressionist parameters | ||||||
|  | Impressionist.setup do |config| | ||||||
|  |   # Define ORM. Could be :active_record (default) and :mongo_mapper | ||||||
|  |   # config.orm = :active_record | ||||||
|  | end | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | require "impressionist/engine.rb" | ||||||
|  | 
 | ||||||
|  | module Impressionist | ||||||
|  |   # Define ORM | ||||||
|  |   mattr_accessor :orm | ||||||
|  |   @@orm = :active_record | ||||||
|  | 
 | ||||||
|  |   # Load configuration from initializer | ||||||
|  |   def self.setup | ||||||
|  |     yield self | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | require 'httpclient' | ||||||
|  | require 'nokogiri' | ||||||
|  | 
 | ||||||
|  | module Impressionist | ||||||
|  |   module Bots | ||||||
|  |     LIST_URL = "http://www.user-agents.org/allagents.xml" | ||||||
|  |     def self.consume | ||||||
|  |       response = HTTPClient.new.get_content(LIST_URL) | ||||||
|  |       doc = Nokogiri::XML(response) | ||||||
|  |       list = [] | ||||||
|  |       doc.xpath('//user-agent').each do |agent| | ||||||
|  |         type = agent.xpath("Type").text | ||||||
|  |         list << agent.xpath("String").text.gsub("<","<") if ["R","S"].include?(type) #gsub hack for badly formatted data | ||||||
|  |       end | ||||||
|  |       list | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | require "impressionist" | ||||||
|  | require "rails" | ||||||
|  | 
 | ||||||
|  | module Impressionist | ||||||
|  |   class Engine < Rails::Engine | ||||||
|  |     initializer 'impressionist.model' do |app| | ||||||
|  |       require "#{root}/app/models/impressionist/impressionable.rb" | ||||||
|  |       if Impressionist.orm == :active_record | ||||||
|  |         require "impressionist/models/active_record/impression.rb" | ||||||
|  |         require "impressionist/models/active_record/impressionist/impressionable.rb" | ||||||
|  |         ActiveRecord::Base.send(:include, Impressionist::Impressionable) | ||||||
|  |       elsif Impressionist.orm == :mongo_mapper | ||||||
|  |         require "impressionist/models/mongo_mapper/impression.rb" | ||||||
|  |         require "impressionist/models/mongo_mapper/impressionist/impressionable.rb" | ||||||
|  |         MongoMapper::Document.plugin Impressionist::Impressionable | ||||||
|  |       elsif Impressionist.orm == :mongoid | ||||||
|  |         require "impressionist/models/mongoid/impression.rb" | ||||||
|  |         require "impressionist/models/mongoid/impressionist/impressionable.rb" | ||||||
|  |         # Mongoid::Document Impressionist::Impressionable | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     initializer 'impressionist.controller' do | ||||||
|  |       ActiveSupport.on_load(:action_controller) do | ||||||
|  |         include ImpressionistController::InstanceMethods | ||||||
|  |         extend ImpressionistController::ClassMethods | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | class Impression < ActiveRecord::Base | ||||||
|  |   attr_accessible :impressionable_type, :impressionable_id, :user_id, | ||||||
|  |   :controller_name, :action_name, :view_name, :request_hash, :ip_address, | ||||||
|  |   :session_hash, :message, :referrer | ||||||
|  | 
 | ||||||
|  |   after_save :update_impressions_counter_cache | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def update_impressions_counter_cache | ||||||
|  |     impressionable_class = self.impressionable_type.constantize | ||||||
|  | 
 | ||||||
|  |     if impressionable_class.impressionist_counter_cache_options | ||||||
|  |       resouce = impressionable_class.find(self.impressionable_id) | ||||||
|  |       resouce.try(:update_impressionist_counter_cache) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
							
								
								
									
										12
									
								
								vendor/impressionist/lib/impressionist/models/active_record/impressionist/impressionable.rb
								
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										12
									
								
								vendor/impressionist/lib/impressionist/models/active_record/impressionist/impressionable.rb
								
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | module Impressionist | ||||||
|  |   module Impressionable | ||||||
|  |     extend ActiveSupport::Concern | ||||||
|  | 
 | ||||||
|  |     module ClassMethods | ||||||
|  |       def is_impressionable(options={}) | ||||||
|  |         has_many :impressions, :as => :impressionable, :dependent => :destroy | ||||||
|  |         @impressionist_cache_options = options[:counter_cache] | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | class Impression | ||||||
|  |   include MongoMapper::Document | ||||||
|  | 
 | ||||||
|  |   key :impressionable_type, String | ||||||
|  |   key :impressionable_id, String | ||||||
|  |   key :user_id, String | ||||||
|  |   key :controller_name, String | ||||||
|  |   key :action_name, String | ||||||
|  |   key :view_name, String | ||||||
|  |   key :request_hash, String | ||||||
|  |   key :ip_address, String | ||||||
|  |   key :session_hash, String | ||||||
|  |   key :message, String | ||||||
|  |   key :referrer, String | ||||||
|  |   timestamps! | ||||||
|  | end | ||||||
							
								
								
									
										12
									
								
								vendor/impressionist/lib/impressionist/models/mongo_mapper/impressionist/impressionable.rb
								
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										12
									
								
								vendor/impressionist/lib/impressionist/models/mongo_mapper/impressionist/impressionable.rb
								
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | module Impressionist | ||||||
|  |   module Impressionable | ||||||
|  |     extend ActiveSupport::Concern | ||||||
|  | 
 | ||||||
|  |     module ClassMethods | ||||||
|  |       def is_impressionable(options={}) | ||||||
|  |         many :impressions, :as => :impressionable, :dependent => :destroy | ||||||
|  |         @cache_options = options[:counter_cache] | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,37 @@ | ||||||
|  | class Impression | ||||||
|  |   include Mongoid::Document | ||||||
|  |   include Mongoid::Timestamps | ||||||
|  | 
 | ||||||
|  |   field :impressionable_type | ||||||
|  |   field :impressionable_id | ||||||
|  |   field :user_id | ||||||
|  |   field :controller_name | ||||||
|  |   field :action_name | ||||||
|  |   field :view_name | ||||||
|  |   field :request_hash | ||||||
|  |   field :ip_address | ||||||
|  |   field :session_hash | ||||||
|  |   field :message | ||||||
|  |   field :referrer | ||||||
|  | 
 | ||||||
|  |   belongs_to :impressionable, :polymorphic => true | ||||||
|  | 
 | ||||||
|  |   after_save :update_impressions_counter_cache | ||||||
|  | 
 | ||||||
|  |   def self.impressionist_count(options={}) | ||||||
|  |     options.reverse_merge!(:filter => :request_hash, :start_date => nil, :end_date => Time.now) | ||||||
|  |     imps = options[:start_date].blank? ? impressions : impressions.where(:created_at.gte => options[:start_date], :created_at.lte => options[:end_date]) | ||||||
|  |     options[:filter] == :all ? imps.count : imps.distinct(options[:filter]).count | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def update_impressions_counter_cache | ||||||
|  |     impressionable_class = self.impressionable_type.constantize | ||||||
|  | 
 | ||||||
|  |     if impressionable_class.impressionist_counter_cache_options | ||||||
|  |       resouce = impressionable_class.find(self.impressionable_id) | ||||||
|  |       resouce.try(:update_impressionist_counter_cache) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
							
								
								
									
										12
									
								
								vendor/impressionist/lib/impressionist/models/mongoid/impressionist/impressionable.rb
								
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										12
									
								
								vendor/impressionist/lib/impressionist/models/mongoid/impressionist/impressionable.rb
								
								
								
									vendored
								
								
									Normal file
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | module Impressionist | ||||||
|  |   module Impressionable | ||||||
|  |     extend ActiveSupport::Concern | ||||||
|  | 
 | ||||||
|  |     module ClassMethods | ||||||
|  |       def is_impressionable(options={}) | ||||||
|  |         has_many :impressions, :as => :impressionable, :dependent => :destroy | ||||||
|  |         @impressionist_cache_options = options[:counter_cache] | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | module Impressionist | ||||||
|  |   VERSION = "1.1.1" | ||||||
|  | end | ||||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 62 KiB | 
|  | @ -0,0 +1,17 @@ | ||||||
|  | # See http://help.github.com/ignore-files/ for more about ignoring files. | ||||||
|  | # | ||||||
|  | # If you find yourself ignoring temporary files generated by your text editor | ||||||
|  | # or operating system, you probably want to add a global ignore instead: | ||||||
|  | #   git config --global core.excludesfile ~/.gitignore_global | ||||||
|  | 
 | ||||||
|  | # Ignore bundler config | ||||||
|  | /.bundle | ||||||
|  | /Gemfile.lock | ||||||
|  | 
 | ||||||
|  | # Ignore the default SQLite database. | ||||||
|  | /db/*.sqlite3 | ||||||
|  | 
 | ||||||
|  | # Ignore all logfiles and tempfiles. | ||||||
|  | /coverage | ||||||
|  | /log/*.log | ||||||
|  | /tmp | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | --color | ||||||
|  | @ -0,0 +1,59 @@ | ||||||
|  | source 'https://rubygems.org' | ||||||
|  | 
 | ||||||
|  | gem 'rails', '3.2.2' | ||||||
|  | 
 | ||||||
|  | gem 'impressionist', :path => '../' | ||||||
|  | 
 | ||||||
|  | platforms :jruby do | ||||||
|  |   gem 'activerecord-jdbcsqlite3-adapter' | ||||||
|  |   gem 'jdbc-sqlite3' | ||||||
|  |   gem 'jruby-openssl' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | platforms :ruby, :mswin, :mingw do | ||||||
|  |   gem 'pg' | ||||||
|  |   gem 'sqlite3' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | gem 'json' | ||||||
|  | 
 | ||||||
|  | # Gems used only for assets and not required | ||||||
|  | # in production environments by default. | ||||||
|  | group :assets do | ||||||
|  |   gem 'sass-rails',   '~> 3.2.3' | ||||||
|  |   gem 'coffee-rails', '~> 3.2.1' | ||||||
|  | 
 | ||||||
|  |   # See https://github.com/sstephenson/execjs#readme for more supported runtimes | ||||||
|  |   # gem 'therubyracer' | ||||||
|  | 
 | ||||||
|  |   gem 'uglifier', '>= 1.0.3' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | group :development, :test do | ||||||
|  |   gem 'autotest-notification' | ||||||
|  |   gem 'rspec-rails' | ||||||
|  |   gem 'spork' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | group :test do | ||||||
|  |   gem 'capybara' | ||||||
|  |   gem 'simplecov' | ||||||
|  |   gem 'systemu' | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | gem 'jquery-rails' | ||||||
|  | 
 | ||||||
|  | # To use ActiveModel has_secure_password | ||||||
|  | # gem 'bcrypt-ruby', '~> 3.0.0' | ||||||
|  | 
 | ||||||
|  | # To use Jbuilder templates for JSON | ||||||
|  | # gem 'jbuilder' | ||||||
|  | 
 | ||||||
|  | # Use unicorn as the app server | ||||||
|  | # gem 'unicorn' | ||||||
|  | 
 | ||||||
|  | # Deploy with Capistrano | ||||||
|  | # gem 'capistrano' | ||||||
|  | 
 | ||||||
|  | # To use debugger | ||||||
|  | # gem 'ruby-debug' | ||||||
|  | @ -0,0 +1,256 @@ | ||||||
|  | == Welcome to Rails | ||||||
|  | 
 | ||||||
|  | Rails is a web-application framework that includes everything needed to create | ||||||
|  | database-backed web applications according to the Model-View-Control pattern. | ||||||
|  | 
 | ||||||
|  | This pattern splits the view (also called the presentation) into "dumb" | ||||||
|  | templates that are primarily responsible for inserting pre-built data in between | ||||||
|  | HTML tags. The model contains the "smart" domain objects (such as Account, | ||||||
|  | Product, Person, Post) that holds all the business logic and knows how to | ||||||
|  | persist themselves to a database. The controller handles the incoming requests | ||||||
|  | (such as Save New Account, Update Product, Show Post) by manipulating the model | ||||||
|  | and directing data to the view. | ||||||
|  | 
 | ||||||
|  | In Rails, the model is handled by what's called an object-relational mapping | ||||||
|  | layer entitled Active Record. This layer allows you to present the data from | ||||||
|  | database rows as objects and embellish these data objects with business logic | ||||||
|  | methods. You can read more about Active Record in | ||||||
|  | link:files/vendor/rails/activerecord/README.html. | ||||||
|  | 
 | ||||||
|  | The controller and view are handled by the Action Pack, which handles both | ||||||
|  | layers by its two parts: Action View and Action Controller. These two layers | ||||||
|  | are bundled in a single package due to their heavy interdependence. This is | ||||||
|  | unlike the relationship between the Active Record and Action Pack that is much | ||||||
|  | more separate. Each of these packages can be used independently outside of | ||||||
|  | Rails. You can read more about Action Pack in | ||||||
|  | link:files/vendor/rails/actionpack/README.html. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Getting Started | ||||||
|  | 
 | ||||||
|  | 1. At the command prompt, create a new Rails application: | ||||||
|  |        <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name) | ||||||
|  | 
 | ||||||
|  | 2. Change directory to <tt>myapp</tt> and start the web server: | ||||||
|  |        <tt>cd myapp; rails server</tt> (run with --help for options) | ||||||
|  | 
 | ||||||
|  | 3. Go to http://localhost:3000/ and you'll see: | ||||||
|  |        "Welcome aboard: You're riding Ruby on Rails!" | ||||||
|  | 
 | ||||||
|  | 4. Follow the guidelines to start developing your application. You can find | ||||||
|  | the following resources handy: | ||||||
|  | 
 | ||||||
|  | * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html | ||||||
|  | * Ruby on Rails Tutorial Book: http://www.railstutorial.org/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Debugging Rails | ||||||
|  | 
 | ||||||
|  | Sometimes your application goes wrong. Fortunately there are a lot of tools that | ||||||
|  | will help you debug it and get it back on the rails. | ||||||
|  | 
 | ||||||
|  | First area to check is the application log files. Have "tail -f" commands | ||||||
|  | running on the server.log and development.log. Rails will automatically display | ||||||
|  | debugging and runtime information to these files. Debugging info will also be | ||||||
|  | shown in the browser on requests from 127.0.0.1. | ||||||
|  | 
 | ||||||
|  | You can also log your own messages directly into the log file from your code | ||||||
|  | using the Ruby logger class from inside your controllers. Example: | ||||||
|  | 
 | ||||||
|  |   class WeblogController < ActionController::Base | ||||||
|  |     def destroy | ||||||
|  |       @weblog = Weblog.find(params[:id]) | ||||||
|  |       @weblog.destroy | ||||||
|  |       logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  | The result will be a message in your log file along the lines of: | ||||||
|  | 
 | ||||||
|  |   Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! | ||||||
|  | 
 | ||||||
|  | More information on how to use the logger is at http://www.ruby-doc.org/core/ | ||||||
|  | 
 | ||||||
|  | Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are | ||||||
|  | several books available online as well: | ||||||
|  | 
 | ||||||
|  | * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) | ||||||
|  | * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) | ||||||
|  | 
 | ||||||
|  | These two books will bring you up to speed on the Ruby language and also on | ||||||
|  | programming in general. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Debugger | ||||||
|  | 
 | ||||||
|  | Debugger support is available through the debugger command when you start your | ||||||
|  | Mongrel or WEBrick server with --debugger. This means that you can break out of | ||||||
|  | execution at any point in the code, investigate and change the model, and then, | ||||||
|  | resume execution! You need to install ruby-debug to run the server in debugging | ||||||
|  | mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example: | ||||||
|  | 
 | ||||||
|  |   class WeblogController < ActionController::Base | ||||||
|  |     def index | ||||||
|  |       @posts = Post.find(:all) | ||||||
|  |       debugger | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  | So the controller will accept the action, run the first line, then present you | ||||||
|  | with a IRB prompt in the server window. Here you can do things like: | ||||||
|  | 
 | ||||||
|  |   >> @posts.inspect | ||||||
|  |   => "[#<Post:0x14a6be8 | ||||||
|  |           @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>, | ||||||
|  |        #<Post:0x14a6620 | ||||||
|  |           @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]" | ||||||
|  |   >> @posts.first.title = "hello from a debugger" | ||||||
|  |   => "hello from a debugger" | ||||||
|  | 
 | ||||||
|  | ...and even better, you can examine how your runtime objects actually work: | ||||||
|  | 
 | ||||||
|  |   >> f = @posts.first | ||||||
|  |   => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}> | ||||||
|  |   >> f. | ||||||
|  |   Display all 152 possibilities? (y or n) | ||||||
|  | 
 | ||||||
|  | Finally, when you're ready to resume execution, you can enter "cont". | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Console | ||||||
|  | 
 | ||||||
|  | The console is a Ruby shell, which allows you to interact with your | ||||||
|  | application's domain model. Here you'll have all parts of the application | ||||||
|  | configured, just like it is when the application is running. You can inspect | ||||||
|  | domain models, change values, and save to the database. Starting the script | ||||||
|  | without arguments will launch it in the development environment. | ||||||
|  | 
 | ||||||
|  | To start the console, run <tt>rails console</tt> from the application | ||||||
|  | directory. | ||||||
|  | 
 | ||||||
|  | Options: | ||||||
|  | 
 | ||||||
|  | * Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications | ||||||
|  |   made to the database. | ||||||
|  | * Passing an environment name as an argument will load the corresponding | ||||||
|  |   environment. Example: <tt>rails console production</tt>. | ||||||
|  | 
 | ||||||
|  | To reload your controllers and models after launching the console run | ||||||
|  | <tt>reload!</tt> | ||||||
|  | 
 | ||||||
|  | More information about irb can be found at: | ||||||
|  | link:http://www.rubycentral.com/pickaxe/irb.html | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == dbconsole | ||||||
|  | 
 | ||||||
|  | You can go to the command line of your database directly through <tt>rails | ||||||
|  | dbconsole</tt>. You would be connected to the database with the credentials | ||||||
|  | defined in database.yml. Starting the script without arguments will connect you | ||||||
|  | to the development database. Passing an argument will connect you to a different | ||||||
|  | database, like <tt>rails dbconsole production</tt>. Currently works for MySQL, | ||||||
|  | PostgreSQL and SQLite 3. | ||||||
|  | 
 | ||||||
|  | == Description of Contents | ||||||
|  | 
 | ||||||
|  | The default directory structure of a generated Ruby on Rails application: | ||||||
|  | 
 | ||||||
|  |   |-- app | ||||||
|  |   |   |-- controllers | ||||||
|  |   |   |-- helpers | ||||||
|  |   |   |-- mailers | ||||||
|  |   |   |-- models | ||||||
|  |   |   `-- views | ||||||
|  |   |       `-- layouts | ||||||
|  |   |-- config | ||||||
|  |   |   |-- environments | ||||||
|  |   |   |-- initializers | ||||||
|  |   |   `-- locales | ||||||
|  |   |-- db | ||||||
|  |   |-- doc | ||||||
|  |   |-- lib | ||||||
|  |   |   `-- tasks | ||||||
|  |   |-- log | ||||||
|  |   |-- public | ||||||
|  |   |   |-- images | ||||||
|  |   |   |-- javascripts | ||||||
|  |   |   `-- stylesheets | ||||||
|  |   |-- script | ||||||
|  |   |-- test | ||||||
|  |   |   |-- fixtures | ||||||
|  |   |   |-- functional | ||||||
|  |   |   |-- integration | ||||||
|  |   |   |-- performance | ||||||
|  |   |   `-- unit | ||||||
|  |   |-- tmp | ||||||
|  |   |   |-- cache | ||||||
|  |   |   |-- pids | ||||||
|  |   |   |-- sessions | ||||||
|  |   |   `-- sockets | ||||||
|  |   `-- vendor | ||||||
|  |       `-- plugins | ||||||
|  | 
 | ||||||
|  | app | ||||||
|  |   Holds all the code that's specific to this particular application. | ||||||
|  | 
 | ||||||
|  | app/controllers | ||||||
|  |   Holds controllers that should be named like weblogs_controller.rb for | ||||||
|  |   automated URL mapping. All controllers should descend from | ||||||
|  |   ApplicationController which itself descends from ActionController::Base. | ||||||
|  | 
 | ||||||
|  | app/models | ||||||
|  |   Holds models that should be named like post.rb. Models descend from | ||||||
|  |   ActiveRecord::Base by default. | ||||||
|  | 
 | ||||||
|  | app/views | ||||||
|  |   Holds the template files for the view that should be named like | ||||||
|  |   weblogs/index.html.erb for the WeblogsController#index action. All views use | ||||||
|  |   eRuby syntax by default. | ||||||
|  | 
 | ||||||
|  | app/views/layouts | ||||||
|  |   Holds the template files for layouts to be used with views. This models the | ||||||
|  |   common header/footer method of wrapping views. In your views, define a layout | ||||||
|  |   using the <tt>layout :default</tt> and create a file named default.html.erb. | ||||||
|  |   Inside default.html.erb, call <% yield %> to render the view using this | ||||||
|  |   layout. | ||||||
|  | 
 | ||||||
|  | app/helpers | ||||||
|  |   Holds view helpers that should be named like weblogs_helper.rb. These are | ||||||
|  |   generated for you automatically when using generators for controllers. | ||||||
|  |   Helpers can be used to wrap functionality for your views into methods. | ||||||
|  | 
 | ||||||
|  | config | ||||||
|  |   Configuration files for the Rails environment, the routing map, the database, | ||||||
|  |   and other dependencies. | ||||||
|  | 
 | ||||||
|  | db | ||||||
|  |   Contains the database schema in schema.rb. db/migrate contains all the | ||||||
|  |   sequence of Migrations for your schema. | ||||||
|  | 
 | ||||||
|  | doc | ||||||
|  |   This directory is where your application documentation will be stored when | ||||||
|  |   generated using <tt>rake doc:app</tt> | ||||||
|  | 
 | ||||||
|  | lib | ||||||
|  |   Application specific libraries. Basically, any kind of custom code that | ||||||
|  |   doesn't belong under controllers, models, or helpers. This directory is in | ||||||
|  |   the load path. | ||||||
|  | 
 | ||||||
|  | public | ||||||
|  |   The directory available for the web server. Contains subdirectories for | ||||||
|  |   images, stylesheets, and javascripts. Also contains the dispatchers and the | ||||||
|  |   default HTML files. This should be set as the DOCUMENT_ROOT of your web | ||||||
|  |   server. | ||||||
|  | 
 | ||||||
|  | script | ||||||
|  |   Helper scripts for automation and generation. | ||||||
|  | 
 | ||||||
|  | test | ||||||
|  |   Unit and functional tests along with fixtures. When using the rails generate | ||||||
|  |   command, template test files will be generated for you and placed in this | ||||||
|  |   directory. | ||||||
|  | 
 | ||||||
|  | vendor | ||||||
|  |   External libraries that the application depends on. Also includes the plugins | ||||||
|  |   subdirectory. If the app has frozen rails, those gems also go here, under | ||||||
|  |   vendor/rails/. This directory is in the load path. | ||||||
|  | @ -0,0 +1,261 @@ | ||||||
|  | == Welcome to Rails | ||||||
|  | 
 | ||||||
|  | Rails is a web-application framework that includes everything needed to create | ||||||
|  | database-backed web applications according to the Model-View-Control pattern. | ||||||
|  | 
 | ||||||
|  | This pattern splits the view (also called the presentation) into "dumb" | ||||||
|  | templates that are primarily responsible for inserting pre-built data in between | ||||||
|  | HTML tags. The model contains the "smart" domain objects (such as Account, | ||||||
|  | Product, Person, Post) that holds all the business logic and knows how to | ||||||
|  | persist themselves to a database. The controller handles the incoming requests | ||||||
|  | (such as Save New Account, Update Product, Show Post) by manipulating the model | ||||||
|  | and directing data to the view. | ||||||
|  | 
 | ||||||
|  | In Rails, the model is handled by what's called an object-relational mapping | ||||||
|  | layer entitled Active Record. This layer allows you to present the data from | ||||||
|  | database rows as objects and embellish these data objects with business logic | ||||||
|  | methods. You can read more about Active Record in | ||||||
|  | link:files/vendor/rails/activerecord/README.html. | ||||||
|  | 
 | ||||||
|  | The controller and view are handled by the Action Pack, which handles both | ||||||
|  | layers by its two parts: Action View and Action Controller. These two layers | ||||||
|  | are bundled in a single package due to their heavy interdependence. This is | ||||||
|  | unlike the relationship between the Active Record and Action Pack that is much | ||||||
|  | more separate. Each of these packages can be used independently outside of | ||||||
|  | Rails. You can read more about Action Pack in | ||||||
|  | link:files/vendor/rails/actionpack/README.html. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Getting Started | ||||||
|  | 
 | ||||||
|  | 1. At the command prompt, create a new Rails application: | ||||||
|  |        <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name) | ||||||
|  | 
 | ||||||
|  | 2. Change directory to <tt>myapp</tt> and start the web server: | ||||||
|  |        <tt>cd myapp; rails server</tt> (run with --help for options) | ||||||
|  | 
 | ||||||
|  | 3. Go to http://localhost:3000/ and you'll see: | ||||||
|  |        "Welcome aboard: You're riding Ruby on Rails!" | ||||||
|  | 
 | ||||||
|  | 4. Follow the guidelines to start developing your application. You can find | ||||||
|  | the following resources handy: | ||||||
|  | 
 | ||||||
|  | * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html | ||||||
|  | * Ruby on Rails Tutorial Book: http://www.railstutorial.org/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Debugging Rails | ||||||
|  | 
 | ||||||
|  | Sometimes your application goes wrong. Fortunately there are a lot of tools that | ||||||
|  | will help you debug it and get it back on the rails. | ||||||
|  | 
 | ||||||
|  | First area to check is the application log files. Have "tail -f" commands | ||||||
|  | running on the server.log and development.log. Rails will automatically display | ||||||
|  | debugging and runtime information to these files. Debugging info will also be | ||||||
|  | shown in the browser on requests from 127.0.0.1. | ||||||
|  | 
 | ||||||
|  | You can also log your own messages directly into the log file from your code | ||||||
|  | using the Ruby logger class from inside your controllers. Example: | ||||||
|  | 
 | ||||||
|  |   class WeblogController < ActionController::Base | ||||||
|  |     def destroy | ||||||
|  |       @weblog = Weblog.find(params[:id]) | ||||||
|  |       @weblog.destroy | ||||||
|  |       logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  | The result will be a message in your log file along the lines of: | ||||||
|  | 
 | ||||||
|  |   Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! | ||||||
|  | 
 | ||||||
|  | More information on how to use the logger is at http://www.ruby-doc.org/core/ | ||||||
|  | 
 | ||||||
|  | Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are | ||||||
|  | several books available online as well: | ||||||
|  | 
 | ||||||
|  | * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) | ||||||
|  | * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) | ||||||
|  | 
 | ||||||
|  | These two books will bring you up to speed on the Ruby language and also on | ||||||
|  | programming in general. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Debugger | ||||||
|  | 
 | ||||||
|  | Debugger support is available through the debugger command when you start your | ||||||
|  | Mongrel or WEBrick server with --debugger. This means that you can break out of | ||||||
|  | execution at any point in the code, investigate and change the model, and then, | ||||||
|  | resume execution! You need to install ruby-debug to run the server in debugging | ||||||
|  | mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example: | ||||||
|  | 
 | ||||||
|  |   class WeblogController < ActionController::Base | ||||||
|  |     def index | ||||||
|  |       @posts = Post.all | ||||||
|  |       debugger | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  | So the controller will accept the action, run the first line, then present you | ||||||
|  | with a IRB prompt in the server window. Here you can do things like: | ||||||
|  | 
 | ||||||
|  |   >> @posts.inspect | ||||||
|  |   => "[#<Post:0x14a6be8 | ||||||
|  |           @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>, | ||||||
|  |        #<Post:0x14a6620 | ||||||
|  |           @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]" | ||||||
|  |   >> @posts.first.title = "hello from a debugger" | ||||||
|  |   => "hello from a debugger" | ||||||
|  | 
 | ||||||
|  | ...and even better, you can examine how your runtime objects actually work: | ||||||
|  | 
 | ||||||
|  |   >> f = @posts.first | ||||||
|  |   => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}> | ||||||
|  |   >> f. | ||||||
|  |   Display all 152 possibilities? (y or n) | ||||||
|  | 
 | ||||||
|  | Finally, when you're ready to resume execution, you can enter "cont". | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == Console | ||||||
|  | 
 | ||||||
|  | The console is a Ruby shell, which allows you to interact with your | ||||||
|  | application's domain model. Here you'll have all parts of the application | ||||||
|  | configured, just like it is when the application is running. You can inspect | ||||||
|  | domain models, change values, and save to the database. Starting the script | ||||||
|  | without arguments will launch it in the development environment. | ||||||
|  | 
 | ||||||
|  | To start the console, run <tt>rails console</tt> from the application | ||||||
|  | directory. | ||||||
|  | 
 | ||||||
|  | Options: | ||||||
|  | 
 | ||||||
|  | * Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications | ||||||
|  |   made to the database. | ||||||
|  | * Passing an environment name as an argument will load the corresponding | ||||||
|  |   environment. Example: <tt>rails console production</tt>. | ||||||
|  | 
 | ||||||
|  | To reload your controllers and models after launching the console run | ||||||
|  | <tt>reload!</tt> | ||||||
|  | 
 | ||||||
|  | More information about irb can be found at: | ||||||
|  | link:http://www.rubycentral.org/pickaxe/irb.html | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | == dbconsole | ||||||
|  | 
 | ||||||
|  | You can go to the command line of your database directly through <tt>rails | ||||||
|  | dbconsole</tt>. You would be connected to the database with the credentials | ||||||
|  | defined in database.yml. Starting the script without arguments will connect you | ||||||
|  | to the development database. Passing an argument will connect you to a different | ||||||
|  | database, like <tt>rails dbconsole production</tt>. Currently works for MySQL, | ||||||
|  | PostgreSQL and SQLite 3. | ||||||
|  | 
 | ||||||
|  | == Description of Contents | ||||||
|  | 
 | ||||||
|  | The default directory structure of a generated Ruby on Rails application: | ||||||
|  | 
 | ||||||
|  |   |-- app | ||||||
|  |   |   |-- assets | ||||||
|  |   |       |-- images | ||||||
|  |   |       |-- javascripts | ||||||
|  |   |       `-- stylesheets | ||||||
|  |   |   |-- controllers | ||||||
|  |   |   |-- helpers | ||||||
|  |   |   |-- mailers | ||||||
|  |   |   |-- models | ||||||
|  |   |   `-- views | ||||||
|  |   |       `-- layouts | ||||||
|  |   |-- config | ||||||
|  |   |   |-- environments | ||||||
|  |   |   |-- initializers | ||||||
|  |   |   `-- locales | ||||||
|  |   |-- db | ||||||
|  |   |-- doc | ||||||
|  |   |-- lib | ||||||
|  |   |   `-- tasks | ||||||
|  |   |-- log | ||||||
|  |   |-- public | ||||||
|  |   |-- script | ||||||
|  |   |-- test | ||||||
|  |   |   |-- fixtures | ||||||
|  |   |   |-- functional | ||||||
|  |   |   |-- integration | ||||||
|  |   |   |-- performance | ||||||
|  |   |   `-- unit | ||||||
|  |   |-- tmp | ||||||
|  |   |   |-- cache | ||||||
|  |   |   |-- pids | ||||||
|  |   |   |-- sessions | ||||||
|  |   |   `-- sockets | ||||||
|  |   `-- vendor | ||||||
|  |       |-- assets | ||||||
|  |           `-- stylesheets | ||||||
|  |       `-- plugins | ||||||
|  | 
 | ||||||
|  | app | ||||||
|  |   Holds all the code that's specific to this particular application. | ||||||
|  | 
 | ||||||
|  | app/assets | ||||||
|  |   Contains subdirectories for images, stylesheets, and JavaScript files. | ||||||
|  | 
 | ||||||
|  | app/controllers | ||||||
|  |   Holds controllers that should be named like weblogs_controller.rb for | ||||||
|  |   automated URL mapping. All controllers should descend from | ||||||
|  |   ApplicationController which itself descends from ActionController::Base. | ||||||
|  | 
 | ||||||
|  | app/models | ||||||
|  |   Holds models that should be named like post.rb. Models descend from | ||||||
|  |   ActiveRecord::Base by default. | ||||||
|  | 
 | ||||||
|  | app/views | ||||||
|  |   Holds the template files for the view that should be named like | ||||||
|  |   weblogs/index.html.erb for the WeblogsController#index action. All views use | ||||||
|  |   eRuby syntax by default. | ||||||
|  | 
 | ||||||
|  | app/views/layouts | ||||||
|  |   Holds the template files for layouts to be used with views. This models the | ||||||
|  |   common header/footer method of wrapping views. In your views, define a layout | ||||||
|  |   using the <tt>layout :default</tt> and create a file named default.html.erb. | ||||||
|  |   Inside default.html.erb, call <% yield %> to render the view using this | ||||||
|  |   layout. | ||||||
|  | 
 | ||||||
|  | app/helpers | ||||||
|  |   Holds view helpers that should be named like weblogs_helper.rb. These are | ||||||
|  |   generated for you automatically when using generators for controllers. | ||||||
|  |   Helpers can be used to wrap functionality for your views into methods. | ||||||
|  | 
 | ||||||
|  | config | ||||||
|  |   Configuration files for the Rails environment, the routing map, the database, | ||||||
|  |   and other dependencies. | ||||||
|  | 
 | ||||||
|  | db | ||||||
|  |   Contains the database schema in schema.rb. db/migrate contains all the | ||||||
|  |   sequence of Migrations for your schema. | ||||||
|  | 
 | ||||||
|  | doc | ||||||
|  |   This directory is where your application documentation will be stored when | ||||||
|  |   generated using <tt>rake doc:app</tt> | ||||||
|  | 
 | ||||||
|  | lib | ||||||
|  |   Application specific libraries. Basically, any kind of custom code that | ||||||
|  |   doesn't belong under controllers, models, or helpers. This directory is in | ||||||
|  |   the load path. | ||||||
|  | 
 | ||||||
|  | public | ||||||
|  |   The directory available for the web server. Also contains the dispatchers and the | ||||||
|  |   default HTML files. This should be set as the DOCUMENT_ROOT of your web | ||||||
|  |   server. | ||||||
|  | 
 | ||||||
|  | script | ||||||
|  |   Helper scripts for automation and generation. | ||||||
|  | 
 | ||||||
|  | test | ||||||
|  |   Unit and functional tests along with fixtures. When using the rails generate | ||||||
|  |   command, template test files will be generated for you and placed in this | ||||||
|  |   directory. | ||||||
|  | 
 | ||||||
|  | vendor | ||||||
|  |   External libraries that the application depends on. Also includes the plugins | ||||||
|  |   subdirectory. If the app has frozen rails, those gems also go here, under | ||||||
|  |   vendor/rails/. This directory is in the load path. | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | #!/usr/bin/env rake | ||||||
|  | # Add your own tasks in files placed in lib/tasks ending in .rake, | ||||||
|  | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. | ||||||
|  | 
 | ||||||
|  | require File.expand_path('../config/application', __FILE__) | ||||||
|  | 
 | ||||||
|  | TestApp::Application.load_tasks | ||||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 6.5 KiB | 
|  | @ -0,0 +1,15 @@ | ||||||
|  | // This is a manifest file that'll be compiled into application.js, which will include all the files
 | ||||||
|  | // listed below.
 | ||||||
|  | //
 | ||||||
|  | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
 | ||||||
|  | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
 | ||||||
|  | //
 | ||||||
|  | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
 | ||||||
|  | // the compiled file.
 | ||||||
|  | //
 | ||||||
|  | // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
 | ||||||
|  | // GO AFTER THE REQUIRES BELOW.
 | ||||||
|  | //
 | ||||||
|  | //= require jquery
 | ||||||
|  | //= require jquery_ujs
 | ||||||
|  | //= require_tree .
 | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | /* | ||||||
|  |  * This is a manifest file that'll be compiled into application.css, which will include all the files | ||||||
|  |  * listed below. | ||||||
|  |  * | ||||||
|  |  * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, | ||||||
|  |  * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. | ||||||
|  |  * | ||||||
|  |  * You're free to add application-wide styles to this file and they'll appear at the top of the | ||||||
|  |  * compiled file, but it's generally better to create a new file per style scope. | ||||||
|  |  * | ||||||
|  |  *= require_self | ||||||
|  |  *= require_tree . | ||||||
|  | */ | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | class ApplicationController < ActionController::Base | ||||||
|  |   protect_from_forgery | ||||||
|  |   before_filter :secondary_before_filter | ||||||
|  | 
 | ||||||
|  |   def secondary_before_filter | ||||||
|  |     @test_secondary_before_filter = "this is a test" | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | class ArticlesController < ApplicationController | ||||||
|  |   before_filter :test_current_user_var | ||||||
|  | 
 | ||||||
|  |   def test_current_user_var | ||||||
|  |     if session[:user_id] | ||||||
|  |       @current_user = User.new | ||||||
|  |       @current_user.id = session[:user_id] | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def index | ||||||
|  |     impressionist(Article.first,"this is a test article impression") | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def show | ||||||
|  |     impressionist(Article.first) | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | # This controller imports the impressionist module to make the modules methods available for testing | ||||||
|  | class DummyController < ActionController::Base | ||||||
|  | 
 | ||||||
|  |   impressionist | ||||||
|  | 
 | ||||||
|  | end | ||||||
|  | @ -0,0 +1,23 @@ | ||||||
|  | class PostsController < ApplicationController | ||||||
|  |   helper_method :current_user | ||||||
|  |   impressionist | ||||||
|  |   def index | ||||||
|  | 
 | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def show | ||||||
|  | 
 | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def edit | ||||||
|  | 
 | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def current_user | ||||||
|  |     if session[:user_id] | ||||||
|  |       user = User.new | ||||||
|  |       user.id = session[:user_id] | ||||||
|  |       @current_user ||= user | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | class WidgetsController < ApplicationController | ||||||
|  |   impressionist :actions=>[:show,:index], :unique => [:controller_name,:action_name,:impressionable_id] | ||||||
|  | 
 | ||||||
|  |   def show | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def index | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def new | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | module ApplicationHelper | ||||||
|  | end | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | class Article < ActiveRecord::Base | ||||||
|  |   is_impressionable | ||||||
|  | end | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | # We don't really care about this model. It's just being used to test the uniqueness controller | ||||||
|  | # specs. Nevertheless, we need a model because the counter caching functionality expects it. | ||||||
|  | # | ||||||
|  | class Dummy < ActiveRecord::Base | ||||||
|  |   self.abstract_class = true # doesn't need to be backed by an actual table | ||||||
|  |   is_impressionable | ||||||
|  | end | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | class Post < ActiveRecord::Base | ||||||
|  |   is_impressionable | ||||||
|  | end | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | class User | ||||||
|  |   attr_accessor :id | ||||||
|  | end | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | class Widget < ActiveRecord::Base | ||||||
|  |   is_impressionable :counter_cache => true | ||||||
|  | end | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | <%=@impressionist_hash==nil%> | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | <%=link_to "Same Page", article_url(Article.first)%> | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  | <head> | ||||||
|  |   <title>TestApp</title> | ||||||
|  |   <%= stylesheet_link_tag    "application", :media => "all" %> | ||||||
|  |   <%= javascript_include_tag "application" %> | ||||||
|  |   <%= csrf_meta_tags %> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | <%= yield %> | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -0,0 +1,4 @@ | ||||||
|  | # This file is used by Rack-based servers to start the application. | ||||||
|  | 
 | ||||||
|  | require ::File.expand_path('../config/environment',  __FILE__) | ||||||
|  | run TestApp::Application | ||||||
|  | @ -0,0 +1,59 @@ | ||||||
|  | require File.expand_path('../boot', __FILE__) | ||||||
|  | 
 | ||||||
|  | require 'rails/all' | ||||||
|  | 
 | ||||||
|  | if defined?(Bundler) | ||||||
|  |   # If you precompile assets before deploying to production, use this line | ||||||
|  |   Bundler.require(*Rails.groups(:assets => %w(development test))) | ||||||
|  |   # If you want your assets lazily compiled in production, use this line | ||||||
|  |   # Bundler.require(:default, :assets, Rails.env) | ||||||
|  | end | ||||||
|  | 
 | ||||||
|  | module TestApp | ||||||
|  |   class Application < Rails::Application | ||||||
|  |     # Settings in config/environments/* take precedence over those specified here. | ||||||
|  |     # Application configuration should go into files in config/initializers | ||||||
|  |     # -- all .rb files in that directory are automatically loaded. | ||||||
|  | 
 | ||||||
|  |     # Custom directories with classes and modules you want to be autoloadable. | ||||||
|  |     # config.autoload_paths += %W(#{config.root}/extras) | ||||||
|  | 
 | ||||||
|  |     # Only load the plugins named here, in the order given (default is alphabetical). | ||||||
|  |     # :all can be used as a placeholder for all plugins not explicitly named. | ||||||
|  |     # config.plugins = [ :exception_notification, :ssl_requirement, :all ] | ||||||
|  | 
 | ||||||
|  |     # Activate observers that should always be running. | ||||||
|  |     # config.active_record.observers = :cacher, :garbage_collector, :forum_observer | ||||||
|  | 
 | ||||||
|  |     # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. | ||||||
|  |     # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. | ||||||
|  |     # config.time_zone = 'Central Time (US & Canada)' | ||||||
|  | 
 | ||||||
|  |     # 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 | ||||||
|  | 
 | ||||||
|  |     # Configure the default encoding used in templates for Ruby 1.9. | ||||||
|  |     config.encoding = "utf-8" | ||||||
|  | 
 | ||||||
|  |     # Configure sensitive parameters which will be filtered from the log file. | ||||||
|  |     config.filter_parameters += [:password] | ||||||
|  | 
 | ||||||
|  |     # Use SQL instead of Active Record's schema dumper when creating the database. | ||||||
|  |     # This is necessary if your schema can't be completely dumped by the schema dumper, | ||||||
|  |     # like if you have constraints or database-specific column types | ||||||
|  |     # config.active_record.schema_format = :sql | ||||||
|  | 
 | ||||||
|  |     # Enforce whitelist mode for mass assignment. | ||||||
|  |     # This will create an empty whitelist of attributes available for mass-assignment for all models | ||||||
|  |     # in your app. As such, your models will need to explicitly whitelist or blacklist accessible | ||||||
|  |     # parameters by using an attr_accessible or attr_protected declaration. | ||||||
|  |     # config.active_record.whitelist_attributes = true | ||||||
|  | 
 | ||||||
|  |     # Enable the asset pipeline | ||||||
|  |     config.assets.enabled = true | ||||||
|  | 
 | ||||||
|  |     # Version of your assets, change this if you want to expire all your assets | ||||||
|  |     config.assets.version = '1.0' | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,6 @@ | ||||||
|  | require 'rubygems' | ||||||
|  | 
 | ||||||
|  | # Set up gems listed in the Gemfile. | ||||||
|  | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) | ||||||
|  | 
 | ||||||
|  | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | <% | ||||||
|  | rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" | ||||||
|  | rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}" | ||||||
|  | std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip" | ||||||
|  | %> | ||||||
|  | default: --drb <%= std_opts %> features | ||||||
|  | wip: --drb --tags @wip:3 --wip features | ||||||
|  | rerun: --drb <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue