card 1.18.4 → 1.18.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardoc/checksums +263 -240
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/VERSION +1 -1
- data/card.gemspec +5 -2
- data/config/initializers/01_core_extensions/array.rb +9 -0
- data/config/initializers/01_core_extensions/hash.rb +57 -0
- data/config/initializers/01_core_extensions/module.rb +14 -0
- data/config/initializers/01_core_extensions/object.rb +43 -0
- data/config/initializers/02_extensions/kaminari.rb +38 -0
- data/config/initializers/core_extensions.rb +24 -0
- data/config/initializers/extensions.rb +3 -0
- data/lib/card.rb +15 -10
- data/lib/card/director_register.rb +7 -0
- data/lib/card/loader.rb +29 -39
- data/lib/card/migration.rb +14 -0
- data/lib/card/query.rb +17 -128
- data/lib/card/query/attributes.rb +2 -244
- data/lib/card/query/conjunctions.rb +36 -0
- data/lib/card/query/helpers.rb +72 -0
- data/lib/card/query/interpretation.rb +124 -0
- data/lib/card/query/relational_attributes.rb +95 -0
- data/lib/card/query/sorting.rb +52 -0
- data/lib/card/set.rb +73 -362
- data/lib/card/set/format.rb +122 -0
- data/lib/card/set/helpers.rb +100 -0
- data/lib/card/set/loader.rb +98 -0
- data/lib/card/set/trait.rb +5 -2
- data/lib/card/subcards.rb +38 -12
- data/lib/cardio.rb +1 -1
- data/lib/generators/card/migration/templates/card_migration.erb +1 -1
- data/mod/01_core/chunk/include.rb +13 -1
- data/mod/01_core/set/all/event.rb +14 -0
- data/mod/01_core/set/all/fetch.rb +21 -7
- data/mod/01_core/set/all/states.rb +3 -1
- data/mod/01_core/set/all/subcards.rb +4 -2
- data/mod/01_core/spec/set/all/fetch_spec.rb +14 -1
- data/mod/02_basic_types/set/abstract/code_file.rb +6 -0
- data/mod/04_settings/set/type/setting.rb +10 -0
- data/mod/05_standard/set/all/rich_html/wrapper.rb +1 -1
- data/mod/05_standard/set/self/codenames.rb +0 -0
- data/mod/05_standard/spec/chunk/include_spec.rb +10 -10
- data/spec/config/initializers/core_extensions_spec.rb +15 -0
- data/spec/lib/card/stage_director_spec.rb +25 -1
- metadata +25 -8
- data/config/initializers/01_init_ruby_extensions.rb +0 -3
- data/lib/card/core_ext.rb +0 -107
data/.yardoc/object_types
CHANGED
Binary file
|
data/.yardoc/objects/root.dat
CHANGED
Binary file
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.18.
|
1
|
+
1.18.5
|
data/card.gemspec
CHANGED
@@ -38,7 +38,9 @@ Gem::Specification.new do |s|
|
|
38
38
|
[
|
39
39
|
['smartname', '0.2.3'],
|
40
40
|
['uuid', '~> 2.3'],
|
41
|
-
|
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,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
|
data/lib/card.rb
CHANGED
@@ -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
|
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
|
-
|
48
|
-
|
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
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
data/lib/card/loader.rb
CHANGED
@@ -21,45 +21,7 @@ class Card
|
|
21
21
|
load_formats
|
22
22
|
load_sets
|
23
23
|
|
24
|
-
|
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"
|
data/lib/card/migration.rb
CHANGED
@@ -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
|
data/lib/card/query.rb
CHANGED
@@ -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
|