card 1.20.2 → 1.20.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +3 -1
  4. data/config/initializers/01_core_extensions/array.rb +1 -1
  5. data/config/initializers/01_core_extensions/module.rb +1 -1
  6. data/config/initializers/02_patches/active_record.rb +66 -0
  7. data/config/initializers/patches.rb +4 -0
  8. data/db/migrate_core_cards/20170314175313_add_notification_event_card.rb +21 -0
  9. data/db/seed/new/card_actions.yml +723 -475
  10. data/db/seed/new/card_acts.yml +45 -45
  11. data/db/seed/new/card_changes.yml +2306 -1675
  12. data/db/seed/new/card_references.yml +389 -116
  13. data/db/seed/new/cards.yml +2537 -2067
  14. data/db/seed/test/fixtures/card_actions.yml +1709 -1445
  15. data/db/seed/test/fixtures/card_acts.yml +302 -290
  16. data/db/seed/test/fixtures/card_changes.yml +5494 -4818
  17. data/db/seed/test/fixtures/card_references.yml +1137 -794
  18. data/db/seed/test/fixtures/cards.yml +3631 -3120
  19. data/db/version_core_cards.txt +1 -1
  20. data/lib/card/auth/current.rb +21 -0
  21. data/lib/card/env.rb +7 -2
  22. data/lib/card/env/success.rb +13 -3
  23. data/lib/card/format/render.rb +13 -4
  24. data/lib/card/migration.rb +4 -6
  25. data/lib/card/mod/loader.rb +8 -0
  26. data/lib/card/model/save_helper.rb +45 -0
  27. data/lib/card/name/view_name.rb +8 -6
  28. data/lib/card/query/join.rb +4 -2
  29. data/lib/card/query/sorting.rb +26 -22
  30. data/lib/card/reference.rb +2 -2
  31. data/lib/card/set/advanced_api.rb +31 -6
  32. data/lib/card/set/event.rb +16 -8
  33. data/lib/card/set/format.rb +15 -0
  34. data/lib/card/set/format/haml_views.rb +78 -0
  35. data/lib/card/set/loader.rb +3 -2
  36. data/lib/cardio.rb +17 -1
  37. data/mod/Modfile +2 -1
  38. data/mod/account/spec/set/all/account_spec.rb +1 -1
  39. data/mod/basic_formats/set/all/all_css.rb +4 -5
  40. data/mod/bootstrap/set/all/bootstrap/navbar.rb +6 -0
  41. data/mod/bootstrap/set/all/bootstrap/tabs.rb +13 -6
  42. data/mod/carrierwave/set/abstract/attachment/upload_cache.rb +6 -0
  43. data/mod/core/set/all/assign_attributes.rb +3 -0
  44. data/mod/core/set/all/fetch.rb +3 -3
  45. data/mod/core/spec/set/all/collection_spec.rb +5 -3
  46. data/mod/history/lib/card/change.rb +2 -2
  47. data/mod/machines/file/all_script_machine_output/file.js +37 -121
  48. data/mod/machines/file/all_style_machine_output/file.css +4 -4
  49. data/mod/machines/lib/javascript/wagn.js.coffee +4 -0
  50. data/mod/machines/lib/javascript/wagn_mod.js.coffee +0 -2
  51. data/mod/machines/set/type/css.rb +6 -0
  52. data/mod/{email → notifications}/format/email_html_format.rb +0 -0
  53. data/mod/{email → notifications}/format/email_text_format.rb +0 -0
  54. data/mod/{email → notifications}/lib/card/follow_option.rb +0 -0
  55. data/mod/{email → notifications}/set/abstract/test_context.rb +0 -0
  56. data/mod/{email → notifications}/set/all/email_html.rb +0 -0
  57. data/mod/{email → notifications}/set/all/email_text.rb +0 -0
  58. data/mod/{email → notifications}/set/all/follow.rb +0 -0
  59. data/mod/notifications/set/all/observer.rb +22 -0
  60. data/mod/{email/set/all/notify.rb → notifications/set/all/send_notifications.rb} +0 -0
  61. data/mod/notifications/set/all/show_notifications.rb +7 -0
  62. data/mod/{email → notifications}/set/right/bcc.rb +0 -0
  63. data/mod/{email → notifications}/set/right/cc.rb +0 -0
  64. data/mod/{email → notifications}/set/right/follow.rb +0 -0
  65. data/mod/{email → notifications}/set/right/follow_fields.rb +0 -0
  66. data/mod/{email → notifications}/set/right/followers.rb +0 -0
  67. data/mod/{email → notifications}/set/right/following.rb +0 -0
  68. data/mod/{email → notifications}/set/right/from.rb +0 -0
  69. data/mod/{email → notifications}/set/right/html_message.rb +0 -0
  70. data/mod/{email → notifications}/set/right/subject.rb +0 -0
  71. data/mod/{email → notifications}/set/right/text_message.rb +0 -0
  72. data/mod/{email → notifications}/set/right/to.rb +0 -0
  73. data/mod/{email → notifications}/set/self/always.rb +0 -0
  74. data/mod/{email → notifications}/set/self/created.rb +0 -0
  75. data/mod/{email → notifications}/set/self/edited.rb +0 -0
  76. data/mod/{email → notifications}/set/self/follow.rb +0 -0
  77. data/mod/{email → notifications}/set/self/follow_defaults.rb +0 -0
  78. data/mod/{email → notifications}/set/self/never.rb +0 -0
  79. data/mod/{email → notifications}/set/type/email_template.rb +0 -0
  80. data/mod/{email → notifications}/set/type/email_template/email_config.rb +0 -0
  81. data/mod/notifications/set/type/notification_template.rb +23 -0
  82. data/mod/{email → notifications}/set/type_plus_right/user/follow.rb +0 -0
  83. data/mod/{email → notifications}/spec/set/all/follow_spec.rb +14 -5
  84. data/mod/{email → notifications}/spec/set/all/notify_spec.rb +1 -1
  85. data/mod/{email → notifications}/spec/set/all/observer_spec.rb +1 -1
  86. data/mod/{email → notifications}/spec/set/right/followers_spec.rb +0 -0
  87. data/mod/{email → notifications}/spec/set/right/following_spec.rb +0 -0
  88. data/mod/{email → notifications}/spec/set/self/follow_defaults_spec.rb +0 -0
  89. data/mod/notifications/spec/set/type/notification_template_spec.rb +58 -0
  90. data/mod/{standard/set/abstract/search/paging.rb → pointer/set/abstract/00_paging.rb} +10 -1
  91. data/mod/{standard/set/abstract/search/paging → pointer/set/abstract/00_paging}/paging_links.rb +0 -0
  92. data/mod/pointer/set/abstract/01_pointer.rb +13 -1
  93. data/mod/pointer/spec/set/type/pointer_spec.rb +7 -0
  94. data/mod/standard/set/abstract/01_search_params.rb +4 -0
  95. data/mod/standard/set/abstract/search.rb +1 -0
  96. data/mod/standard/set/abstract/wql_search.rb +6 -4
  97. data/mod/standard/set/all/rich_html/toolbar.rb +31 -16
  98. data/mod/standard/set/all/rich_html/wrapper.rb +3 -1
  99. data/mod/standard/set/self/search.rb +28 -8
  100. data/mod/standard/set/type/search_type.rb +10 -8
  101. data/mod/standard/spec/set/all/rich_html/editing_spec.rb +2 -1
  102. data/mod/standard/spec/set/all/rich_html/form_spec.rb +2 -2
  103. data/mod/standard/spec/set/self/search_spec.rb +8 -1
  104. data/mod/standard/spec/set/type/phrase_spec.rb +2 -1
  105. data/mod/twitter/Gemfile +3 -0
  106. data/mod/twitter/db/migrate_cards/20170305112346_add_twitter_cards.rb +30 -0
  107. data/mod/twitter/set/type/twitter_template.rb +22 -0
  108. data/spec/lib/card/query/sorting_spec.rb +68 -0
  109. data/spec/lib/card/query_spec.rb +0 -65
  110. metadata +78 -40
  111. data/mod/email/set/all/observer.rb +0 -26
  112. data/mod/standard/spec/set/all/email_html_spec.rb +0 -15
