card 1.18.4 → 1.18.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.yardoc/checksums +263 -240
  3. data/.yardoc/object_types +0 -0
  4. data/.yardoc/objects/root.dat +0 -0
  5. data/VERSION +1 -1
  6. data/card.gemspec +5 -2
  7. data/config/initializers/01_core_extensions/array.rb +9 -0
  8. data/config/initializers/01_core_extensions/hash.rb +57 -0
  9. data/config/initializers/01_core_extensions/module.rb +14 -0
  10. data/config/initializers/01_core_extensions/object.rb +43 -0
  11. data/config/initializers/02_extensions/kaminari.rb +38 -0
  12. data/config/initializers/core_extensions.rb +24 -0
  13. data/config/initializers/extensions.rb +3 -0
  14. data/lib/card.rb +15 -10
  15. data/lib/card/director_register.rb +7 -0
  16. data/lib/card/loader.rb +29 -39
  17. data/lib/card/migration.rb +14 -0
  18. data/lib/card/query.rb +17 -128
  19. data/lib/card/query/attributes.rb +2 -244
  20. data/lib/card/query/conjunctions.rb +36 -0
  21. data/lib/card/query/helpers.rb +72 -0
  22. data/lib/card/query/interpretation.rb +124 -0
  23. data/lib/card/query/relational_attributes.rb +95 -0
  24. data/lib/card/query/sorting.rb +52 -0
  25. data/lib/card/set.rb +73 -362
  26. data/lib/card/set/format.rb +122 -0
  27. data/lib/card/set/helpers.rb +100 -0
  28. data/lib/card/set/loader.rb +98 -0
  29. data/lib/card/set/trait.rb +5 -2
  30. data/lib/card/subcards.rb +38 -12
  31. data/lib/cardio.rb +1 -1
  32. data/lib/generators/card/migration/templates/card_migration.erb +1 -1
  33. data/mod/01_core/chunk/include.rb +13 -1
  34. data/mod/01_core/set/all/event.rb +14 -0
  35. data/mod/01_core/set/all/fetch.rb +21 -7
  36. data/mod/01_core/set/all/states.rb +3 -1
  37. data/mod/01_core/set/all/subcards.rb +4 -2
  38. data/mod/01_core/spec/set/all/fetch_spec.rb +14 -1
  39. data/mod/02_basic_types/set/abstract/code_file.rb +6 -0
  40. data/mod/04_settings/set/type/setting.rb +10 -0
  41. data/mod/05_standard/set/all/rich_html/wrapper.rb +1 -1
  42. data/mod/05_standard/set/self/codenames.rb +0 -0
  43. data/mod/05_standard/spec/chunk/include_spec.rb +10 -10
  44. data/spec/config/initializers/core_extensions_spec.rb +15 -0
  45. data/spec/lib/card/stage_director_spec.rb +25 -1
  46. metadata +25 -8
  47. data/config/initializers/01_init_ruby_extensions.rb +0 -3
  48. data/lib/card/core_ext.rb +0 -107
Binary file
Binary file
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.18.4
1
+ 1.18.5
@@ -38,7 +38,9 @@ Gem::Specification.new do |s|
38
38
  [
39
39
  ['smartname', '0.2.3'],
40
40
  ['uuid', '~> 2.3'],
41
- ['carrierwave', '~> 0.10'],
41
+ # with carrierwave 0.11.1 and 0.11.2 wagn hangs in a loop on creating
42
+ # style and script machine output
43
+ ['carrierwave', '<= 0.11.0'],
42
44
  ['htmlentities', '~> 4.3'],
43
45
  ['mini_magick', '~> 4.2'],
44
46
  ['recaptcha', '~> 0.4.0'],
@@ -55,7 +57,8 @@ Gem::Specification.new do |s|
55
57
  ['diff-lcs', '~> 1.2'],
56
58
  # mime-types can be removed if we drop support for ruby 1.9.3
57
59
  # mime-types 3.0 uses mime-types-data which isn't compatible with 1.9.3
58
- ['mime-types', '2.99.1']
60
+ ['mime-types', '2.99.1'],
61
+
59
62
  ].each do |dep|
60
63
  s.add_runtime_dependency(*dep)
61
64
  end
