best_boy 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -2
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +24 -10
- data/app/controllers/best_boy/best_boy_events_controller.rb +112 -12
- data/app/views/best_boy/best_boy_events/_navigation.html.erb +1 -1
- data/app/views/best_boy/best_boy_events/charts.html.erb +26 -0
- data/app/views/best_boy/best_boy_events/details.html.erb +66 -0
- data/app/views/best_boy/best_boy_events/lists.html.erb +2 -1
- data/app/views/best_boy/best_boy_events/stats.html.erb +4 -2
- data/app/views/layouts/best_boy_backend.html.erb +1 -0
- data/best_boy.gemspec +2 -1
- data/config/routes.rb +2 -0
- data/db/bestboy.db +0 -0
- data/lib/best_boy/controllers/best_boy_controller.rb +2 -6
- data/lib/best_boy/engine.rb +1 -1
- data/lib/best_boy/models/active_record/best_boy/eventable.rb +29 -24
- data/lib/best_boy/models/active_record/best_boy_event.rb +1 -1
- data/lib/best_boy/version.rb +1 -1
- data/lib/generators/active_record/best_boy_generator.rb +6 -1
- data/lib/generators/active_record/templates/add_event_source_to_best_boy_events_table.rb +11 -0
- data/spec/best_boy/best_boy_event_spec.rb +4 -2
- data/spec/spec_helper.rb +1 -0
- metadata +31 -17
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
best_boy
|
2
2
|
========
|
3
|
-
[![Build Status](https://secure.travis-ci.org/
|
3
|
+
[![Build Status](https://secure.travis-ci.org/Absolventa/best_boy.png?branch=master)](https://secure.travis-ci.org/Absolventa/best_boy)
|
4
4
|
|
5
5
|
A simple event driven logging for ActiveRecord models.
|
6
|
+
This gem moved from cseydel/best_boy to absolventa/best_boy
|
6
7
|
|
7
8
|
|
8
9
|
What does this gem do?
|
@@ -46,6 +47,18 @@ Run the migration
|
|
46
47
|
rake db:migrate
|
47
48
|
|
48
49
|
|
50
|
+
Update from version 0.1.0
|
51
|
+
-------------------------
|
52
|
+
|
53
|
+
Rerun the generator to get needed migrations
|
54
|
+
|
55
|
+
rails g best_boy
|
56
|
+
|
57
|
+
Run the migration
|
58
|
+
|
59
|
+
rake db:migrate
|
60
|
+
|
61
|
+
|
49
62
|
Usage
|
50
63
|
-----
|
51
64
|
|
@@ -55,11 +68,15 @@ In model context:
|
|
55
68
|
|
56
69
|
This will log "create" and "delete" event for each instance.
|
57
70
|
|
71
|
+
If you do not want to selflog create and delete events, maybe because you will sort it semantically with a create source, just deactivate the callback logging by setting the parameter :disable_callbacks to true.
|
72
|
+
|
73
|
+
has_a_best_boy :disable_callbacks => true
|
74
|
+
|
58
75
|
In controller context:
|
59
76
|
|
60
|
-
best_boy_event object, event
|
77
|
+
best_boy_event object, event, event_source = nil
|
61
78
|
|
62
|
-
This will log custom events for a object and a event phrase.
|
79
|
+
This will log custom events for a object and a event phrase. You can specify this event with a event_source parameter to log maybe seperate create actions.
|
63
80
|
|
64
81
|
If no Object is given, it will raise an exception as well as if no event is provided.
|
65
82
|
|
@@ -70,6 +87,7 @@ BestBoyEvent table
|
|
70
87
|
t.integer "owner_id" # owner model id
|
71
88
|
t.string "owner_type" # owner model class type
|
72
89
|
t.string "event" # event (create, delete)
|
90
|
+
t.string "event_source" # event_source parameter for specific action tracking
|
73
91
|
t.datetime "updated_at" # last update timestamp
|
74
92
|
t.datetime "created_at" # creation timestamp
|
75
93
|
|
@@ -97,15 +115,11 @@ Used gems and resource
|
|
97
115
|
|
98
116
|
[Stefan Petre](http://www.eyecon.ro/bootstrap-datepicker) for Datepicker in Twitter Bootstrap style
|
99
117
|
|
118
|
+
[Winston Teo Yong Wei](https://github.com/winston/google_visualr) Google_Visulr in its version 2.1.2
|
119
|
+
|
100
120
|
Thanks
|
101
121
|
------
|
102
122
|
|
103
123
|
Big thanks to each contributor on Impressionist. This gem helped me a long way to get here in modelling and creating a gem.
|
104
124
|
|
105
|
-
|
106
|
-
-----------------
|
107
|
-
It's my first gem, be gentle ;)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
Copyright (c) 2012 Christoph Seydel. See LICENSE.txt for further details.
|
125
|
+
Copyright (c) 2012 Absolventa GmbH. See LICENSE.txt for further details.
|
@@ -2,42 +2,128 @@ module BestBoy
|
|
2
2
|
class BestBoyEventsController < BestBoy.base_controller.constantize
|
3
3
|
|
4
4
|
before_filter BestBoy.before_filter if BestBoy.before_filter.present?
|
5
|
+
before_filter :prepare_chart, :only => [:charts]
|
5
6
|
skip_before_filter BestBoy.skip_before_filter if BestBoy.skip_before_filter.present?
|
6
7
|
|
7
8
|
layout 'best_boy_backend'
|
8
9
|
|
9
|
-
helper_method :available_owner_types, :available_events, :
|
10
|
+
helper_method :available_owner_types, :available_events, :available_event_sources, :available_years, :current_owner_type,
|
11
|
+
:current_event, :current_event_source, :current_year, :collection, :statistics, :stats_by_event_and_month,
|
12
|
+
:stats_by_event_source_and_month, :render_chart, :event_source_details, :month_name_array
|
10
13
|
|
11
14
|
private
|
12
15
|
|
13
|
-
def
|
14
|
-
|
16
|
+
def render_chart(chart, dom)
|
17
|
+
chart.to_js(dom).html_safe
|
15
18
|
end
|
16
19
|
|
17
|
-
def
|
18
|
-
|
20
|
+
def week_name_array
|
21
|
+
%w(Mon Tue Wed Thu Fri Sat Sun)
|
22
|
+
end
|
23
|
+
|
24
|
+
def month_name_array
|
25
|
+
%w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
|
26
|
+
end
|
27
|
+
|
28
|
+
def custom_data_count(time)
|
29
|
+
scope = BestBoyEvent.where("best_boy_events.owner_type = ?", current_owner_type)
|
30
|
+
scope = scope.where("best_boy_events.event = ?", current_event) if current_event.present?
|
31
|
+
scope = scope.where("best_boy_events.event_source = ?", current_event_source) if current_event_source.present?
|
32
|
+
scope = scope.send("per_#{ current_time_interval == "year" ? "month" : "day" }", time)
|
33
|
+
scope.count
|
34
|
+
end
|
35
|
+
|
36
|
+
def time_periode_range
|
37
|
+
case current_time_interval
|
38
|
+
when "month"
|
39
|
+
(0..(Time.days_in_month(Time.zone.now.month) - 1))
|
40
|
+
when "week"
|
41
|
+
(0..6)
|
42
|
+
else
|
43
|
+
(0..11)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def calculated_point_in_time(periode)
|
48
|
+
case current_time_interval
|
49
|
+
when "month"
|
50
|
+
Time.zone.now.beginning_of_month + periode.days
|
51
|
+
when "week"
|
52
|
+
Time.zone.now.beginning_of_week + periode.days
|
53
|
+
else
|
54
|
+
Time.zone.now.beginning_of_year + periode.month
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def chart_legend_time_name(periode)
|
59
|
+
case current_time_interval
|
60
|
+
when "year"
|
61
|
+
month_name_array[periode]
|
62
|
+
when "week"
|
63
|
+
week_name_array[periode]
|
64
|
+
else
|
65
|
+
(periode + 1).to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def stats_by_event_and_month(event, month)
|
70
|
+
date = "1-#{month}-#{current_year}".to_time
|
71
|
+
BestBoyEvent.where("best_boy_events.owner_type = ? AND best_boy_events.event = ?", current_owner_type, event).per_month(date).count
|
72
|
+
end
|
73
|
+
|
74
|
+
def stats_by_event_source_and_month(source, month)
|
75
|
+
date = "1-#{month}-#{current_year}".to_time
|
76
|
+
BestBoyEvent.where("best_boy_events.owner_type = ? AND best_boy_events.event = ? AND best_boy_events.event_source = ?", current_owner_type, current_event, source).per_month(date).count
|
19
77
|
end
|
20
78
|
|
21
79
|
def current_date
|
22
80
|
@current_date ||= Date.strptime(params[:date], "%d-%m-%Y") if params[:date] rescue nil
|
23
81
|
end
|
24
82
|
|
83
|
+
def current_event
|
84
|
+
@current_event ||= available_events.include?(params[:event]) ? params[:event] : nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def current_event_source
|
88
|
+
@current_event_source ||= available_event_sources.include?(params[:event_source]) ? params[:event_source] : nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def current_owner_type
|
92
|
+
@current_owner_type ||= available_owner_types.include?(params[:owner_type]) ? params[:owner_type] : available_owner_types.first
|
93
|
+
end
|
94
|
+
|
95
|
+
def current_time_interval
|
96
|
+
@current_time_interval ||= %w(year month week).include?(params[:time_interval]) ? params[:time_interval] : "year"
|
97
|
+
end
|
98
|
+
|
25
99
|
def current_year
|
26
100
|
@current_year ||= available_years.include?(params[:year]) ? params[:year] : Time.zone.now.year
|
27
101
|
end
|
28
102
|
|
29
|
-
def
|
30
|
-
@
|
103
|
+
def available_events
|
104
|
+
@available_events ||= (
|
105
|
+
scope = BestBoyEvent.where("best_boy_events.owner_type = ?", current_owner_type)
|
106
|
+
scope = scope.select("best_boy_events.event").order("best_boy_events.event ASC")
|
107
|
+
scope = scope.group("best_boy_events.event").map(&:event)
|
108
|
+
)
|
31
109
|
end
|
32
110
|
|
33
|
-
def
|
34
|
-
@
|
111
|
+
def available_event_sources
|
112
|
+
@available_event_sources ||= (
|
113
|
+
scope = BestBoyEvent.where("best_boy_events.owner_type = ? AND best_boy_events.event = ?", current_owner_type, current_event)
|
114
|
+
scope = scope.select("best_boy_events.event_source").order("best_boy_events.event_source ASC")
|
115
|
+
scope = scope.group("best_boy_events.event_source").map(&:event_source)
|
116
|
+
)
|
35
117
|
end
|
36
118
|
|
37
119
|
def available_years
|
38
120
|
@available_years = (BestBoyEvent.order("best_boy_events.created_at ASC").first.created_at.to_date.year..Time.zone.now.year).map{ |year| year.to_s } rescue [Time.zone.now.year]
|
39
121
|
end
|
40
122
|
|
123
|
+
def available_owner_types
|
124
|
+
@available_owner_types ||= BestBoyEvent.select("DISTINCT best_boy_events.owner_type").order("best_boy_events.owner_type ASC").map(&:owner_type)
|
125
|
+
end
|
126
|
+
|
41
127
|
def collection
|
42
128
|
@best_boy_events ||= (
|
43
129
|
scope = BestBoyEvent.where("best_boy_events.owner_type = ?", current_owner_type)
|
@@ -57,9 +143,23 @@ module BestBoy
|
|
57
143
|
@statistics
|
58
144
|
end
|
59
145
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
146
|
+
def event_source_details
|
147
|
+
@event_source_details = Array.new
|
148
|
+
available_event_sources.each do |source|
|
149
|
+
scope = BestBoyEvent.where("best_boy_events.owner_type = ? AND best_boy_events.event = ?", current_owner_type, current_event).where("best_boy_events.event_source = ?", source)
|
150
|
+
@event_source_details.push([source, scope.count] + %w(year month week day).map{ |delimiter| scope.send("per_#{delimiter}", Time.zone.now).count })
|
151
|
+
end
|
152
|
+
@event_source_details
|
153
|
+
end
|
154
|
+
|
155
|
+
def prepare_chart
|
156
|
+
data_table = GoogleVisualr::DataTable.new
|
157
|
+
data_table.new_column('string', 'time')
|
158
|
+
data_table.new_column('number', current_owner_type.to_s)
|
159
|
+
time_periode_range.each do |periode|
|
160
|
+
data_table.add_row([chart_legend_time_name(periode), custom_data_count(calculated_point_in_time(periode))])
|
161
|
+
end
|
162
|
+
@chart = GoogleVisualr::Interactive::AreaChart.new(data_table, { width: 900, height: 240, title: "" })
|
63
163
|
end
|
64
164
|
end
|
65
165
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<ul class="nav nav-tabs">
|
3
3
|
<% available_owner_types.each do |owner_type| %>
|
4
4
|
<li class="<%= (current_owner_type == owner_type) ? 'active' : nil %>">
|
5
|
-
<%= link_to owner_type, (referrer
|
5
|
+
<%= link_to owner_type, send("best_boy_admin_#{referrer}_path", :owner_type => owner_type) %>
|
6
6
|
</li>
|
7
7
|
<% end %>
|
8
8
|
</ul>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<% content_for :javascripts do %>
|
2
|
+
<script src='http://www.google.com/jsapi'></script>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
|
6
|
+
<%= form_tag best_boy_admin_charts_path, :method => :get, :id => "chart-form" do %>
|
7
|
+
<div class="span3">
|
8
|
+
<%= select_tag :owner_type, options_for_select([["Owner", nil]] + available_owner_types, :selected => params[:owner_type]), :onchange => "submit();" %>
|
9
|
+
</div>
|
10
|
+
<div class="span3">
|
11
|
+
<%= select_tag :event, options_for_select([["Event", nil]] + available_events, :selected => params[:event]), :onchange => "submit();" %>
|
12
|
+
</div>
|
13
|
+
<div class="span3">
|
14
|
+
<%= select_tag :event_source, options_for_select([["Event Source", nil]] + available_event_sources, :selected => params[:event_source]), :onchange => "submit();" %>
|
15
|
+
</div>
|
16
|
+
<div class="span3">
|
17
|
+
<%= select_tag :time_interval, options_for_select([["Time Interval", nil], ["yearly", "year"], ["monthly", "month"], ["weekly", "week"]], :selected => params[:time_interval]), :onchange => "submit();" %>
|
18
|
+
</div>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<div class="span12">
|
22
|
+
<div class="well">
|
23
|
+
<div id='chart'></div>
|
24
|
+
<%= render_chart(@chart, 'chart') %>
|
25
|
+
</div>
|
26
|
+
</div>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
<div class="span12">
|
2
|
+
<div class="well">
|
3
|
+
<%= link_to "<< back to stats", best_boy_admin_stats_path(:owner_type => current_owner_type) %>
|
4
|
+
</div>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<div class="span12">
|
8
|
+
<div class="well">
|
9
|
+
<h3>Detailed Statistics</h3>
|
10
|
+
<table class="table table-striped table-bordered">
|
11
|
+
<thead>
|
12
|
+
<tr>
|
13
|
+
<th>Source</th>
|
14
|
+
<th>overall</th>
|
15
|
+
<th>year</th>
|
16
|
+
<th>month</th>
|
17
|
+
<th>week</th>
|
18
|
+
<th>day</th>
|
19
|
+
</tr>
|
20
|
+
</thead>
|
21
|
+
<tbody>
|
22
|
+
<% event_source_details.each do |best_boy_event_source| %>
|
23
|
+
<tr>
|
24
|
+
<% (0..5).each do |key| %>
|
25
|
+
<td><%= best_boy_event_source[key] %></td>
|
26
|
+
<% end %>
|
27
|
+
</tr>
|
28
|
+
<% end %>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<div class="span12">
|
35
|
+
<div class="well">
|
36
|
+
<h3 class="pull-left">Detailed Statistics for <%= current_year %> per month</h3>
|
37
|
+
|
38
|
+
<div class="pull-right">
|
39
|
+
<%= form_tag best_boy_admin_details_path, :method => :get do %>
|
40
|
+
<%= hidden_field_tag :owner_type, current_owner_type %>
|
41
|
+
<%= hidden_field_tag :event, current_event %>
|
42
|
+
<%= select_tag :year, options_for_select(available_years, :selected => current_year), :onchange => "submit();" %>
|
43
|
+
<% end %>
|
44
|
+
</div>
|
45
|
+
<table class="table table-striped table-bordered">
|
46
|
+
<thead>
|
47
|
+
<tr>
|
48
|
+
<th>Event</th>
|
49
|
+
<% month_name_array.each do |month| %>
|
50
|
+
<th><%= month %></th>
|
51
|
+
<% end %>
|
52
|
+
</tr>
|
53
|
+
</thead>
|
54
|
+
<tbody>
|
55
|
+
<% available_event_sources.each do |source| %>
|
56
|
+
<tr>
|
57
|
+
<td><%= source %></td>
|
58
|
+
<% %w(1 2 3 4 5 6 7 8 9 10 11 12).each do |month| %>
|
59
|
+
<td><%= stats_by_event_source_and_month source, month %></td>
|
60
|
+
<% end %>
|
61
|
+
</tr>
|
62
|
+
<% end %>
|
63
|
+
</tbody>
|
64
|
+
</table>
|
65
|
+
</div>
|
66
|
+
</div>
|
@@ -1,4 +1,3 @@
|
|
1
|
-
<%= render "navigation", :referrer => "lists" %>
|
2
1
|
<% content_for :stylesheets do %>
|
3
2
|
<%= stylesheet_link_tag "bootstrap_datepicker" %>
|
4
3
|
<% end %>
|
@@ -10,6 +9,8 @@
|
|
10
9
|
</script>
|
11
10
|
<% end %>
|
12
11
|
|
12
|
+
<%= render "navigation", :referrer => "lists" %>
|
13
|
+
|
13
14
|
<div class="span12">
|
14
15
|
<div class="well">
|
15
16
|
<h3 class="pull-left">Log</h3>
|
@@ -17,7 +17,8 @@
|
|
17
17
|
<tbody>
|
18
18
|
<% statistics.each do |best_boy_event| %>
|
19
19
|
<tr>
|
20
|
-
|
20
|
+
<td><%= link_to best_boy_event[0], best_boy_admin_details_path(:event => best_boy_event[0], :owner_type => current_owner_type) %>
|
21
|
+
<% (1..5).each do |key| %>
|
21
22
|
<td><%= best_boy_event[key] %></td>
|
22
23
|
<% end %>
|
23
24
|
</tr>
|
@@ -33,6 +34,7 @@
|
|
33
34
|
|
34
35
|
<div class="pull-right">
|
35
36
|
<%= form_tag best_boy_admin_stats_path, :method => :get do %>
|
37
|
+
<%= hidden_field_tag :owner_type, current_owner_type %>
|
36
38
|
<%= select_tag :year, options_for_select(available_years, :selected => current_year), :onchange => "submit();" %>
|
37
39
|
<% end %>
|
38
40
|
</div>
|
@@ -40,7 +42,7 @@
|
|
40
42
|
<thead>
|
41
43
|
<tr>
|
42
44
|
<th>Event</th>
|
43
|
-
<%
|
45
|
+
<% month_name_array.each do |month| %>
|
44
46
|
<th><%= month %></th>
|
45
47
|
<% end %>
|
46
48
|
</tr>
|
@@ -39,6 +39,7 @@
|
|
39
39
|
<ul class="nav">
|
40
40
|
<li><%= link_to "Statistics", best_boy_admin_stats_path %></li>
|
41
41
|
<li><%= link_to "List & Logs", best_boy_admin_lists_path %></li>
|
42
|
+
<li><%= link_to "Charts", best_boy_admin_charts_path %></li>
|
42
43
|
</ul>
|
43
44
|
<% if BestBoy.custom_redirect.present? %>
|
44
45
|
<p class="navbar-text pull-right"><%= link_to("back", Rails.application.routes.recognize_path(BestBoy.custom_redirect)) %></p>
|
data/best_boy.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.license = ['MIT']
|
10
10
|
s.authors = ["Christoph Seydel"]
|
11
11
|
s.email = ["christoph.seydel@me.com"]
|
12
|
-
s.homepage = "https://github.com/
|
12
|
+
s.homepage = "https://github.com/absolventa/best_boy"
|
13
13
|
s.summary = %q{a simple event driven logging for models}
|
14
14
|
s.description = %q{Hybrid action logging, consisting of standard and custom logging.}
|
15
15
|
|
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.required_rubygems_version = ">= 1.3.6"
|
18
18
|
|
19
19
|
s.add_dependency('kaminari')
|
20
|
+
s.add_dependency('google_visualr')
|
20
21
|
|
21
22
|
s.add_development_dependency('bundler', '~> 1.1.0')
|
22
23
|
s.add_development_dependency('activerecord')
|
data/config/routes.rb
CHANGED
@@ -2,4 +2,6 @@ Rails.application.routes.draw do |map|
|
|
2
2
|
get "best_boy_admin" => "best_boy/best_boy_events#index", :as => :best_boy_admin
|
3
3
|
get "best_boy_admin/stats" => "best_boy/best_boy_events#stats", :as => :best_boy_admin_stats
|
4
4
|
get "best_boy_admin/lists" => "best_boy/best_boy_events#lists", :as => :best_boy_admin_lists
|
5
|
+
get "best_boy_admin/charts" => "best_boy/best_boy_events#charts", :as => :best_boy_admin_charts
|
6
|
+
get "best_boy_admin/details" => "best_boy/best_boy_events#details", :as => :best_boy_admin_details
|
5
7
|
end
|
data/db/bestboy.db
ADDED
Binary file
|
@@ -1,12 +1,8 @@
|
|
1
1
|
module BestBoyController
|
2
2
|
module InstanceMethods
|
3
|
-
def best_boy_event(obj, event)
|
3
|
+
def best_boy_event(obj, event, source = nil)
|
4
4
|
if obj.respond_to?("eventable?")
|
5
|
-
|
6
|
-
obj.trigger_custom_event(event)
|
7
|
-
else
|
8
|
-
raise "There is no event to trigger."
|
9
|
-
end
|
5
|
+
obj.trigger_best_boy_event(event, source)
|
10
6
|
else
|
11
7
|
raise "#{obj.class.to_s} is not a best_boy eventable!"
|
12
8
|
end
|
data/lib/best_boy/engine.rb
CHANGED
@@ -3,11 +3,14 @@ module BestBoy
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
|
7
|
-
|
6
|
+
attr_accessor :disable_callbacks
|
7
|
+
@disable_callbacks = nil
|
8
|
+
|
9
|
+
def has_a_best_boy(options={})
|
10
|
+
# constants
|
8
11
|
#
|
9
12
|
#
|
10
|
-
|
13
|
+
@disable_callbacks = options[:disable_callbacks]
|
11
14
|
|
12
15
|
# associations
|
13
16
|
#
|
@@ -20,33 +23,35 @@ module BestBoy
|
|
20
23
|
after_create :trigger_create_event
|
21
24
|
after_destroy :trigger_destroy_event
|
22
25
|
end
|
23
|
-
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
true
|
27
|
+
def best_boy_disable_callbacks
|
28
|
+
@disable_callbacks
|
28
29
|
end
|
30
|
+
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
def eventable?
|
33
|
+
true
|
34
|
+
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
create_best_boy_event_with_type "destroy"
|
39
|
-
end
|
36
|
+
def trigger_create_event
|
37
|
+
return if self.class.best_boy_disable_callbacks
|
38
|
+
create_best_boy_event_with_type "create"
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
def trigger_destroy_event
|
42
|
+
return if self.class.best_boy_disable_callbacks
|
43
|
+
create_best_boy_event_with_type "destroy"
|
44
|
+
end
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
def trigger_best_boy_event type, source = nil
|
47
|
+
create_best_boy_event_with_type(type, source)
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_best_boy_event_with_type type, source = nil
|
51
|
+
raise "nil event is not allowed" if type.blank?
|
52
|
+
best_boy_event = BestBoyEvent.new(:event => type, :event_source => source)
|
53
|
+
best_boy_event.owner = self
|
54
|
+
best_boy_event.save
|
50
55
|
end
|
51
56
|
end
|
52
57
|
end
|
data/lib/best_boy/version.rb
CHANGED
@@ -14,7 +14,12 @@ module ActiveRecord
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def create_migration_file
|
17
|
-
|
17
|
+
%w(create_best_boy_events_table.rb add_event_source_to_best_boy_events_table.rb).each do |migration_file|
|
18
|
+
destination = "db/migrate/#{migration_file.sub(%r\.rb$\, '')}"
|
19
|
+
if not self.class.migration_exists?(File.dirname(destination), File.basename(destination))
|
20
|
+
migration_template migration_file, destination
|
21
|
+
end
|
22
|
+
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddEventSourceToBestBoyEventsTable < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :best_boy_events, :event_source, :string
|
4
|
+
add_index :best_boy_events, :event_source
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.down
|
8
|
+
remove_index :best_boy_events, :event_source
|
9
|
+
remove_column :best_boy_events, :event_source
|
10
|
+
end
|
11
|
+
end
|
@@ -3,7 +3,9 @@ require "spec_helper"
|
|
3
3
|
describe BestBoyEvent, 'with creating' do
|
4
4
|
it "should have valid model" do
|
5
5
|
example = Example.create
|
6
|
-
BestBoyEvent.create(:
|
6
|
+
best_boy_event = BestBoyEvent.create(:event => "create")
|
7
|
+
best_boy_event.owner = example
|
8
|
+
best_boy_event.should be_valid
|
7
9
|
end
|
8
10
|
end
|
9
11
|
|
@@ -22,7 +24,7 @@ describe BestBoyEvent, 'with scopes' do
|
|
22
24
|
ActiveRecord::Base.connection.execute("DELETE FROM 'best_boy_events'")
|
23
25
|
example = Example.create
|
24
26
|
(1..times).each do
|
25
|
-
example.
|
27
|
+
example.trigger_best_boy_event("year_test")
|
26
28
|
example.best_boy_events.last.update_attribute(:created_at, created_at)
|
27
29
|
end
|
28
30
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: best_boy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Christoph Seydel
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-06-
|
13
|
+
date: 2012-06-27 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -25,82 +25,93 @@ dependencies:
|
|
25
25
|
type: :runtime
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: google_visualr
|
29
29
|
prerelease: false
|
30
30
|
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: bundler
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
31
42
|
none: false
|
32
43
|
requirements:
|
33
44
|
- - ~>
|
34
45
|
- !ruby/object:Gem::Version
|
35
46
|
version: 1.1.0
|
36
47
|
type: :development
|
37
|
-
version_requirements: *
|
48
|
+
version_requirements: *id003
|
38
49
|
- !ruby/object:Gem::Dependency
|
39
50
|
name: activerecord
|
40
51
|
prerelease: false
|
41
|
-
requirement: &
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
42
53
|
none: false
|
43
54
|
requirements:
|
44
55
|
- - ">="
|
45
56
|
- !ruby/object:Gem::Version
|
46
57
|
version: "0"
|
47
58
|
type: :development
|
48
|
-
version_requirements: *
|
59
|
+
version_requirements: *id004
|
49
60
|
- !ruby/object:Gem::Dependency
|
50
61
|
name: activesupport
|
51
62
|
prerelease: false
|
52
|
-
requirement: &
|
63
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
53
64
|
none: false
|
54
65
|
requirements:
|
55
66
|
- - ">="
|
56
67
|
- !ruby/object:Gem::Version
|
57
68
|
version: "0"
|
58
69
|
type: :development
|
59
|
-
version_requirements: *
|
70
|
+
version_requirements: *id005
|
60
71
|
- !ruby/object:Gem::Dependency
|
61
72
|
name: sqlite3
|
62
73
|
prerelease: false
|
63
|
-
requirement: &
|
74
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
64
75
|
none: false
|
65
76
|
requirements:
|
66
77
|
- - ~>
|
67
78
|
- !ruby/object:Gem::Version
|
68
79
|
version: 1.3.6
|
69
80
|
type: :development
|
70
|
-
version_requirements: *
|
81
|
+
version_requirements: *id006
|
71
82
|
- !ruby/object:Gem::Dependency
|
72
83
|
name: rake
|
73
84
|
prerelease: false
|
74
|
-
requirement: &
|
85
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
75
86
|
none: false
|
76
87
|
requirements:
|
77
88
|
- - ~>
|
78
89
|
- !ruby/object:Gem::Version
|
79
90
|
version: 0.9.2.2
|
80
91
|
type: :development
|
81
|
-
version_requirements: *
|
92
|
+
version_requirements: *id007
|
82
93
|
- !ruby/object:Gem::Dependency
|
83
94
|
name: rspec
|
84
95
|
prerelease: false
|
85
|
-
requirement: &
|
96
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
86
97
|
none: false
|
87
98
|
requirements:
|
88
99
|
- - ~>
|
89
100
|
- !ruby/object:Gem::Version
|
90
101
|
version: 2.10.0
|
91
102
|
type: :development
|
92
|
-
version_requirements: *
|
103
|
+
version_requirements: *id008
|
93
104
|
- !ruby/object:Gem::Dependency
|
94
105
|
name: shoulda
|
95
106
|
prerelease: false
|
96
|
-
requirement: &
|
107
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
97
108
|
none: false
|
98
109
|
requirements:
|
99
110
|
- - ~>
|
100
111
|
- !ruby/object:Gem::Version
|
101
112
|
version: 3.0.1
|
102
113
|
type: :development
|
103
|
-
version_requirements: *
|
114
|
+
version_requirements: *id009
|
104
115
|
description: Hybrid action logging, consisting of standard and custom logging.
|
105
116
|
email:
|
106
117
|
- christoph.seydel@me.com
|
@@ -121,6 +132,8 @@ files:
|
|
121
132
|
- Rakefile
|
122
133
|
- app/controllers/best_boy/best_boy_events_controller.rb
|
123
134
|
- app/views/best_boy/best_boy_events/_navigation.html.erb
|
135
|
+
- app/views/best_boy/best_boy_events/charts.html.erb
|
136
|
+
- app/views/best_boy/best_boy_events/details.html.erb
|
124
137
|
- app/views/best_boy/best_boy_events/index.html.erb
|
125
138
|
- app/views/best_boy/best_boy_events/lists.html.erb
|
126
139
|
- app/views/best_boy/best_boy_events/stats.html.erb
|
@@ -135,6 +148,7 @@ files:
|
|
135
148
|
- lib/best_boy/models/active_record/best_boy_event.rb
|
136
149
|
- lib/best_boy/version.rb
|
137
150
|
- lib/generators/active_record/best_boy_generator.rb
|
151
|
+
- lib/generators/active_record/templates/add_event_source_to_best_boy_events_table.rb
|
138
152
|
- lib/generators/active_record/templates/create_best_boy_events_table.rb
|
139
153
|
- lib/generators/best_boy_generator.rb
|
140
154
|
- lib/generators/templates/best_boy.rb
|
@@ -149,7 +163,7 @@ files:
|
|
149
163
|
- spec/best_boy/eventable_spec.rb
|
150
164
|
- spec/spec_helper.rb
|
151
165
|
has_rdoc: true
|
152
|
-
homepage: https://github.com/
|
166
|
+
homepage: https://github.com/absolventa/best_boy
|
153
167
|
licenses:
|
154
168
|
- - MIT
|
155
169
|
post_install_message:
|