@@ -1 +1 @@
1
- 20170209132834
1
+ 20170314175313
@@ -49,6 +49,27 @@ class Card
49
49
  end
50
50
  end
51
51
 
52
+ def serialize
53
+ { as_id: as_id, current_id: current_id }
54
+ end
55
+
56
+ # @param auth_data [Integer|Hash] user id or a hash
57
+ # @opts auth_data [Integer] current_id
58
+ # @opts auth_data [Integer] as_id
59
+ def with auth_data
60
+ auth_data = { current_id: auth_data } if auth_data.is_a?(Integer)
61
+ raise ArgumentError unless auth_data.is_a? Hash
62
+
63
+ tmp_current = current_id
64
+ tmp_as_id = as_id
65
+ @current_id = auth_data[:current_id]
66
+ @as_id = auth_data[:as_id] if auth_data[:as_id]
67
+ yield
68
+ ensure
69
+ @current_id = tmp_current
70
+ @as_id = tmp_as_id
71
+ end
72
+
52
73
  # get session object from Env
53
74
  # return [Session]
54
75
  def session
@@ -64,9 +64,14 @@ class Card
64
64
  @env.select { |k, _v| SERIALIZABLE_ATTRIBUTES.include?(k) }
65
65
  end
66
66
 
67
- def deserialize! data
67
+ # @param serialized_env [Hash]
68
+ def with serialized_env
69
+ tmp_env = serialize if @env
68
70
  @env ||= {}