@@ -0,0 +1,9 @@
1
+ module CoreExtensions
2
+ module Array
3
+ def to_pointer_content
4
+ map do |item|
5
+ "[[#{item}]]"
6
+ end.join "\n"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,57 @@
1
+ module CoreExtensions
2
+ module Hash
3
+ module ClassMethods
4
+ module Nesting
5
+ # create hash with default nested structures
6
+ # @example
7
+ # h = Hash.new_nested Hash, Array
8
+ # h[:a] # => {}
9
+ # h[:b][:c] # => []
10
+ def new_nested *classes
11
+ initialize_nested classes.unshift ::Hash
12
+ end
13
+
14
+ def initialize_nested classes, level=0
15
+ return classes[level].new if level == classes.size - 1
16
+ classes[level].new do |h, k|
17
+ h[k] = initialize_nested classes, level + 1
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ module Merging
24
+ # attach CSS classes
25
+ # @example
26
+ # {}.css_merge({:class => "btn"}) # => {:class=>"btn"}
27
+ #
28
+ # h = {:class => "btn"} # => {:class=>"btn"}
29
+ # h.css_merge({:class => "btn-primary"}) # => {:class=>"btn
30
+ # btn-primary"}
31
+ def css_merge other_hash, separator=' '
32
+ merge(other_hash) do |key, old, new|
33
+ key == :class ? old.to_s + separator + new.to_s : new
34
+ end
35
+ end
36
+
37
+ def css_merge! other_hash, separator=' '
38
+ merge!(other_hash) do |key, old, new|
39
+ key == :class ? old.to_s + separator + new.to_s : new
40
+ end
41
+ end
42
+
43
+ # merge string values with `separator`
44
+ def string_merge other_hash, separator=' '
45
+ merge(other_hash) do |_key, old, new|
46
+ old.is_a?(String) ? old + separator + new.to_s : new
47
+ end
48
+ end
49
+
50
+ def string_merge! other_hash, separator=' '
51
+ merge!(other_hash) do |_key, old, new|
52
+ old.is_a?(String) ? old + separator + new.to_s : new
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,14 @@
1
+ module CoreExtensions
2
+ module Module
3
+ RUBY_VERSION_18 = !!(RUBY_VERSION =~ /^1\.8/)
4
+
5
+ def const_get_if_defined const
6
+ args = RUBY_VERSION_18 ? [const] : [const, false]
7
+ const_get(*args) if const_defined?(*args)
8
+ end
9
+
10
+ def const_get_or_set const
11
+ const_get_if_defined(const) || const_set(const, yield)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,43 @@
1
+ module CoreExtensions
2
+ module Object
3
+ def deep_clone
4
+ case self
5
+ when Fixnum, Bignum, Float, NilClass, FalseClass, TrueClass, Symbol
6
+ klone = self
7
+ when Hash
8
+ klone = clone
9
+ each { |k, v| klone[k] = v.deep_clone }
10
+ when Array
11
+ klone = clone
12
+ klone.clear
13
+ each { |v| klone << v.deep_clone }
14
+ else
15
+ klone = clone
16
+ end
17
+ klone.deep_clone_instance_variables
18
+ klone
19
+ end
20
+
21
+ def send_unless method, *args, &_block
22
+ (block_given? ? yield : self) || send(method, *args)
23
+ end
24
+
25
+ def send_if method, *args, &_block
26
+ (block_given? ? yield : self) && send(method, *args)
27
+ end
28
+
29
+ def to_name
30
+ Card::Name.new self
31
+ end
32
+
33
+ def to_viewname
34
+ Card::ViewName.new self
35
+ end
36
+
37
+ def deep_clone_instance_variables
38
+ instance_variables.each do |v|
39
+ instance_variable_set v, instance_variable_get(v).deep_clone
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,38 @@
1
+ module Extensions
2
+ module Kaminari
3
+ module Helpers
4
+ module Tag
5
+ def page_url_for page
6
+ p = params_for(page)
7
+ p.delete :controller
8
+ p.delete :action
9
+ card = Card[p.delete('id')]
10
+ card.format.path p
11
+ end
12
+
13
+ private
14
+
15
+ def params_for page
16
+ page_params = Rack::Utils.parse_nested_query "#{@param_name}=#{page}"
17
+ page_params = @params.with_indifferent_access.deep_merge(page_params)
18
+
19
+ if Kaminari.config.respond_to?(:params_on_first_page) &&
20
+ !Kaminari.config.params_on_first_page && page <= 1
21
+ # This converts a hash:
22
+ # from: {other: "params", page: 1}
23
+ # to: {other: "params", page: nil}
24
+ # (when @param_name == "page")
25
+ #
26
+ # from: {other: "params", user: {name: "yuki", page: 1}}
27
+ # to: {other: "params", user: {name: "yuki", page: nil}}
28
+ # (when @param_name == "user[page]")
29
+ @param_name.to_s.scan(/\w+/)[0..-2]
30
+ .inject(page_params) { |h, k| h[k] }[$&] = nil
31
+ end
32
+
33
+ page_params
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ # include is private in ruby 1.9.3
4
+ # Object.include CoreExtensions::Object
5
+ # Module.include CoreExtensions::Module
6
+ # Hash.include CoreExtensions::Hash::Merging
7
+ # Array.include CoreExtensions::Array
8
+ class Object
9
+ include CoreExtensions::Object
10
+ end
11
+
12
+ class Module
13
+ include CoreExtensions::Module
14
+ end
15
+
16
+ class Hash
17
+ include CoreExtensions::Hash::Merging
18
+ end
19
+
20
+ class Array
21
+ include CoreExtensions::Array
22
+ end
23
+
24
+ Hash.extend CoreExtensions::Hash::ClassMethods::Nesting
@@ -0,0 +1,3 @@
1
+ class Kaminari::Helpers::Tag
2
+ include Extensions::Kaminari::Helpers::Tag
3
+ end
@@ -15,7 +15,7 @@ class Card < ActiveRecord::Base
15
15
  # attributes that ActiveJob can handle
