card 1.18.1 → 1.18.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0e96aef9fe8581d7e787b0ad6ed56db1b3ec7d1
4
- data.tar.gz: bbdd504c7800d1c372bd4199a293eeeb4e0ad501
3
+ metadata.gz: 040ce812a1f8d7900a5c5e742871133e90225ff0
4
+ data.tar.gz: e03884ae6c5850eeec5b6456cdaa202c4f6da9c2
5
5
  SHA512:
6
- metadata.gz: 2bb8bfa7d9df016796744af64b3361c5abbf5fefe1b10d17f4ae08af370e12600e1e1353da8ed00ae07bc281c484a0fbf458fe51d535e06ff0b49fd2987d58a1
7
- data.tar.gz: d0f7b44c9ec0b44118f29a0fab7721402fcdfb397df4396a914243aa5477e18eeefed973fcb1434eb56eb8af6c788104a59178f23fcf10c414b17b1394d4eb38
6
+ metadata.gz: d6de0ea37ead3e1e4de679e46e2d013e9707303550e43d3c44a111c83a857d1483e0ace41ea9c31cbf92f109713391ab5f8f49518353cbd429517aeabb5de277
7
+ data.tar.gz: 0b923c3dd12e2ef9df97c19d5fae2c0a198dddc8b032bc70fea8a82637aba4eacecb0765e177427828976f469847512fe36b7f148b669cb521afce246acc955f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.18.1
1
+ 1.18.2
@@ -20,7 +20,7 @@ class SearchCardContext < Card::CoreMigration
20
20
  end
21
21
  card.update_column :db_content, content
22
22
  card.actions.each do |action|
23
- next unless (content_change = action.change_for(:db_content).first)
23
+ next unless (content_change = action.change :db_content)
24
24
  content = content_change.value
25
25
  replace.each do |key, val|