69
- @env.update data
71
+ @env.update serialized_env
72
+ yield
73
+ ensure
74
+ @env.update tmp_env if tmp_env
70
75
  end
71
76
 
72
77
  private
@@ -43,7 +43,9 @@ class Card
43
43
  end
44
44
 
45
45
  def id= id
46
- self.mark = id # for backwards compatibility use mark here: id was often used for the card name
46
+ # for backwards compatibility use mark here.
47
+ # id was often used for the card name
48
+ self.mark = id
47
49
  end
48
50
 
49
51
  def type= type
@@ -63,7 +65,7 @@ class Card
63
65
  case value
64
66
  when "" then ""
65
67
  when "*previous", :previous then :previous
66
- when /^(http|\/)/ then value
68
+ when %r{^(http|/)} then value
67
69
  when /^TEXT:\s*(.+)/ then Regexp.last_match(1)
68
70
  when /^REDIRECT:\s*(.+)/
69
71
  @redirect = true
@@ -89,7 +91,9 @@ class Card
89
91
  end
90
92
 
91
93
  def target name_context=@name_context
92
- card(name_context) || (@target == :previous ? Card::Env.previous_location : @target) || Card.fetch(name_context)
94
+ card(name_context) ||
95
+ (@target == :previous ? Card::Env.previous_location : @target) ||
96
+ Card.fetch(name_context)
93
97
  end
94
98
 
95
99
  def []= key, value
@@ -112,6 +116,12 @@ class Card
112
116
  end
113
117
  end
114
118
 
119
+ def flash message=nil
120
+ @params[:flash] ||= []
121
+ @params[:flash] << message if message
122
+ @params[:flash]
123
+ end
124
+
115
125
  def params
116
126
  @params.marshal_dump
117
127
  end
@@ -113,10 +113,19 @@ class Card
113
113
  end
114
114
 
115
115
  def view_method view
116
- method "_view_#{view}"
117
- rescue
118
- voo.unsupported_view = view
119
- method "_view_unsupported_view"
116
+ unless supports_view? view
117
+ voo.unsupported_view = view
118
+ view = :unsupported_view
119
+ end
120
+ method view_method_name(view)
121
+ end
122
+
123
+ def supports_view? view
124
+ respond_to? view_method_name(view)
125
+ end
126
+
127
+ def view_method_name view
128
+ "_view_#{view}"
120
129
  end
121
130
 
122
131
  def current_view view
@@ -62,12 +62,10 @@ class Card::Migration < ActiveRecord::Migration
62
62
  Card::Cache.reset_all
63
63
  Cardio.schema_mode "" do
64
64
  Card::Auth.as_bot do