16
16
  def self.serializable_attr_accessor *args
17
17
  self.serializable_attributes = args
18
- attr_accessor *args
18
+ attr_accessor(*args)
19
19
  end
20
20
 
21
21
  require_dependency 'card/active_record_ext'
@@ -35,7 +35,6 @@ class Card < ActiveRecord::Base
35
35
  require_dependency 'card/stage_director'
36
36
  require_dependency 'card/director_register'
37
37
 
38
-
39
38
  has_many :references_in, class_name: :Reference, foreign_key: :referee_id
40
39
  has_many :references_out, class_name: :Reference, foreign_key: :referer_id
41
40
  has_many :acts, -> { order :id }
@@ -44,8 +43,8 @@ class Card < ActiveRecord::Base
44
43
 
45
44
  cattr_accessor :set_patterns, :serializable_attributes, :error_codes,
46
45
  :set_specific_attributes, :current_act
47
- @@set_patterns = []
48
- @@error_codes = {}
46
+ self.set_patterns = []
47
+ self.error_codes = {}
49
48
 
50
49
  serializable_attr_accessor(
51
50
  :action, :supercard, :superleft,
@@ -61,12 +60,18 @@ class Card < ActiveRecord::Base
61
60
 
62
61
  attr_accessor :follower_stash
63
62
 
64
- define_callbacks :select_action, :show_page, :handle, :act,
65
- :initialize_stage,
66
- :prepare_to_validate_stage, :validate_stage,
67
- :prepare_to_store_stage, :store_stage,
68
- :finalize_stage,
69
- :integrate_stage, :integrate_with_delay_stage
63
+ define_callbacks(
64
+ :select_action, :show_page, :handle, :act,
65
+
66
+ # VALIDATION PHASE
67
+ :initialize_stage, :prepare_to_validate_stage, :validate_stage,
68
+
69
+ # STORAGE PHASE
70
+ :prepare_to_store_stage, :store_stage, :finalize_stage,
71
+
72
+ # INTEGRATION PHASE
73
+ :integrate_stage, :integrate_with_delay_stage
74
+ )
70
75
 
71
76
  before_validation :validation_phase, if: -> { run_phases? }
72
77
  around_save :storage_phase
@@ -63,6 +63,13 @@ class Card
63
63
  director.delete
64
64
  end
65
65
 
66
+ def deep_delete director
67
+ director.subdirectors.each do |subdir|
68
+ deep_delete subdir
69
+ end
70
+ delete director
71
+ end
72
+
66
73
  def to_s
67
74
  directors.values.map(&:to_s).join "\n"
68
75
  end
@@ -21,45 +21,7 @@ class Card
21
21
  load_formats
22
22
  load_sets
23
23
 
24
- update_machine_output_hack if ENV['RAILS_ENV'] == 'development'
25
- end
26
-
27
- def update_machine_output_hack
28
- update_script_output
29
- update_style_output
30
- end
31
-
32
- def update_script_output
33
- script = Card['*all+*script']
34
- return unless (mtime_output = script.machine_output_card.updated_at)
35
- ['wagn_mod.js.coffee', 'wagn.js.coffee',
36
- 'script_card_menu.js.coffee'].each do |name|
37
- mtime_file = File.mtime(
38
- "#{Cardio.gem_root}/mod/03_machines/lib/javascript/#{name}"
39
- )
40
- if mtime_file > mtime_output
41
- script.update_machine_output
42
- break
43
- end
44
- end
45
- end
46
-
47
- def update_style_output
48
- style = Card['*all+*style']
49
- return unless (mtime_output = style.machine_output_card.updated_at)
50
- style.machine_input_card.item_cards.each do |i_card|
51
- next unless i_card.codename
52
- %w(03_machines 06_bootstrap).each do |mod|
53
- style_dir = "#{Cardio.gem_root}/mod/#{mod}/lib/stylesheets"
54
- file_path = "#{style_dir}/#{i_card.codename}.scss"
55
- next unless File.exist? file_path
56
- mtime_file = File.mtime file_path
57
- if mtime_file > mtime_output
58
- style.update_machine_output
59
- break
60
- end
61
- end
62
- end
24
+ refresh_script_and_style if ENV['RAILS_ENV'] == 'development'
63
25
  end
64
26
 
65
27
  def load_chunks
@@ -94,6 +56,34 @@ class Card
94
56
 
95
57
  private
96
58
 
59
+ def refresh_script_and_style
60
+ update_if_source_file_changed Card[:all, :script]
61
+ update_if_source_file_changed Card[:all, :style]
62
+ end
63
+
64
+ # regenerates the machine output if a source file of a input card
65
+ # has been changed
66
+ def update_if_source_file_changed machine_card
67
+ mtime_output = machine_card.machine_output_card.updated_at
68
+ return unless mtime_output
69
+ source_files(machine_card).each do |path|
70
+ if File.mtime(path) > mtime_output
71
+ machine_card.update_machine_output
72
+ break
73
+ end
74
+ end
75
+ end
76
+
77
+ def source_files card
78
+ files = []
79
+ card.machine_input_card.extended_item_cards.each do |i_card|
80
+ next unless i_card.codename
81
+ next unless i_card.respond_to?(:existing_source_paths)
82
+ files << i_card.existing_source_paths
83
+ end
84
+ files.flatten
85
+ end
86
+
97
87
  def load_set_patterns
98
88
  generate_set_pattern_tmp_files if rewrite_tmp_files?
99
89
  load_dir "#{Card.paths['tmp/set_pattern'].first}/*.rb"
@@ -85,6 +85,20 @@ class Card::Migration < ActiveRecord::Migration
85
85
  Card.merge_list read_json(filename), merge_opts
86
86
  end
87
87
 
88
+ def import_cards filename, merge_opts={}
89
+ Card::Mailer.perform_deliveries = false
90
+ output_file = File.join data_path, "unmerged_#{filename}"
91
+ merge_opts[:output_file] ||= output_file
92
+ meta_data = JSON.parse(File.read(data_path(filename)))
93
+ full_data =
94
+ meta_data.map do |hash|
95
+ hash['content'] =
96
+ File.read data_path(File.join('cards', hash['name'].to_name.key))
97
+ hash
98
+ end
99
+ Card.merge_list full_data, merge_opts
100
+ end
101
+
88
102
  def read_json filename
89
103
  raw_json = File.read data_path(filename)
90
104
  json = JSON.parse raw_json
@@ -43,10 +43,15 @@ class Card
43
43
 
44
44
  include Clause
45
45
  include Attributes
46
+ include RelationalAttributes
47
+ include Interpretation
48
+ include Sorting
49
+ include Conjunctions
50
+ include Helpers
46
51
 
47
52
  ATTRIBUTES = {
48
53
  basic: %w( id name key type_id content left_id right_id
49
- creator_id updater_id codename read_rule_id ),
54
+ creator_id updater_id codename read_rule_id ),
50
55
  relational: %w( type part left right
51
56
  editor_of edited_by last_editor_of last_edited_by
52
57
  creator_of created_by member_of member ),
@@ -74,6 +79,17 @@ class Card
74
79
  :subqueries, :superquery
75
80
  attr_accessor :joins, :table_seq, :unjoined, :conditions_on_join
76
81
 
82
+
83
+ # Query Execution
84
+
85
+ # By default a query returns card objects. This is accomplished by returning
86
+ # a card identifier from SQL and then hooking into our caching system (see
87
+ # Card::Fetch)
88
+
89
+ def self.run statement, comment=nil
90
+ new(statement, comment).run
91
+ end
92
+
77
93
  def initialize statement, comment=nil
78
94
  @subqueries = []
79
95
  @conditions = []
@@ -98,15 +114,6 @@ class Card
98
114
  statement.to_s
99
115
  end
100
116
 
101
- # Query Execution
102
- # By default a query returns card objects. This is accomplished by returning
103
- # a card identifier from SQL and then hooking into our caching system (see
104
- # Card::Fetch)
105
-
106
- def self.run statement, comment=nil
107
- new(statement, comment).run
108
- end
109
-
110
117
  # run the current query
111
118
  # @return array of card objects by default
112
119
  def run
@@ -162,52 +169,6 @@ class Card
162
169
  subquery
163
170
  end
164
171
 
165
- # Query Interpretation
166
-
167
- # normalize and extract meaning from a clause
168
- # @param clause [Hash, String, Integer] statement or chunk thereof
169
- def interpret clause
170
- interpret_by_key normalize_clause(clause)
171
- end
172
-
173
- def normalize_clause clause
174
- clause = clause_to_hash clause
175
- clause.symbolize_keys!
176
- clause.each do |key, val|
177
- clause[key] = normalize_value val
178
- end
179
- clause
180
- end
181
-
182
- def clause_to_hash clause
183
- case clause
184
- when Hash then clause
185
- when String then { key: clause.to_name.key }
186
- when Integer then { id: clause }
187
- else raise BadQuery, "Invalid query args #{clause.inspect}"
188
- end
189
- end
190
-
191
- def normalize_value val
192
- case val
193
- when Integer, Float, Symbol, Hash then val
194
- when String, SmartName then normalize_string_value val
195
- when Array then val.map { |v| normalize_value v }
196
- else raise BadQuery, "unknown WQL value type: #{val.class}"
197
- end
198
- end
199
-
200
- def normalize_string_value val
201
- case val.to_s
202
- when /^\$(\w+)$/ # replace from @vars
203
- @vars[Regexp.last_match[1].to_sym].to_s.strip
204
- when /\b_/ # absolutize based on @context
205
- val.to_name.to_absolute(context)
206
- else
207
- val
208
- end
209
- end
210
-
211
172
  def context
212
173
  if !@context.nil?
213
174
  @context
@@ -215,77 +176,5 @@ class Card
215
176
  @context = @superquery ? @superquery.context : ''
216
177
  end
217
178
  end
218
-
219
- def interpret_by_key clause
220
- clause.each do |key, val|
221
- case
222
- when OPERATORS.key?(key.to_s) && !ATTRIBUTES[key]
223
- # eg "match" is both operator and attribute;
224
- # interpret as attribute when "match" is key
225
- interpret content: [key, val]
226
- when MODIFIERS.key?(key) && !clause[key].is_a?(Hash)
227
- # eg when "sort" is hash, it can have subqueries
228
- # and must be interpreted like an attribute
229
- @mods[key] = val.is_a?(Array) ? val : val.to_s
230
- else
231
- interpret_attributes key, val
232
- end
233
- end
234
- end
235
-
236
- def add_condition *args
237
- @conditions <<
238
- if args.size > 1
239
- [args.shift, Value.new(args.shift, self)]
240
- else
241
- args[0]
242
- end
243
- end
244
-
245
- def interpret_attributes key, val
246
- case ATTRIBUTES[key]
247
- when :basic then add_condition key, val
248
- when :conjunction then send key, val
249
- when :relational then relate key, val
250
- when :special then relate key, val
251
- when :ref_relational then relate key, val, method: :join_references
252
- when :plus_relational then relate_compound key, val
253
- when :ignore then # noop
254
- else raise BadQuery, "Invalid attribute #{key}"
255
- end
256
- end
257
-
258
- def relate_compound key, val
259
- has_multiple_values =
260
- val.is_a?(Array) &&
261
- (val.first.is_a?(Array) || conjunction(val.first).present?)
262
- relate key, val, multiple: has_multiple_values
263
- end
264
-
265
- def relate key, val, opts={}
266
- multiple = opts[:multiple].nil? ? val.is_a?(Array) : opts[:multiple]
267
- method = opts[:method] || :send
268
-
269
- if multiple
270
- conj = conjunction(val.first) ? conjunction(val.shift) : :and
271
- if conj == current_conjunction
272
- # same conjunction as container, no need for subcondition
273
- val.each { |v| send method, key, v }
274
- else
275
- send conj, val.map { |v| { key => v } }
276
- end
277
- else
278
- send method, key, val
279
- end
280
- end
281
-
282
- def current_conjunction
283
- @mods[:conj].blank? ? :and : @mods[:conj]
284
- end
285
-
286
- def all_joins
287
- @all_joins ||=
288
- (joins + subqueries.select(&:unjoined).map(&:all_joins)).flatten
289
- end
290
179
  end
291
180
  end