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
|
||||||
|
@ -35,5 +36,18 @@ class Admin::DashboardsController < ApplicationController
|
||||||
sorted_objects = a.sort {|a,b| b[1]<=>a[1]}
|
sorted_objects = a.sort {|a,b| b[1]<=>a[1]}
|
||||||
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'
|
||||||
|
@ -14,18 +15,19 @@ class PagesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
#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))
|
||||||
case @item._type
|
impressionist(@item)
|
||||||
when 'Page'
|
case @item._type
|
||||||
render_page
|
when 'Page'
|
||||||
when 'Link'
|
render_page
|
||||||
redirect_to "http://#{@item[:url]}"
|
when 'Link'
|
||||||
end
|
redirect_to @item[:url]
|
||||||
else
|
end
|
||||||
render :file => "#{Rails.root}/public/404.html", :status => :not_found
|
else
|
||||||
end
|
render :file => "#{Rails.root}/public/404.html", :status => :not_found
|
||||||
|
end
|
||||||
#rescue
|
#rescue
|
||||||
# render :file => "#{Rails.root}/public/404.html", :status => :not_found
|
# render :file => "#{Rails.root}/public/404.html", :status => :not_found
|
||||||
#end
|
#end
|
||||||
|
@ -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]})
|
||||||
# @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]})
|
|
||||||
# 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
|
||||||
:host => 'mruling.nccu.edu.tw', #mruling.nccu.edu.tw or 127.0.0.1
|
|
||||||
:port => 3306, #3306 or 8005
|
@mid_host = {
|
||||||
:username => "root",
|
:host => 'mruling.nccu.edu.tw', #mruling.nccu.edu.tw or 127.0.0.1
|
||||||
:password => "a3G6yWd9",
|
:port => 3306, #3306 or 8005
|
||||||
:database => "RSS23_NCCU_MIDDLE",
|
:username => "rulingcom",
|
||||||
:encoding => "UTF8"
|
:password => "5w3iJQ9OJQMGhJibKP6YQje8",
|
||||||
}
|
:database => "RSS23_NCCU_MIDDLE",
|
||||||
MID_CLIENT = Mysql2::Client.new(mid_host)
|
:encoding => "UTF8"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
class NewsBulletin
|
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,10 +6,10 @@ 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
|
||||||
format.xml { render :xml => @page_contexts }
|
format.xml { render :xml => @page_contexts }
|
||||||
|
|
|
@ -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,23 +1,23 @@
|
||||||
|
<tr id="<%= dom_id page_context %>" class="with_action">
|
||||||
<tr id="<%= dom_id page_context %>" class="with_action">
|
<td>
|
||||||
<td>
|
<%= page_context.page.path %></br>
|
||||||
<%= page_context.page.path %>
|
<%= 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)%>
|
||||||
<li><%= link_to t('admin.page_context.edit'), edit_panel_page_content_back_end_page_context_path(page_context) %></li>
|
<li><%= link_to t('admin.page_context.edit'), edit_panel_page_content_back_end_page_context_path(page_context) %></li>
|
||||||
<%if (is_manager? || is_admin?) %>
|
<%if (is_manager? || is_admin?) %>
|
||||||
<li><%=show_page_context_edit_auth_link page_context%></li>
|
<li><%=show_page_context_edit_auth_link page_context%></li>
|
||||||
<% end%>
|
<% end%>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<%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)%>
|
||||||
<%= link_to page_context.version, panel_page_content_back_end_view_path(page_context.page_id) %>
|
<%= link_to page_context.version, panel_page_content_back_end_view_path(page_context.page_id) %>
|
||||||
<%end -%>
|
<%end -%>
|
||||||
</td>
|
</td>
|
||||||
<td><%= page_context.updated_at.strftime("%Y-%m-%d %H:%I:%S") %></td>
|
<td><%= page_context.updated_at.strftime("%Y-%m-%d %H:%I:%S") %></td>
|
||||||
<td><%= User.find(page_context.create_user_id).name %></td>
|
<td><%= User.find(page_context.create_user_id).name %></td>
|
||||||
</tr>
|
</tr>
|
|
@ -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 @@
|
||||||
|
![Impressionist Logo](https://github.com/charlotte-ruby/impressionist/raw/master/logo.png)
|
||||||
|
|
||||||
|
[![Build Status](https://secure.travis-ci.org/charlotte-ruby/impressionist.png?branch=master)](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
Reference in New Issue