65
- ActiveRecord::Base.transaction do
66
- begin
67
- yield
68
- ensure
69
- Card::Cache.reset_all
70
- end
65
+ begin
66
+ yield
67
+ ensure
68
+ Card::Cache.reset_all
71
69
  end
72
70
  end
73
71
  end
@@ -18,6 +18,7 @@ class Card
18
18
  module Loader
19
19
  class << self
20
20
  def load_mods
21
+ load_initializers
21
22
  load_set_patterns
22
23
  load_formats
23
24
  load_sets
@@ -89,6 +90,13 @@ class Card
89
90
  files.flatten
90
91
  end
91
92
 
93
+ def load_initializers
94
+ Card.config.paths["mod/config/initializers"].existent
95
+ .sort.each do |initializer|
96
+ load initializer
97
+ end
98
+ end
99
+
92
100
  def load_set_patterns
93
101
  generate_set_pattern_tmp_files if rewrite_tmp_files?
94
102
  load_dir Card.paths["tmp/set_pattern"].first
@@ -9,6 +9,14 @@ class Card
9
9
  # All !-methods in this module rename existing cards
10
10
  # to resolve name conflicts)
11
11
  module SaveHelper
12
+ def as_user user_name
13
+ current = Card::Auth.current_id
14
+ Card::Auth.current_id = Card.fetch_id user_name
15
+ result = yield
16
+ Card::Auth.current_id = current
17
+ result
18
+ end
19
+
12
20
  def create_card name_or_args, content_or_args=nil
13
21
  args = standardize_args name_or_args, content_or_args
14
22
  resolve_name_conflict args
@@ -75,6 +83,43 @@ class Card
75
83
  end
76
84
  end
77
85
 
86
+
87
+ # Creates or updates a trait card with codename and right rules.
88
+ # Content for rules that are pointer cards by default
89
+ # is converted to pointer format.
90
+ # @example
91
+ # ensure_trait "*a_or_b", :a_or_b,
92
+ # default: { type_id: Card::PointerID },
93
+ # options: ["A", "B"],
94
+ # input: "radio"
95
+ def ensure_trait name, codename, args={}
96
+ ensure_card name, codename: codename
97
+ args.each do |setting, value|
98
+ ensure_trait_rule name, setting, value
99
+ end
100
+ end
101
+
102
+ def ensure_trait_rule trait, setting, value
103
+ validate_setting setting
104
+ card_args = normalize_trait_rule_args setting, value
105
+ ensure_card [trait, :right, setting], card_args
106
+ end
107
+
108
+ def validate_setting setting
109
+ unless Card::Codename[setting] &&
110
+ Card.fetch_type_id(setting) == SettingID
111
+ raise ArgumentError, "not a valid setting: #{setting}"
112
+ end
113
+ end
114
+
115
+ def normalize_trait_rule_args setting, value
116
+ return value if value.is_a? Hash
117
+ if Card.fetch_type_id([setting, :right, :default]) == PointerID
118
+ value = Array(value).to_pointer_content
119
+ end
120
+ { content: value }
121
+ end
122
+
78
123
  # if card with same name exists move it out of the way
79
124
  def create_card! name_or_args, content_or_args=nil
80
125
  args = standardize_args name_or_args, content_or_args
@@ -12,7 +12,7 @@ class Card
12
12
  def new obj
13
13
  return obj if self.class === obj
14
14
  str = Array === obj ? obj * joint : obj.to_s
15
- if known_name = @@name2viewnameobject[str]
15
+ if (known_name = @@name2viewnameobject[str])
16
16
  known_name
17
17
  else
18
18
  super str.strip
@@ -23,13 +23,14 @@ class Card
23
23
  def initialize str
24
24
  @s = str.to_s.strip
25
25
  @s = @s.encode("UTF-8") if RUBYENCODING
