best_boy 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
[](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:
|