26
26
  content.gsub!(/(#{sep})_(#{key})(?=#{sep})/, "\\1_#{val}")
@@ -2,11 +2,17 @@
2
2
 
3
3
  class AddRecentSettingSessionCard < Card::CoreMigration
4
4
  def up
5
- Card.create! name: '*recent settings', codename: 'recent_settings', type_code: :pointer, subcards: {
6
- '+*self+*options' => { type_code: :search_type, content: '{"type":"setting"}' },
7
- '+*self+*update' => { content: '[[Anyone]]' },
8
- '+*self**create' => { content: '[[Anyone]]' },
9
- '+*self**read' => { content: '[[Anyone]]' }
10
- }
5
+ Card.create!(
6
+ name: '*recent settings',
7
+ codename: 'recent_settings',
8
+ type_code: :pointer,
9
+ subcards: {
10
+ '+*self+*options' => { type_code: :search_type,
11
+ content: '{"type":"setting"}' },
12
+ '+*self+*update' => { content: '[[Anyone]]' },
13
+ '+*self**create' => { content: '[[Anyone]]' },
14
+ '+*self**read' => { content: '[[Anyone]]' }
15
+ }
16
+ )
11
17
  end
12
18
  end
@@ -26,7 +26,7 @@ class UpdateFileAndImageCards < Card::CoreMigration
26
26
  Card::Cache.reset_all
27
27
  Card.search(type: [:in, 'file', 'image']).each do |card|
28
28
  card.actions.each do |action|
29
- if (content_change = action.change_for(:db_content).first)
29
+ if (content_change = action.change :db_content)
30
30
  original_filename = content_change.value.split("\n").first
31
31
  action.update_attributes! comment: original_filename
32
32
  end
@@ -4,7 +4,7 @@ class UpdateFileHistory < Card::CoreMigration
4
4
  def up
5
5
  Card.search(type: [:in, 'file', 'image']).each do |card|
6
6
  card.actions.each do |action|
7
- next unless (content_change = action.change_for(:db_content).first)
7
+ next unless (content_change = action.change :db_content)
8
8
  original_filename, file_type, action_id, mod = content_change.value.split("\n")
9
9
  next unless file_type.present? && action_id.present?
10
10
  value =
data/lib/card/cache.rb CHANGED
@@ -1,17 +1,6 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  class Card
4
- ActiveSupport::Cache::FileStore.class_eval do
5
- # escape special symbols \*"<>| additionaly to :?.
6
- # All of them not allowed to use in ms windows file system
7
- def real_file_path name
8
- name = name.gsub('%', '%25').gsub('?', '%3F').gsub(':', '%3A')
9
- name = name.gsub('\\', '%5C').gsub('*', '%2A').gsub('"', '%22')
10
- name = name.gsub('<', '%3C').gsub('>', '%3E').gsub('|', '%7C')
11
- '%s/%s.cache' % [@cache_path, name]
12
- end
13
- end
14
-
15
4
  class Cache
16
5
  TEST_ENVS = %w(test cucumber).freeze
17
6
  @@prepopulating = TEST_ENVS.include? Rails.env
@@ -28,22 +17,14 @@ class Card
28
17
  store: cache_type
29
18
  end
30
19
 
20
+ # establish clean context;
21
+ # clear the temporary caches and ensure we're using the latest stamp
22
+ # on the persistent caches.
31
23
  def renew
32
- cache_by_class.keys do |klass|
33
- raise "renewing nil cache: #{klass}" unless klass.cache
34
- cache_by_class[klass].system_prefix = system_prefix(klass)
24
+ cache_by_class.each do |_klass, cache|
25
+ cache.soft.reset
26
+ cache.hard.renew if cache.hard
35
27
  end
36
- reset_soft
37
- end
38
-
39
- def database_name
40
- @database_name ||= (cfg = Cardio.config) &&
41
- (dbcfg = cfg.database_configuration) &&
42
- dbcfg[Rails.env]['database']
43
- end
44
-
45
- def system_prefix klass
46
- "#{database_name}/#{klass}"
47
28
  end
48
29
 
49
30
  def restore
@@ -51,16 +32,18 @@ class Card
51
32
  prepopulate
52
33
  end
53
34
 
54
- def reset_global # deprecated
55
- reset_all
35
+ def reset_global
36
+ cache_by_class.each do |_klass, cache|
37
+ cache.soft.reset
38
+ cache.hard.annihilate if cache.hard
39
+ end
40
+ reset_other
56
41
  end
57
42
 
58
43
  def reset_all
59
44
  reset_hard
60
45
  reset_soft
61
-
62
- Card::Codename.reset_cache
63
- Cardio.delete_tmp_files
46
+ reset_other
64
47
  end
65
48
 
66
49
  def reset_hard
@@ -75,6 +58,11 @@ class Card
75
58
  end
76
59
  end
77
60
 
61
+ def reset_other
62
+ Card::Codename.reset_cache
63
+ Cardio.delete_tmp_files
64
+ end
65
+
78
66
  def obj_to_key obj
79
67
  case obj
80
68
  when Hash
@@ -161,3 +149,14 @@ class Card
161
149
  end
162
150
  end
163
151
  end
152
+
153
+ ActiveSupport::Cache::FileStore.class_eval do
154
+ # escape special symbols \*"<>| additionaly to :?.
155
+ # All of them not allowed to use in ms windows file system
156
+ def real_file_path name
157
+ name = name.gsub('%', '%25').gsub('?', '%3F').gsub(':', '%3A')
158
+ name = name.gsub('\\', '%5C').gsub('*', '%2A').gsub('"', '%22')
159
+ name = name.gsub('<', '%3C').gsub('>', '%3E').gsub('|', '%7C')
160
+ '%s/%s.cache' % [@cache_path, name]
161
+ end
162
+ end
@@ -1,33 +1,68 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  class Card::Cache::Persistent
4
- attr_reader :prefix
4
+ attr_accessor :prefix
5
+
6
+ class << self
7
+ def database_name
8
+ @database_name ||= (cfg = Cardio.config) &&
9
+ (dbcfg = cfg.database_configuration) &&
10
+ dbcfg[Rails.env]['database']
11
+ end
12
+ end
5
13
 
6
14
  def initialize opts
7
15
  @store = opts[:store]
8
- self.system_prefix =
9
- opts[:prefix] || Card::Cache.system_prefix(opts[:class])
16
+ @klass = opts[:class]
17
+ @class_key = @klass.to_s.to_name.key
18
+ @database = opts[:database] || self.class.database_name
10
19
  end
11
20
 
12
- def system_prefix= system_prefix
13
- @system_prefix = system_prefix
14
- @prefix = "#{system_prefix}/"
21
+ def renew
22
+ @stamp = nil
23
+ @prefix = nil
24
+ end
25
+
26
+ def reset
27
+ @stamp = new_stamp
28
+ @prefix = nil
29
+ Cardio.cache.write stamp_key, @stamp
30
+ end
31
+
32
+ def stamp
33
+ @stamp ||= Cardio.cache.fetch stamp_key { new_stamp }
34
+ end
35
+
36
+ def stamp_key
37
+ "#{@database}/#{@class_key}/stamp"
38
+ end
39
+
40
+ def new_stamp
41
+ Time.now.to_i.to_s 32
42
+ end
43
+
44
+ def prefix
45
+ @prefix ||= "#{@database}/#{@class_key}/#{stamp}"
46
+ end
47
+
48
+ def full_key key
49
+ "#{prefix}/#{key}"
15
50
  end
16
51
 
17
52
  def read key
18
- @store.read(full_key(key))
53
+ @store.read full_key(key)
19
54
  end
20
55
 
21
56
  def write_variable key, variable, value
22
- if @store && (object = @store.read key)
57
+ if @store && (object = read key)
23
58
  object.instance_variable_set "@#{variable}", value
24
- @store.write key, object
59
+ write key, object
25
60
  end
26
61
  value
27
62
  end
28
63
 
29
64
  def write key, value
30
- @store.write(full_key(key), value)
65
+ @store.write full_key(key), value
31
66
  end
32
67
 
33
68
  def fetch key, &block
@@ -38,17 +73,11 @@ class Card::Cache::Persistent
38
73
  @store.delete full_key(key)
39
74
  end
40
75
 
41
- def reset
76
+ def annihilate
42
77
  @store.clear
43
- rescue => e
44
- Rails.logger.debug "Problem clearing cache: #{e.message}"
45
78
  end
46
79
 
47
80
  def exist? key
48
81
  @store.exist? full_key(key)
49
82
  end
50
-
51
- def full_key key
52
- @prefix + key
53
- end
54
83
  end
@@ -1,9 +1,9 @@
1
1
  class Card
2
2
  class Query
3
3
  class SqlStatement
4
- def initialize query
4
+ def initialize query=nil
5
5
  @query = query
6
- @mods = query.mods
6
+ @mods = query && query.mods
7
7
  end
8
8
 
9
9
  def build
@@ -146,18 +146,19 @@ class Card
146
146
  end
147
147
 
148
148
  def standard_conditions query
149
- [trash_condition(query), permission_conditions(query)].compact * ' AND '
149
+ table = query.table_alias
150
+ [trash_condition(table), permission_conditions(table)].compact * ' AND '
150
151
  end
151
152
 
152
- def trash_condition query
153
- "#{query.table_alias}.trash is false"
153
+ def trash_condition table
154
+ "#{table}.trash is false"
154
155
  end
155
156
 
156
- def permission_conditions query
157
+ def permission_conditions table
157
158
  return if Auth.always_ok?
158
159
  read_rules = Auth.as_card.read_rules
159
160
  read_rule_list = read_rules.present? ? read_rules.join(',') : 1
160
- "#{query.table_alias}.read_rule_id IN (#{read_rule_list})"
161
+ "#{table}.read_rule_id IN (#{read_rule_list})"
161
162
  end
162
163
 
163
164
  def group
@@ -205,7 +206,7 @@ class Card
205
206
  when 'id' then "#{table}.id"
206
207
  when 'update' then "#{table}.updated_at"
207
208
  when 'create' then "#{table}.created_at"
208
- when /^(name|alpha)$/ then "LOWER( #{table}.key )"
209
+ when /^(name|alpha)$/ then "#{table}.key"
209
210
  when 'content' then "#{table}.db_content"
210
211
  when 'relevance' then "#{table}.updated_at" # deprecated
211
212
  else
data/lib/cardio.rb CHANGED
@@ -29,7 +29,6 @@ module Cardio
29
29
  recaptcha_private_key: nil,
30
30
  recaptcha_proxy: nil,
31
31
 
32
- cache_store: [:file_store, 'tmp/cache'],
33
32
  override_host: nil,
34
33
  override_protocol: nil,
35
34
 
@@ -41,7 +40,7 @@ module Cardio
41
40
  email_defaults: nil,
42
41
 
43
42
  token_expiry: 2.days,
44
- revisions_per_page: 10,
43
+ acts_per_page: 10,
45
44
  space_last_in_multispace: true,
46
45
  closed_search_limit: 50,
47
46
 
@@ -9,7 +9,7 @@ describe Card::Set::All::Content do
9
9
  @card.save_content_draft('booboo')
10
10
  @card.reload
11
11
  expect(@card.drafts.length).to eq 1
12
- expect(@card.drafts[0].new_values[:content]).to eq 'booboo'
12
+ expect(@card.drafts[0].value(:db_content)).to eq 'booboo'
13
13
  end
14
14
  end
15
15
  end
@@ -9,13 +9,20 @@ class Card
9
9
  class_name: 'Card::Action'
10
10
 
11
11
  belongs_to :actor, class_name: 'Card'
12
- belongs_to :card
12
+
13
+ def card
14
+ Card.fetch card_id, look_in_trash: true, skip_modules: true
15
+ end
13
16
 
14
17
  class << self
18
+ def delete_cardless
19
+ left_join = 'LEFT JOIN cards ON card_acts.card_id = cards.id'
20
+ joins(left_join).where('cards.id IS NULL').delete_all
21
+ end
22
+
15
23
  def delete_actionless
16
24
  joins(
17
- 'LEFT JOIN card_actions '\
18
- 'ON card_acts.id = card_actions.card_act_id'
25
+ 'LEFT JOIN card_actions ON card_acts.id = card_act_id'
19
26
  ).where(
20
27
  'card_actions.id is null'
21
28
  ).delete_all
@@ -27,6 +34,19 @@ class Card
27
34
  vars = { card_ids: card_ids, current_user_id: Card::Auth.current_id }
28
35
  joins(:actions).where(sql, vars).uniq.order(:id).reverse_order
29
36
  end
37
+
38
+ def all_viewable
39
+ joins = 'JOIN card_actions ON card_acts.id = card_act_id ' \
40
+ 'JOIN cards ON cards.id = card_actions.card_id'
41
+ where = [
42
+ 'card_actions.id is not null', # data check. should not be needed
43
+ 'cards.id is not null', # ditto
44
+ 'draft is not true',
45
+ Card::Query::SqlStatement.new.permission_conditions('cards')
46
+ ].compact.join ' AND '
47
+
48
+ joins(joins).where(where).uniq
49
+ end
30
50
  end
31
51
 
32
52
  def set_actor
@@ -54,8 +74,8 @@ class Card
54
74
 
55
75
  def relevant_actions_for card
56
76
  actions.select do |action|
57
- card.included_card_ids.include?(action.card_id) ||
58
- (card.id == action.card_id)
77
+ (card.id == action.card_id) ||
78
+ card.included_card_ids.include?(action.card_id)
59
79
  end
60
80
  end
61
81
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  class Card
4
4
  class Action < ActiveRecord::Base
5
- belongs_to :card
6
5
  belongs_to :act, foreign_key: :card_act_id, inverse_of: :actions
7
6
  has_many :card_changes, foreign_key: :card_action_id, inverse_of: :action,
8
7
  dependent: :delete_all, class_name: 'Card::Change'
@@ -29,14 +28,23 @@ class Card
29
28
  end
30
29
 
31
30
  def fetch id
32
- cache.read(id.to_s) || begin
33
- cache.write id.to_s, Action.find(id.to_i)
31
+ cache.fetch id.to_s do
32
+ find id.to_i
34
33
  end
35
34
  end
36
35
 
37
36
  def delete_cardless
38
37
  left_join = 'LEFT JOIN cards ON card_actions.card_id = cards.id'
39
- Card::Action.joins(left_join).where('cards.id IS NULL').delete_all
38
+ joins(left_join).where('cards.id IS NULL').delete_all
39
+ end
40
+
41
+ def delete_changeless
42
+ joins(
43
+ 'LEFT JOIN card_changes '\
44
+ 'ON card_changes.card_action_id = card_actions.id'
45
+ ).where(
46
+ 'card_changes.id IS NULL'
47
+ ).delete_all
40
48
  end
41
49
 
42
50
  def delete_old
@@ -61,76 +69,44 @@ class Card
61
69
  # writing here (disabled history), we still have to generate change stream
62
70
  # events in another way.
63
71
 
64
- def changed_fields obj, changed_fields
65
- changed_fields.each do |f|
66
- Card::Change.create field: f, value: obj[f], card_action_id: id
67
- end
68
- end
69
-
70
- def edit_info
71
- @edit_info ||= {
72
- action_type: "#{action_type}d",
73
- new_content: new_values[:content],
74
- new_name: new_values[:name],
75
- new_cardtype: new_values[:cardtype],
76
- old_content: old_values[:content],
77
- old_name: old_values[:name],
78
- old_cardtype: old_values[:cardtype]
79
- }
80
- end
81
-
82
- def new_values
83
- @new_values ||=
84
- {
85
- content: new_value_for(:db_content),
86
- name: new_value_for(:name),
87
- cardtype: ((typecard = Card[new_value_for(:type_id).to_i]) &&
88
- typecard.name.capitalize)
89
- }
90
- end
91
-
92
- def old_values
93
- @old_values ||= {
94
- content: last_value_for(:db_content),
95
- name: last_value_for(:name),
96
- cardtype: ((value = last_value_for(:type_id)) &&
97
- (typecard = Card.find(value)) &&
98
- typecard.name.capitalize)
99
- }
100
- end
72
+ # def changed_fields obj, changed_fields
73
+ # changed_fields.each do |f|
74
+ # Card::Change.create field: f, value: obj[f], card_action_id: id
75
+ # end
76
+ # end
101
77
 
102
- def last_value_for field
103
- ch = card.last_change_on(field, before: self)
104
- ch && ch.value
78
+ def value field
79
+ return unless (change = change field)
80
+ interpret_value field, change.value
105
81
  end
106
82
 
107
- def field_index field
108
- if field.is_a? Integer
109
- field
110
- else
111
- Card::TRACKED_FIELDS.index(field.to_s)
112
- end
83
+ def change field
84
+ changes[interpret_field field]
113
85
  end
114
86
 
115
- def new_value_for field
116
- ch = card_changes.find_by(field: field_index(field))
117
- ch && ch.value
87
+ def changes
88
+ @changes ||=
89
+ card_changes.each_with_object({}) do |change, hash|
90
+ hash[change.field.to_sym] = change
91
+ end
118
92
  end
119
93
 
120
- def change_for field
121
- card_changes.where 'card_changes.field = ?', field_index(field)
94
+ def previous_value field
95
+ return if action_type == :create
96
+ return unless (previous_change = previous_change field)
97
+ interpret_value field, previous_change.value
122
98
  end
123
99
 
124
100
  def new_type?
125
- new_value_for :type_id
101
+ value :type_id
126
102
  end
127
103
 
128
104
  def new_content?
129
- new_value_for :db_content
105
+ value :db_content
130
106
  end
131
107
 
132
108
  def new_name?
133
- new_value_for :name
109
+ value :name
134
110
  end
135
111
 
136
112
  def action_type= value
@@ -141,10 +117,6 @@ class Card
141
117
  TYPE[read_attribute(:action_type)]
142
118
  end
143
119
 
144
- def set_act
145
- self.set_act ||= acts.last
146
- end
147
-
148
120
  def revision_nr
149
121
  card.actions.index_of self
150
122
  end
@@ -157,18 +129,14 @@ class Card
157
129
  content_diff_object.green?
158
130
  end
159
131
 
160
- # def diff
161
- # @diff ||= { cardtype: type_diff, content: content_diff, name: name_diff}
162
- # end
163
-
164
132
  def name_diff opts={}
165
133
  return unless new_name?
166
- Card::Diff.complete old_values[:name], new_values[:name], opts
134
+ Card::Diff.complete previous_value(:name), value(:name), opts
167
135
  end
168
136
 
169
137
  def cardtype_diff opts={}
170
138
  return unless new_type?
171
- Card::Diff.complete old_values[:cardtype], new_values[:cardtype], opts
139
+ Card::Diff.complete previous_value(:cardtype), value(:cardtype), opts
172
140
  end
173
141
 
174
142
  def content_diff diff_type=:expanded, opts=nil
@@ -180,15 +148,46 @@ class Card
180
148
  end
181
149
  end
182
150
 
151
+ def card
152
+ Card.fetch card_id, look_in_trash: true, skip_modules: true
153
+ end
154
+
155
+ private
156
+
183
157
  def content_diff_object opts=nil
184
158
  @diff ||= begin
185
159
  diff_args = opts || card.include_set_modules.diff_args
186
- Card::Diff.new old_values[:content], new_values[:content], diff_args
160
+ Card::Diff.new previous_value(:content), value(:content), diff_args
187
161
  end
188
162
  end
189
163
 
190
- def card
191
- Card.fetch card_id, look_in_trash: true
164
+ def previous_change field
165
+ field = interpret_field field
166
+ if @previous_changes && @previous_changes.key?(field)
167
+ @previous_changes[field]
168
+ else
169
+ @previous_changes ||= {}
170
+ @previous_changes[field] = card.last_change_on field, before: self
171
+ end
172
+ end
173
+
174
+ def interpret_field field
175
+ case field
176
+ when :content then :db_content
177
+ when :cardtype then :type_id
178
+ else field.to_sym
179
+ end
180
+ end
181
+
182
+ def interpret_value field, value
183
+ case field.to_sym
184
+ when :type_id
185
+ value && value.to_i
186
+ when :cardtype
187
+ type_card = value && Card.quick_fetch(value.to_i)
188
+ type_card && type_card.name.capitalize
189
+ else value
190
+ end
192
191
  end
193
192
  end
194
193
  end