26
- @key = if @s.index(self.class.joint)
27
- @parts = @s.split(/\s*#{JOINT_RE}\s*/)
26
+ @key =
27
+ if @s.index(self.class.joint)
28
+ @parts = @s.split(/\s*#{JOINT_RE}\s*/)
28
29
  @parts << "" if @s[-1, 1] == self.class.joint
29
30
  @simple = false
30
31
  @parts.map { |p| p.to_name.key } * self.class.joint
31
- else
32
- @parts = [str]
32
+ else
33
+ @parts = [str]
33
34
  @simple = true
34
35
  str.empty? ? "" : simple_key
35
36
  end
@@ -37,7 +38,8 @@ class Card
37
38
  end
38
39
 
39
40
  def simple_key
40
- decoded.underscore.gsub(/[^#{OK4KEY_RE}]+/, "_").split(/_+/).reject(&:empty?) * "_"
41
+ decoded.underscore.gsub(/[^#{OK4KEY_RE}]+/, "_")
42
+ .split(/_+/).reject(&:empty?) * "_"
41
43
  end
42
44
 
43
45
  def to_viewname
@@ -8,6 +8,7 @@ class Card
8
8
  :from_field, :to_field,
9
9
  :superjoin, :subjoins
10
10
 
11
+ # documentation??? -pk
11
12
  def initialize opts={}
12
13
  from_and_to opts
13
14
  opts.each do |key, value|
@@ -15,8 +16,9 @@ class Card
15
16
  end
16
17
  @from_field ||= :id
17
18
  @to_field ||= :id
18
- @conditions = []
19
- @subjoins = []
19
+
20
+ @conditions = Array @conditions
21
+ @subjoins = Array @subjoins
20
22
  if @from.is_a? Join
21
23
  @superjoin = @from
22
24
  @superjoin.subjoins << self
@@ -22,30 +22,34 @@ class Card
22
22
 
23
23
  # EXPERIMENTAL!
24
24
  def sort_by_count val, item
25
- if item == "referred_to"
26
- @mods[:sort] = "coalesce(count,0)" # needed for postgres
27
- cs = Query.new(
28
- return: "coalesce(count(*), 0) as count",
29
- group: "sort_join_field",
30
- superquery: self
31
- )
32
- subselect = Query.new val.merge(return: "id", superquery: self)
33
- cs.add_condition "referer_id in (#{subselect.sql})"
34
- # FIXME: - SQL generated before SQL phase
35
- cs.joins << Join.new(
36
- from: cs,
37
- to: %w(card_references wr referee_id)
38
- )
39
- cs.mods[:sort_join_field] = "#{cs.table_alias}.id as sort_join_field"
40
- # HACK!
41
-
42
- joins << Join.new(
43
- from: self,
44
- to: [cs, "srtbl", "sort_join_field"]
45
- )
46
- else
25
+ method_name = "sort_by_count_#{item}"
26
+ unless respond_to?(method_name)
47
27
  raise Card::Error::BadQuery, "count with item: #{item} not yet implemented"
48
28
  end
29
+ send method_name, val
30
+ end
31
+
32
+ def sort_by_count_referred_to val
33
+ @mods[:sort] = "coalesce(count,0)" # needed for postgres
34
+ cs = Query.new(
35
+ return: "coalesce(count(*), 0) as count",
36
+ group: "sort_join_field",
37
+ superquery: self
38
+ )
39
+ subselect = Query.new val.merge(return: "id", superquery: self)
40
+ cs.add_condition "referer_id in (#{subselect.sql})"
41
+ # FIXME: - SQL generated before SQL phase
42
+ cs.joins << Join.new(
43
+ from: cs,
44
+ to: %w(card_references wr referee_id)
45
+ )
46
+ cs.mods[:sort_join_field] = "#{cs.table_alias}.id as sort_join_field"
47
+ # HACK!
48
+
49
+ joins << Join.new(
50
+ from: self,
51
+ to: [cs, "srtbl", "sort_join_field"]
52
+ )
49
53
  end
50
54
  end
51
55
  end
@@ -41,10 +41,10 @@ class Card
41
41
  "LEFT JOIN cards ON card_references.referer_id = cards.id"
42
42
  ).where(
43
43
  "cards.id IS NULL"
44
- ).find_in_batches do |group|
44
+ ).pluck_in_batches(:id) do |group_ids|
45
45
  # used to be .delete_all here, but that was failing on large dbs
46
46
  puts "deleting batch of references"
47
- where("id in (#{group.map(&:id).join ','})").delete_all
47
+ where("id in (#{group_ids.join ','})").delete_all
48
48
  end
49
49
  end
50
50
 
@@ -4,14 +4,11 @@ class Card
4
4
  module AdvancedApi
5
5
  def ensure_set &block
6
6
  set_module = yield
7
+ set_module = card_set_module_const_get(set_module) unless set_module.is_a?(Module)
8
+ set_module
7
9
  rescue NameError => e
8
10
  if e.message =~ /uninitialized constant (?:Card::Set::)?(.+)$/
9
- constant_pieces = Regexp.last_match(1).split("::")
10
- constant_pieces.inject(Card::Set) do |set_mod, module_name|
11
- set_mod.const_get_or_set module_name do
12
- Module.new
13
- end
14
- end
11
+ define_set Regexp.last_match(1)
15
12
  end
16
13
  # try again - there might be another submodule that doesn't exist
17
14
  ensure_set(&block)
@@ -40,6 +37,34 @@ class Card
40
37
  end
41
38
  end
42
39
  end
40
+
41
+ private
42
+
43
+ # @param set_name [String] name of the constant to be defined
44
+ def define_set set_name
45
+ constant_pieces = set_name.split("::")
46
+ constant_pieces.inject(Card::Set) do |set_mod, module_name|
47
+ set_mod.const_get_or_set module_name do
48
+ Module.new
49
+ end
50
+ end
51
+ end
52
+
53
+ # "set" is the noun not the verb
54
+ def card_set_module_const_get const
55
+ Card::Set.const_get normalize_const(const)
56
+ end
57
+
58
+ def normalize_const const
59
+ case const
60
+ when Array
61
+ const.map { |piece| piece.to_s.camelcase }.join("::")
62
+ when Symbol
63
+ const.to_s.camelcase
64
+ else
65
+ const
66
+ end
67
+ end
43
68
  end
44
69
  end
45
70
  end
@@ -1,5 +1,5 @@
1
1
  class Card
2
- def deserialize_for_active_job! attr, env, current_id
2
+ def deserialize_for_active_job! attr
3
3
  attr.each do |attname, args|
4
4
  # symbols are not allowed so all symbols arrive here as strings
5
5
  # convert strings that were symbols before back to symbols
@@ -7,15 +7,21 @@ class Card
7
7
  instance_variable_set("@#{attname}", value)
8
8
  end
9
9
  include_set_modules
10
+ end
11
+
12
+ def with_env_and_auth env, auth
10
13
  # If active jobs (and hence the integrate_with_delay events) don't run
11
14
  # in a background process then Card::Env.deserialize! decouples the
12
15
  # controller's params hash and the Card::Env's params hash with the
13
16
  # effect that params changes in the CardController get lost
14
17
  # (a crucial example are success params that are processed in
15
18
  # CardController#update_params_for_success)
16
- return if Wagn.config.active_job.queue_adapter == :inline
17
- Card::Env.deserialize! env
18
- Card::Auth.current_id = current_id
19
+ return yield if Wagn.config.active_job.queue_adapter == :inline
20
+ Card::Auth.with auth do
21
+ Card::Env.with env do
22
+ yield
23
+ end
24
+ end
19
25
  end
20
26
 
21
27
  def serialize_for_active_job
@@ -115,16 +121,18 @@ class Card
115
121
  define_method(method_name, proc do
116
122
  IntegrateWithDelayJob.set(queue: event).perform_later(
117
123
  self, serialize_for_active_job, Card::Env.serialize,
118
- Card::Auth.current_id, final_method_name
124
+ Card::Auth.serialize, final_method_name
119
125
  )
120
126
  end)
121
127
  end
122
128
  end
123
129
 
124
130
  class IntegrateWithDelayJob < ActiveJob::Base
125
- def perform card, card_attribs, env, current_id, method_name
126
- card.deserialize_for_active_job! card_attribs, env, current_id
127
- card.send method_name
131
+ def perform card, card_attribs, env, auth, method_name
132
+ card.deserialize_for_active_job! card_attribs
133
+ card.with_env_and_auth env, auth do
134
+ card.send method_name
135
+ end
128
136
  end
129
137
  end
130
138