wagn 1.14.1 → 1.14.2
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.
- checksums.yaml +4 -4
- data/.tm_properties +2 -1
- data/VERSION +1 -1
- data/app/controllers/card_controller.rb +4 -3
- data/db/bootstrap/card_acts.yml +1 -1
- data/db/bootstrap/cards.yml +1028 -1028
- data/db/migrate_core_cards/20140629222005_add_email_cards.rb +2 -25
- data/db/migrate_core_cards/20141204061304_watchers_to_following.rb +38 -0
- data/db/version_core_cards.txt +1 -1
- data/features/history.feature +21 -0
- data/features/step_definitions/history_steps.rb +3 -0
- data/features/step_definitions/wagn_steps.rb +10 -1
- data/lib/card/act.rb +2 -2
- data/lib/card/action.rb +9 -9
- data/lib/card/diff.rb +370 -211
- data/lib/card/exceptions.rb +2 -0
- data/lib/card/format.rb +5 -3
- data/lib/card/query.rb +4 -4
- data/lib/card/query/card_spec.rb +69 -51
- data/lib/card/set.rb +3 -2
- data/lib/wagn.rb +15 -3
- data/lib/wagn/all.rb +1 -3
- data/lib/wagn/application.rb +10 -1
- data/lib/wagn/generators/wagn/templates/Gemfile +6 -1
- data/lib/wagn/log.rb +69 -0
- data/lib/wagn/tasks/wagn.rake +1 -1
- data/mod/01_core/set/all/collection.rb +8 -5
- data/mod/01_core/set/all/content.rb +1 -1
- data/mod/01_core/set/all/fetch.rb +34 -32
- data/mod/01_core/set/all/notify.rb +2 -2
- data/mod/01_core/set/all/phases.rb +5 -0
- data/mod/01_core/set/all/trash.rb +1 -1
- data/mod/02_basic_types/set/type/pointer.rb +4 -0
- data/mod/03_machines/set/type/coffee_script.rb +10 -0
- data/mod/03_machines/set/type/css.rb +9 -0
- data/mod/03_machines/set/type/java_script.rb +5 -0
- data/mod/03_machines/set/type/scss.rb +8 -2
- data/mod/05_standard/set/all/history.rb +10 -1
- data/mod/05_standard/set/type/html.rb +4 -0
- data/mod/05_standard/spec/set/all/base_spec.rb +2 -0
- data/mod/05_standard/spec/set/all/history_spec.rb +12 -0
- data/mod/06_email/set/all/email_html.rb +0 -4
- data/mod/06_email/set/type/email_template.rb +6 -2
- data/spec/lib/card/diff_spec.rb +207 -107
- data/spec/lib/card/query_spec.rb +14 -13
- data/test/fixtures/card_actions.yml +21 -0
- data/test/fixtures/card_acts.yml +103 -85
- data/test/fixtures/card_changes.yml +53 -23
- data/test/fixtures/cards.yml +1349 -1331
- data/test/seed.rb +5 -1
- metadata +8 -3
- data/lib/wagn/config/initializers/airbrake.rb +0 -9
data/lib/card/exceptions.rb
CHANGED
data/lib/card/format.rb
CHANGED
@@ -183,7 +183,9 @@ class Card
|
|
183
183
|
@current_view = view = ok_view canonicalize_view( view ), args
|
184
184
|
args = default_render_args view, args
|
185
185
|
with_inclusion_mode view do
|
186
|
-
|
186
|
+
Wagn.with_logging card.name, :view, view, args do
|
187
|
+
send "_view_#{ view }", args
|
188
|
+
end
|
187
189
|
end
|
188
190
|
end
|
189
191
|
rescue => e
|
@@ -244,9 +246,9 @@ class Card
|
|
244
246
|
if Rails.env =~ /^cucumber|test$/
|
245
247
|
raise e
|
246
248
|
else
|
247
|
-
controller.send :notify_airbrake, e if Airbrake.configuration.api_key
|
248
249
|
Rails.logger.info "\nError rendering #{error_cardname} / #{view}: #{e.class} : #{e.message}"
|
249
|
-
|
250
|
+
Card::Error.current = e
|
251
|
+
card.notable_exception_raised
|
250
252
|
rendering_error e, view
|
251
253
|
end
|
252
254
|
end
|
data/lib/card/query.rb
CHANGED
@@ -27,6 +27,7 @@ class Card::Query
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def run
|
30
|
+
# puts "~~~~~~~~~~~~~~\nCARD SPEC =\n#{@card_spec.rawspec}\n\n-----\n\nSQL=\n#{sql}"
|
30
31
|
rows = ActiveRecord::Base.connection.select_all( sql )
|
31
32
|
retrn = query[:return].present? ? query[:return].to_s : 'card'
|
32
33
|
case retrn
|
@@ -66,10 +67,9 @@ class Card::Query
|
|
66
67
|
end
|
67
68
|
|
68
69
|
def to_s
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
)"
|
70
|
+
select = fields.reject(&:blank?) * ', '
|
71
|
+
where = conditions.reject(&:blank?) * ' and '
|
72
|
+
['(SELECT', select, 'FROM', tables, joins, 'WHERE', where, group, order, limit, offset, ')'].compact * ' '
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
data/lib/card/query/card_spec.rb
CHANGED
@@ -17,7 +17,7 @@ class Card
|
|
17
17
|
CONJUNCTIONS = { :any=>:or, :in=>:or, :or=>:or, :all=>:and, :and=>:and }
|
18
18
|
|
19
19
|
attr_reader :sql, :query, :rawspec, :selfname
|
20
|
-
attr_accessor :joins
|
20
|
+
attr_accessor :joins, :join_count
|
21
21
|
|
22
22
|
class << self
|
23
23
|
def build query
|
@@ -185,7 +185,7 @@ class Card
|
|
185
185
|
#~~~~~~ RELATIONAL
|
186
186
|
|
187
187
|
def type val
|
188
|
-
|
188
|
+
restrict :type_id, val
|
189
189
|
end
|
190
190
|
|
191
191
|
def part val
|
@@ -193,12 +193,13 @@ class Card
|
|
193
193
|
subcondition :left=>val, :right=>right, :conj=>:or
|
194
194
|
end
|
195
195
|
|
196
|
+
|
196
197
|
def left val
|
197
|
-
|
198
|
+
restrict :left_id, val
|
198
199
|
end
|
199
200
|
|
200
201
|
def right val
|
201
|
-
|
202
|
+
restrict :right_id, val
|
202
203
|
end
|
203
204
|
|
204
205
|
def editor_of val
|
@@ -210,19 +211,19 @@ class Card
|
|
210
211
|
end
|
211
212
|
|
212
213
|
def last_editor_of val
|
213
|
-
|
214
|
+
restrict_by_join :id, val, :return=>'updater_id'
|
214
215
|
end
|
215
216
|
|
216
217
|
def last_edited_by val
|
217
|
-
|
218
|
+
restrict :updater_id, val
|
218
219
|
end
|
219
220
|
|
220
221
|
def creator_of val
|
221
|
-
|
222
|
+
restrict_by_join :id, val, :return=>'creator_id'
|
222
223
|
end
|
223
224
|
|
224
225
|
def created_by val
|
225
|
-
|
226
|
+
restrict :creator_id, val
|
226
227
|
end
|
227
228
|
|
228
229
|
def member_of val
|
@@ -236,18 +237,21 @@ class Card
|
|
236
237
|
|
237
238
|
#~~~~~~ PLUS RELATIONAL
|
238
239
|
|
239
|
-
def left_plus
|
240
|
-
|
241
|
-
merge( field(:id) => subspec(junc_spec, :return=>'right_id', :left =>part_spec))
|
240
|
+
def left_plus val
|
241
|
+
junction :left, val
|
242
242
|
end
|
243
243
|
|
244
|
-
def right_plus
|
245
|
-
|
246
|
-
merge( field(:id) => subspec(junc_spec, :return=>'left_id', :right=> part_spec ))
|
244
|
+
def right_plus val
|
245
|
+
junction :right, val
|
247
246
|
end
|
248
247
|
|
249
|
-
def plus
|
250
|
-
|
248
|
+
def plus val
|
249
|
+
any( { :left_plus=>val, :right_plus=>val.deep_clone } )
|
250
|
+
end
|
251
|
+
|
252
|
+
def junction side, val
|
253
|
+
part_spec, junction_spec = val.is_a?(Array) ? val : [ val, {} ]
|
254
|
+
restrict_by_join :id, junction_spec, side=>part_spec, :return=>"#{ side==:left ? :right : :left}_id"
|
251
255
|
end
|
252
256
|
|
253
257
|
|
@@ -280,23 +284,23 @@ class Card
|
|
280
284
|
unless c && [SearchTypeID,SetID].include?(c.type_id)
|
281
285
|
raise BadQuery, %{"found_by" value needs to be valid Search, but #{c.name} is a #{c.type_name}}
|
282
286
|
end
|
283
|
-
|
284
|
-
merge(field(:id) => subspec(found_by_spec))
|
287
|
+
restrict_by_join :id, CardSpec.new(c.get_spec).rawspec
|
285
288
|
end
|
286
289
|
end
|
287
290
|
|
288
291
|
def not val
|
289
|
-
|
292
|
+
subselect = CardSpec.build(:return=>:id, :_parent=>self).merge(val).to_sql
|
293
|
+
join_alias = add_join :not, subselect, :id, :id, :side=>'LEFT'
|
294
|
+
merge field(:cond) => SqlCond.new("#{join_alias}.id is null")
|
290
295
|
end
|
291
296
|
|
292
297
|
def sort val
|
293
298
|
return nil if @parent
|
294
299
|
val[:return] = val[:return] ? safe_sql(val[:return]) : 'db_content'
|
295
|
-
@mods[:sort] = "t_sort.#{val[:return]}"
|
296
300
|
item = val.delete(:item) || 'left'
|
297
301
|
|
298
302
|
if val[:return] == 'count'
|
299
|
-
cs_args = { :return=>'count', :group=>'sort_join_field' }
|
303
|
+
cs_args = { :return=>'count', :group=>'sort_join_field', :_parent=>self }
|
300
304
|
@mods[:sort] = "coalesce(#{@mods[:sort]},0)"
|
301
305
|
case item
|
302
306
|
when 'referred_to'
|
@@ -316,7 +320,9 @@ class Card
|
|
316
320
|
end
|
317
321
|
|
318
322
|
cs.sql.fields << "#{cs.table_alias}.#{join_field} as sort_join_field"
|
319
|
-
add_join :sort, cs.to_sql, :id, :sort_join_field, :side=>'LEFT'
|
323
|
+
join_table = add_join :sort, cs.to_sql, :id, :sort_join_field, :side=>'LEFT'
|
324
|
+
@mods[:sort] = "#{join_table}.#{val[:return]}"
|
325
|
+
|
320
326
|
end
|
321
327
|
|
322
328
|
def match(val)
|
@@ -345,8 +351,9 @@ class Card
|
|
345
351
|
end
|
346
352
|
|
347
353
|
def extension_type val
|
348
|
-
# DEPRECATED!!!
|
349
|
-
|
354
|
+
# DEPRECATED LONG AGO!!!
|
355
|
+
Rails.logger.info "using DEPRECATED extension_type in WQL"
|
356
|
+
merge field(:right_plus) => AccountID
|
350
357
|
end
|
351
358
|
|
352
359
|
|
@@ -367,8 +374,16 @@ class Card
|
|
367
374
|
end
|
368
375
|
|
369
376
|
def add_join(name, table, cardfield, otherfield, opts={})
|
370
|
-
|
371
|
-
|
377
|
+
root.join_count = root.join_count.to_i + 1
|
378
|
+
join_alias = "#{name}_#{root.join_count}"
|
379
|
+
on = "#{table_alias}.#{cardfield} = #{join_alias}.#{otherfield}"
|
380
|
+
is_subselect = !table.is_a?( Symbol )
|
381
|
+
|
382
|
+
if @mods[:conj] == 'or' and is_subselect
|
383
|
+
opts[:side] ||= 'LEFT'
|
384
|
+
merge field(:cond) => SqlCond.new(on)
|
385
|
+
end
|
386
|
+
@joins[join_alias] = ["\n ", opts[:side], 'JOIN', table, 'AS', join_alias, 'ON', on, "\n"].compact.join ' '
|
372
387
|
join_alias
|
373
388
|
end
|
374
389
|
|
@@ -376,11 +391,11 @@ class Card
|
|
376
391
|
@fields ||= {}
|
377
392
|
@fields[name] ||= 0
|
378
393
|
@fields[name] += 1
|
379
|
-
"#{ name }
|
394
|
+
"#{ name }_#{ @fields[name] }"
|
380
395
|
end
|
381
396
|
|
382
397
|
def field_root key
|
383
|
-
key.to_s.gsub
|
398
|
+
key.to_s.gsub /\_\d+/, ''
|
384
399
|
end
|
385
400
|
|
386
401
|
def subcondition(val, args={})
|
@@ -388,34 +403,34 @@ class Card
|
|
388
403
|
cardspec = CardSpec.build( args )
|
389
404
|
merge field(:cond) => cardspec.merge(val)
|
390
405
|
self.joins.merge! cardspec.joins
|
391
|
-
end
|
392
|
-
|
393
|
-
# def revision_spec(field, linkfield, val)
|
394
|
-
# card_select = CardSpec.build(:_parent=>self, :return=>'id').merge(val).to_sql
|
395
|
-
# add_join :ed, "(select distinct #{field} from card_revisions where #{linkfield} in #{card_select})", :id, field
|
396
|
-
# end
|
397
|
-
|
406
|
+
end
|
398
407
|
|
399
408
|
def action_spec(field, linkfield, val)
|
400
409
|
card_select = CardSpec.build(:_parent=>self, :return=>'id').merge(val).to_sql
|
401
410
|
sql = "(SELECT DISTINCT #{field} AS join_card_id FROM card_acts INNER JOIN card_actions ON card_acts.id = card_act_id "
|
402
|
-
sql += "
|
411
|
+
sql += " JOIN (#{card_select}) AS ss ON #{linkfield}=ss.id AND (draft is false OR draft is null))"
|
403
412
|
add_join :ac, sql, :id, :join_card_id
|
404
413
|
end
|
405
414
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
415
|
+
def id_from_spec spec
|
416
|
+
case spec
|
417
|
+
when Integer ; spec
|
418
|
+
when String ; Card.fetch_id(spec)
|
419
|
+
end
|
411
420
|
end
|
412
|
-
|
413
|
-
def
|
414
|
-
id =
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
421
|
+
|
422
|
+
def restrict id_field, val, opts={}
|
423
|
+
if id = id_from_spec(val)
|
424
|
+
merge field(id_field) => id
|
425
|
+
else
|
426
|
+
restrict_by_join id_field, val, opts
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def restrict_by_join id_field, val, opts={}
|
431
|
+
opts.reverse_merge!(:return=>:id, :_parent=>self)
|
432
|
+
subselect = CardSpec.build(opts).merge(val).to_sql
|
433
|
+
add_join "card_#{id_field}", subselect, id_field, opts[:return]
|
419
434
|
end
|
420
435
|
|
421
436
|
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
@@ -425,8 +440,11 @@ class Card
|
|
425
440
|
|
426
441
|
def to_sql *args
|
427
442
|
sql.conditions << basic_conditions
|
428
|
-
|
429
|
-
|
443
|
+
|
444
|
+
if @mods[:return]=='condition'
|
445
|
+
conds = sql.conditions.last
|
446
|
+
return conds.blank? ? nil : "(#{conds})"
|
447
|
+
end
|
430
448
|
|
431
449
|
if pconds = permission_conditions
|
432
450
|
sql.conditions << pconds
|
@@ -451,7 +469,7 @@ class Card
|
|
451
469
|
end
|
452
470
|
|
453
471
|
def basic_conditions
|
454
|
-
@spec.map { |key, val| val.to_sql field_root(key) }.join " #{ current_conjunction } "
|
472
|
+
@spec.map { |key, val| val.to_sql field_root(key) }.compact.join " #{ current_conjunction } "
|
455
473
|
end
|
456
474
|
|
457
475
|
def current_conjunction
|
data/lib/card/set.rb
CHANGED
data/lib/wagn.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
# should be able to move these to more appropriate places
|
2
|
-
|
3
2
|
WAGN_GEM_ROOT = File.expand_path('../..', __FILE__)
|
4
3
|
|
5
4
|
module Wagn
|
6
5
|
|
7
|
-
class << self
|
6
|
+
class << self
|
8
7
|
def root
|
9
8
|
Rails.root
|
10
9
|
end
|
@@ -25,9 +24,22 @@ module Wagn
|
|
25
24
|
WAGN_GEM_ROOT
|
26
25
|
end
|
27
26
|
|
27
|
+
def with_logging cardname, method, message, details, &block
|
28
|
+
if Wagn.config.performance_logger and
|
29
|
+
Wagn.config.performance_logger[:methods] and
|
30
|
+
Wagn.config.performance_logger[:methods].include? method
|
31
|
+
Wagn::Log.start_block :cardname=>cardname, :method=>method, :message=>message, :details=>details
|
32
|
+
result = block.call
|
33
|
+
Wagn::Log.finish_block
|
34
|
+
result
|
35
|
+
else
|
36
|
+
block.call
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
28
40
|
def future_stamp
|
29
41
|
## used in test data
|
30
42
|
@@future_stamp ||= Time.local 2020,1,1,0,0,0
|
31
43
|
end
|
32
44
|
end
|
33
|
-
end
|
45
|
+
end
|
data/lib/wagn/all.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
require 'rails/all'
|
2
2
|
|
3
|
+
require 'builder'
|
3
4
|
require 'htmlentities'
|
4
5
|
require 'recaptcha'
|
5
|
-
require 'airbrake'
|
6
6
|
require 'RMagick'
|
7
7
|
require 'paperclip'
|
8
8
|
require 'coderay'
|
9
9
|
require 'haml'
|
10
10
|
require 'kaminari'
|
11
11
|
require 'diff/lcs'
|
12
|
-
require 'diffy'
|
13
|
-
#require 'scheduler_daemon'
|
14
12
|
|
15
13
|
require 'wagn/application'
|
16
14
|
|
data/lib/wagn/application.rb
CHANGED
@@ -9,6 +9,14 @@ if defined?(Bundler)
|
|
9
9
|
# Bundler.require(:default, :assets, Rails.env)
|
10
10
|
end
|
11
11
|
|
12
|
+
module ActiveSupport::BufferedLogger::Severity
|
13
|
+
WAGN = UNKNOWN + 1
|
14
|
+
|
15
|
+
def wagn progname, &block
|
16
|
+
add(WAGN, nil, progname, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
12
20
|
|
13
21
|
module Wagn
|
14
22
|
class Application < Rails::Application
|
@@ -28,7 +36,7 @@ module Wagn
|
|
28
36
|
end
|
29
37
|
|
30
38
|
initializer :load_mod_initializers, :after => :load_wagn_config_initializers do
|
31
|
-
paths.add 'mod-initializers', :with=>'mod', :glob=>"
|
39
|
+
paths.add 'mod-initializers', :with=>'mod', :glob=>"**{,/*/**}/initializers/*.rb"
|
32
40
|
config.paths['mod-initializers'].existent.sort.each do |initializer|
|
33
41
|
load(initializer)
|
34
42
|
end
|
@@ -76,6 +84,7 @@ module Wagn
|
|
76
84
|
config.token_expiry = 2.days
|
77
85
|
config.revisions_per_page = 10
|
78
86
|
config.request_logger = false
|
87
|
+
config.performance_logger = false
|
79
88
|
|
80
89
|
config
|
81
90
|
end
|
@@ -65,7 +65,7 @@ group :test do
|
|
65
65
|
|
66
66
|
# CUKES see features dir
|
67
67
|
gem 'cucumber-rails', '~> 1.3', :require=>false # feature-driven-development suite
|
68
|
-
gem 'capybara', '~> 2.
|
68
|
+
gem 'capybara', '~> 2.4.4'
|
69
69
|
gem 'selenium-webdriver', '~> 2.39'
|
70
70
|
# gem 'capybara-webkit'
|
71
71
|
gem 'launchy' # lets cucumber launch browser windows
|
@@ -97,3 +97,8 @@ group :debug do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
<% end %>
|
100
|
+
|
101
|
+
Dir.glob(File.join(File.dirname(__FILE__), '*','**{,/*/**}','Gemfile')).each do |gemfile|
|
102
|
+
instance_eval(File.read(gemfile))
|
103
|
+
end
|
104
|
+
|
data/lib/wagn/log.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
class Wagn::Log
|
3
|
+
TAB_SIZE = 2
|
4
|
+
@@log = []
|
5
|
+
@@last_toplevel_card = nil
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# args:
|
10
|
+
# :method => :view|:event|:fetch|:search
|
11
|
+
# :cardname, :message, :details
|
12
|
+
def start_block args
|
13
|
+
level = @@log.last ? @@log.last[:level] + 1 : 1
|
14
|
+
@@log << args.merge( :start => Time.now, :level=>level, :subtree =>[] )
|
15
|
+
end
|
16
|
+
|
17
|
+
def finish_block
|
18
|
+
log = @@log.pop
|
19
|
+
duration = (Time.now - log[:start]) * 1000
|
20
|
+
return if limit = Wagn.config.performance_logger[:limit] and limit > 0 and duration < limit
|
21
|
+
|
22
|
+
log_msg = "#{ indent log[:level] }(%d.2ms) #{ log[:method] }: #{ log[:message] }" % duration
|
23
|
+
log_msg += details log if Wagn.config.performance_logger[:details]
|
24
|
+
log_msg += subtree log
|
25
|
+
|
26
|
+
if log_parent = @@log.last
|
27
|
+
if sibling = log_parent[:subtree].last and ( sibling[:card] == log[:cardname] or not log[:cardname] )
|
28
|
+
sibling[:lines] << log_msg
|
29
|
+
else
|
30
|
+
log_parent[:subtree] << {:card=>log[:cardname], :lines=>[log_msg]}
|
31
|
+
end
|
32
|
+
else
|
33
|
+
if log[:cardname] and @@last_toplevel_card != log[:cardname]
|
34
|
+
@@last_toplevel_card = log[:cardname]
|
35
|
+
Rails.logger.wagn log[:cardname]
|
36
|
+
end
|
37
|
+
Rails.logger.wagn log_msg
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def indent level, args={}
|
43
|
+
res = (' '*TAB_SIZE + '|') * level
|
44
|
+
res += args[:no_link] ? ' ' : '--'
|
45
|
+
end
|
46
|
+
|
47
|
+
def details log
|
48
|
+
if log[:details]
|
49
|
+
", " + log[:details].to_s.gsub( "\n", "\n#{ indent( log[:level]+1, :no_link=>true) }" )
|
50
|
+
else
|
51
|
+
''
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def subtree log
|
56
|
+
if log[:subtree].present?
|
57
|
+
"\n" + log[:subtree].map do |subentry|
|
58
|
+
msg = subentry[:card] ? "#{ indent(log[:level]) }#{ subentry[:card] }\n" : ''
|
59
|
+
msg += subentry[:lines].join("\n")
|
60
|
+
end.join("\n")
|
61
|
+
else
|
62
|
+
''
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|