card 1.105.0 → 1.105.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/card/director/card_class.rb +17 -14
- data/lib/card/fetch/card_class.rb +19 -13
- data/lib/card/name.rb +3 -3
- data/lib/card/query.rb +8 -5
- data/lib/card/set/abstract.rb +1 -0
- data/lib/card/set/format/abstract_format/wrapper.rb +0 -1
- data/lib/card/set/format/abstract_format.rb +4 -3
- data/lib/card/set/format.rb +46 -20
- data/lib/card/set/helpers.rb +49 -36
- data/lib/card/set/registrar.rb +3 -5
- data/lib/card/set/required_field.rb +3 -2
- data/lib/card/set/type.rb +1 -0
- data/lib/card/set.rb +67 -21
- data/lib/card.rb +30 -12
- data/lib/cardio/command/custom.rb +1 -0
- data/lib/cardio/command/rake_command.rb +1 -1
- data/lib/cardio/command/rspec_command/parser.rb +7 -4
- data/lib/cardio/generators.rb +1 -1
- data/lib/cardio/mod/class_methods.rb +2 -2
- data/lib/cardio/mod/dirs.rb +1 -1
- data/lib/cardio/mod/eat/edibles.rb +21 -1
- data/lib/cardio/mod/eat.rb +4 -2
- data/lib/cardio/mod/modfile_api.rb +2 -2
- data/lib/cardio/mod/sow.rb +16 -16
- data/lib/cardio/mod.rb +30 -48
- data/lib/cardio/railtie.rb +3 -3
- data/lib/generators/mod/mod_generator.rb +5 -5
- data/mod/core/lib/tasks/card/mod.rake +5 -2
- data/mod/core/lib/tasks/card/seed.rake +6 -4
- data/mod/core/lib/tasks/card.rake +8 -4
- data/mod/core/set/all/states.rb +8 -2
- metadata +6 -8
- data/mod/core/lib/tasks/card/assets.rake +0 -17
- data/mod/core/lib/tasks/card/create.rake +0 -81
- /data/mod/core/{locales → config/locales}/de.yml +0 -0
- /data/mod/core/{locales → config/locales}/en.yml +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d1c8cf4b2e9416f3e17e107de3651e51957b9bb0f8bd9a32dfb7c9e5ffcfe5e
|
4
|
+
data.tar.gz: ea4bf60694b93994f9fd8e626fe2dd6bf0860ce1e270e533066b42d3e98c0f39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65ff19795cd4a020bd67bf08d35d5eef95c3b904bc70fd2fe94eee219c5e34e4e77b29868302f98069d3fc2877c7cf9f69bffc5193bdffec337925a57997b1d3
|
7
|
+
data.tar.gz: 40ada7a7227dd40ae2d8edb9a23aa4a6c4777c505a73f1a39e2ed2ad9ce741078e1645ac995de6ad8c509bfb94f11f02dec78d8906ad465cdae09ecc444cbab1
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.15.
|
1
|
+
0.15.1
|
@@ -16,35 +16,38 @@ class Card
|
|
16
16
|
|
17
17
|
# The ensure methods are use to make sure a card exists and can be used when you're
|
18
18
|
# unsure as to whether it already does. It's arguments are largely the same as
|
19
|
-
# those used by Card
|
20
|
-
# `conflict`.
|
21
|
-
|
19
|
+
# those used by {#create Card#create} and {Director::All#update @card.update} with
|
20
|
+
# the important exception of `conflict`.
|
21
|
+
#
|
22
22
|
# The conflict argument takes one of three values:
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
|
23
|
+
#
|
24
|
+
# - **defer**: let existing card stay as it is
|
25
|
+
# - **default**: update existing card if it is "pristine" (meaning it has not
|
26
|
+
# been edited by anyone other than Decko Bot)
|
27
|
+
# - **override**: update existing card
|
28
|
+
#
|
28
29
|
# If the options specify a codename and the name is already in use, things get a
|
29
30
|
# little more involved. (Note: we MUST ensure that a card with the codename exists!)
|
30
|
-
|
31
|
-
# If the conflict setting is "defer":
|
31
|
+
#
|
32
|
+
# If the conflict setting is "**defer**":
|
32
33
|
#
|
33
34
|
# - if the _codename_ is NOT already in use, we create a new card with an
|
34
35
|
# altered name
|
35
36
|
# - otherwise we do nothing.
|
36
37
|
#
|
37
|
-
# If the conflict setting is "default":
|
38
|
+
# If the conflict setting is "**default**":
|
39
|
+
#
|
38
40
|
# - if the _codename_ is NOT already in use:
|
39
41
|
# - if the card using the name we want is pristine, we update that card
|
40
42
|
# - otherwise we create a new card with an altered name
|
41
|
-
# - if the
|
43
|
+
# - if the _codename_ IS already in use
|
42
44
|
# - if the card with the codename is pristine, we update everything but the
|
43
45
|
# name (which is used by another card)
|
44
46
|
# - otherwise we do nothing
|
45
47
|
#
|
46
|
-
# If the conflict setting is "override":
|
47
|
-
#
|
48
|
+
# If the conflict setting is "**override**":
|
49
|
+
#
|
50
|
+
# - if the _codename_ is NOT already in use, we update the existing card with the
|
48
51
|
# name.
|
49
52
|
# - otherwise we alter the card withe the conflicting name and update the card
|
50
53
|
# with the codename.
|
@@ -1,29 +1,32 @@
|
|
1
1
|
class Card
|
2
2
|
class Fetch
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# A multipurpose retrieval operator that integrates caching, database lookups,
|
3
|
+
# A multipurpose retrieval system that integrates caching, database lookups,
|
6
4
|
# and "virtual" card construction
|
7
5
|
module CardClass
|
8
6
|
# Look for cards in
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
7
|
+
# * cache
|
8
|
+
# * database
|
9
|
+
# * virtual cards
|
12
10
|
#
|
13
11
|
# @param args [Integer, String, Card::Name, Symbol, Array]
|
14
12
|
# Initials args must be one or more "marks," which uniquely idenfify cards:
|
13
|
+
#
|
14
|
+
#
|
15
15
|
# 1. a name/key. (String or Card::Name)
|
16
16
|
# 2. a numeric id. Can be (a) an Integer or (b) a String with an integer
|
17
17
|
# prefixed with a tilde, eg "~1234"
|
18
18
|
# 3. a codename. Can be (a) a Symbol or (b) a String with a colon prefix,
|
19
19
|
# eg :mycodename
|
20
|
+
#
|
20
21
|
# If you pass more then one mark or an array of marks they get joined with a '+'.
|
21
22
|
# The final argument can be a Hash to set the following options
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
23
|
+
#
|
24
|
+
# :skip_virtual Real cards only
|
25
|
+
# :skip_modules Don't load Set modules
|
26
|
+
# :look_in_trash Return trashed card objects
|
27
|
+
# :local_only Use only local cache for lookup and storing
|
28
|
+
# new: { opts for Card#new } Return a new card when not found
|
29
|
+
#
|
27
30
|
# @return [Card]
|
28
31
|
def fetch *args
|
29
32
|
f = Fetch.new(*args)
|
@@ -32,9 +35,9 @@ class Card
|
|
32
35
|
Card.new name: "card id out of range: #{f.mark}"
|
33
36
|
end
|
34
37
|
|
35
|
-
# fetch only real (no
|
38
|
+
# a shortcut for fetch that returns only real cards (no virtuals)
|
36
39
|
#
|
37
|
-
# @param mark - see #fetch
|
40
|
+
# @param mark [various] - see {#fetch}
|
38
41
|
# @return [Card]
|
39
42
|
def [] *mark
|
40
43
|
fetch(*mark, skip_virtual: true)
|
@@ -62,6 +65,9 @@ class Card
|
|
62
65
|
# ATTRIBUTE FETCHING
|
63
66
|
# The following methods optimize fetching of specific attributes
|
64
67
|
|
68
|
+
# numerical card id
|
69
|
+
# @params cardish [various] interprets integers as id, symbols as codename, etc
|
70
|
+
# @return [Integer]
|
65
71
|
def id cardish
|
66
72
|
case cardish
|
67
73
|
when Integer then cardish
|
data/lib/card/name.rb
CHANGED
@@ -5,10 +5,10 @@
|
|
5
5
|
require "cardname"
|
6
6
|
|
7
7
|
class Card
|
8
|
-
# The Cardname class provides generalized of Card naming patterns
|
9
|
-
#
|
8
|
+
# The {Cardname} class provides generalized of Card naming patterns (compound names,
|
9
|
+
# key-based variants, etc) and can be used independently of Card objects.
|
10
10
|
#
|
11
|
-
# Card::Name adds support for deeper
|
11
|
+
# {Card::Name} adds support for deeper integration with Card objects
|
12
12
|
class Name < Cardname
|
13
13
|
include NameVariants
|
14
14
|
|
data/lib/card/query.rb
CHANGED
@@ -7,8 +7,8 @@ class Card
|
|
7
7
|
# frequently used directly in code.
|
8
8
|
#
|
9
9
|
# Query "statements" (objects, really) are made in CQL (Card Query
|
10
|
-
# Language). Because CQL is used by Sharks, the primary
|
11
|
-
#
|
10
|
+
# Language). Because CQL is used by Sharks, [the primary CQL Syntax documentation is
|
11
|
+
# on decko.org](https://decko.org/CQL_Syntax). Note that the
|
12
12
|
# examples there are in JSON, like Search card content, but statements in
|
13
13
|
# Card::Query are in ruby form.
|
14
14
|
#
|
@@ -17,9 +17,11 @@ class Card
|
|
17
17
|
# CQL statement interpretation.
|
18
18
|
#
|
19
19
|
# The most common way to use Card::Query is as follows:
|
20
|
+
#
|
20
21
|
# list_of_cards = Card::Query.run(statement)
|
21
22
|
#
|
22
23
|
# This is equivalent to:
|
24
|
+
#
|
23
25
|
# query = Card::Query.new(statement)
|
24
26
|
# list_of_cards = query.run
|
25
27
|
#
|
@@ -32,7 +34,8 @@ class Card
|
|
32
34
|
# - @subqueries - a list of other queries nested within this one
|
33
35
|
#
|
34
36
|
# Each condition is either a SQL-ready string (boo) or an Array in this form:
|
35
|
-
#
|
37
|
+
#
|
38
|
+
# [field_string_or_sym, (Card::Value::Query object)]
|
36
39
|
module Query
|
37
40
|
require "card/query/clause"
|
38
41
|
require "card/query/card_query"
|
@@ -48,8 +51,8 @@ class Card
|
|
48
51
|
# their values are translated fairly directly into SQL-safe values.
|
49
52
|
# (These are referred to as "properties" in CQL documentation. Need to
|
50
53
|
# reconcile #EFM)
|
51
|
-
basic: %i[id name key type_id content left_id right_id
|
52
|
-
creator_id updater_id
|
54
|
+
basic: %i[id name key type_id content left_id right_id codename read_rule_id
|
55
|
+
created_at updated_at creator_id updater_id ],
|
53
56
|
# "Relational" values can involve tying multiple queries together
|
54
57
|
relational: %i[type
|
55
58
|
part left right
|
data/lib/card/set/abstract.rb
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
class Card
|
4
4
|
module Set
|
5
5
|
module Format
|
6
|
-
# AbstractFormat manages the
|
7
|
-
#
|
8
|
-
# create a format
|
6
|
+
# AbstractFormat manages the DSL for defining {#view views}.
|
7
|
+
#
|
8
|
+
# Whenever you create a {Format format} block in a {Cardio::Set set module},
|
9
|
+
# you create a format module that is extended with AbstractFormat.
|
9
10
|
module AbstractFormat
|
10
11
|
include ViewOpts
|
11
12
|
include ViewDefinition
|
data/lib/card/set/format.rb
CHANGED
@@ -2,33 +2,58 @@
|
|
2
2
|
|
3
3
|
class Card
|
4
4
|
module Set
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Card::Set::Format is responsible for handling `format` blocks within the set module
|
6
|
+
# DSL, which is used in {Cardio::Mod Set module} files found in {Cardio::Mod mods'}
|
7
|
+
# set directories. Monkeys use the DSL to define views that apply to specific sets of
|
8
|
+
# cards in specific formats. The views can then be
|
9
|
+
# used by Monkeys in code and by Sharks via the UI.
|
7
10
|
#
|
8
|
-
#
|
11
|
+
# For example, imagine you have a set module file in `mod/mymod/type/my_type.rb`.
|
12
|
+
# There you can define a view like this:
|
9
13
|
#
|
10
14
|
# format :html do
|
11
|
-
#
|
15
|
+
# view :hello do
|
16
|
+
# greeting
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# {AbstractFormat#view Learn more about defining views}
|
21
|
+
#
|
22
|
+
# This view will now be available to MyType cards in HTML -- but not in other formats.
|
23
|
+
# Similarly, you can define other methods in format blocks:
|
24
|
+
#
|
25
|
+
# format :html do
|
26
|
+
# def greeting
|
12
27
|
# :rocks
|
13
28
|
# end
|
14
29
|
# end
|
15
30
|
#
|
16
|
-
# The magic that happens here is that the method #
|
17
|
-
# available) _only_ to the cards in the set specified by the mod, and
|
18
|
-
#
|
31
|
+
# The magic that happens here is that the method #greeting is now applicable (and
|
32
|
+
# available) _only_ to the cards in the {Card::Set set} specified by the mod, and
|
33
|
+
# only when rendering a view of the card in the HTML format. {Card::Format Learn
|
34
|
+
# more about formats}.
|
19
35
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# How the format object for a given card in the set includes this module dynamically
|
23
|
-
# when it's initialized. And so on...
|
36
|
+
# So if, for example, I had a card "MyCard" with the type "MyType", the following
|
37
|
+
# should use the method above:
|
24
38
|
#
|
25
|
-
#
|
39
|
+
# ````
|
40
|
+
# "MyCard".card.format(:html).greeting
|
41
|
+
# ````
|
42
|
+
#
|
43
|
+
# ...but if the card had a different type, or if I tried to use the method in, say,
|
44
|
+
# the JSON format, this #beethoven method wouldn't be available.
|
45
|
+
#
|
46
|
+
# Under the hood, the DSL creates a ruby module that looks something like
|
47
|
+
# `Card::Set::Type::MyType::HtmlFormat`. This module will then be dynamically included
|
48
|
+
# in HTML format objects for MyCard.
|
49
|
+
#
|
50
|
+
# As monkeys, we don't usually think about all that much, because we work in
|
26
51
|
# the set module space, which lets us focus on the card patterns.
|
27
52
|
#
|
28
53
|
# Speaking of which, there are a few key patterns to be aware of:
|
29
54
|
#
|
30
55
|
# 1. Just as in {Card::Set sets}, format methods for narrower sets will override
|
31
|
-
# format methods for more general sets. So if a #
|
56
|
+
# format methods for more general sets. So if a #greeting method is defined
|
32
57
|
# for all cards and again for a specific card type, then the type method will
|
33
58
|
# override the all method when both apply.
|
34
59
|
# 2. Similarly, specific formats inherit from more general formats, and all formats
|
@@ -36,27 +61,28 @@ class Card
|
|
36
61
|
# will define methods on the base format class.
|
37
62
|
#
|
38
63
|
# format do
|
39
|
-
# def
|
40
|
-
#
|
64
|
+
# def farewell
|
65
|
+
# "goodbye"
|
41
66
|
# end
|
42
67
|
# end
|
43
68
|
#
|
44
69
|
# 3. It is possible to use super to refer to overridden methods. For example
|
45
70
|
#
|
46
71
|
# format :html do
|
47
|
-
# def
|
72
|
+
# def goodbye
|
48
73
|
# "<em>#{super}</em>"
|
49
74
|
# end
|
50
75
|
# end
|
51
76
|
#
|
52
77
|
# Note: Set precedence has a higher priority than Format precedence.
|
53
78
|
#
|
54
|
-
# 4.
|
55
|
-
# be defined on the base format.
|
56
|
-
#
|
57
|
-
# 5. Some very powerful API calls (including {AbstractFormat#view view} and
|
79
|
+
# 4. Some very powerful API calls (including {AbstractFormat#view view} and
|
58
80
|
# {AbstractFormat#before before}) are defined in {AbstractFormat}. These methods are
|
59
81
|
# always available in format blocks.
|
82
|
+
#
|
83
|
+
# 5. {#view} and {#before}, however, can ALSO both be called outside of a format
|
84
|
+
# block. They will be defined on the base format.
|
85
|
+
#
|
60
86
|
module Format
|
61
87
|
require "card/set/format/haml_paths"
|
62
88
|
require "card/set/format/abstract_format"
|
data/lib/card/set/helpers.rb
CHANGED
@@ -1,42 +1,32 @@
|
|
1
1
|
class Card
|
2
2
|
module Set
|
3
|
+
# These helper methods provide easy access to metadata, such as information about
|
4
|
+
# the set modified by a module. These methods are seldom used by Monkeys; they are
|
5
|
+
# primarily Platypus tools.
|
3
6
|
module Helpers
|
4
7
|
SET_PATTERN_TEST_REGEXP = /^(?<pattern>\w+)_set\?$/
|
5
8
|
|
9
|
+
# @return [String] short name of card module. For example, returns Type::User for
|
10
|
+
# Card::Set::Type::User
|
6
11
|
def shortname
|
7
12
|
first = 2 # shortname eliminates Card::Set
|
8
13
|
last = first + num_set_parts(pattern_code)
|
9
14
|
set_name_parts[first..last].join "::"
|
10
15
|
end
|
11
16
|
|
12
|
-
|
17
|
+
# @return [String] name of card module with underscores. For example, returns
|
18
|
+
# Card__Set__Type__User for Card::Set::Type::User
|
19
|
+
def underscored_name
|
13
20
|
shortname.tr(":", "_").underscore
|
14
21
|
end
|
15
22
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Pattern.find(pattern_code).anchor_parts_count
|
20
|
-
end
|
21
|
-
|
22
|
-
def set_format_type_key
|
23
|
-
@set_format_type_key ||= :"#{set_type_key}_format"
|
24
|
-
end
|
25
|
-
|
26
|
-
def set_type_key
|
27
|
-
if all_set?
|
28
|
-
:base
|
29
|
-
elsif abstract_set?
|
30
|
-
:abstract
|
31
|
-
else
|
32
|
-
:nonbase
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
23
|
+
# @return [Array] list of strings of parts of set module's name
|
24
|
+
# Eg, returns ["Card", "Set", "Type", "User"] for Card::Set::Type::User
|
36
25
|
def set_name_parts
|
37
26
|
@set_name_parts ||= name.split "::"
|
38
27
|
end
|
39
28
|
|
29
|
+
# @return [Symbol] codename associated with set's pattern. Eg :type, :right, etc
|
40
30
|
def pattern_code
|
41
31
|
@pattern_code ||= set_name_parts[2].underscore.to_sym
|
42
32
|
end
|
@@ -50,6 +40,8 @@ class Card
|
|
50
40
|
end
|
51
41
|
end
|
52
42
|
|
43
|
+
# @return [true/false]
|
44
|
+
# handles all_set?, abstract_set?, type_set?, etc.
|
53
45
|
def respond_to_missing? method_name, _include_private=false
|
54
46
|
method_name.match? SET_PATTERN_TEST_REGEXP
|
55
47
|
end
|
@@ -64,21 +56,6 @@ class Card
|
|
64
56
|
end
|
65
57
|
end
|
66
58
|
|
67
|
-
def test_set
|
68
|
-
# rubocop:disable Lint/Eval
|
69
|
-
::Card::Set::Self.const_remove_if_defined :TestSet
|
70
|
-
eval <<-RUBY, binding, __FILE__, __LINE__ + 1
|
71
|
-
class ::Card::Set::Self
|
72
|
-
module TestSet
|
73
|
-
extend Card::Set
|
74
|
-
include_set #{name}
|
75
|
-
end
|
76
|
-
end
|
77
|
-
RUBY
|
78
|
-
::Card::Set::Self::TestSet
|
79
|
-
# rubocop:enable Lint/Eval
|
80
|
-
end
|
81
|
-
|
82
59
|
def format_modules format_sym, test: true
|
83
60
|
if base_format_modules?
|
84
61
|
[format_module(format_sym)]
|
@@ -95,6 +72,36 @@ class Card
|
|
95
72
|
|
96
73
|
private
|
97
74
|
|
75
|
+
# @return [Symbol] base_format,
|
76
|
+
def set_format_type_key
|
77
|
+
@set_format_type_key ||= :"#{set_type_key}_format"
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_type_key
|
81
|
+
if all_set?
|
82
|
+
:base
|
83
|
+
elsif abstract_set?
|
84
|
+
:abstract
|
85
|
+
else
|
86
|
+
:nonbase
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_set
|
91
|
+
# rubocop:disable Lint/Eval
|
92
|
+
::Card::Set::Self.const_remove_if_defined :TestSet
|
93
|
+
eval <<-RUBY, binding, __FILE__, __LINE__ + 1
|
94
|
+
class ::Card::Set::Self
|
95
|
+
module TestSet
|
96
|
+
extend Card::Set
|
97
|
+
include_set #{name}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
RUBY
|
101
|
+
::Card::Set::Self::TestSet
|
102
|
+
# rubocop:enable Lint/Eval
|
103
|
+
end
|
104
|
+
|
98
105
|
def base_format_modules?
|
99
106
|
!set_format_type_key || set_format_type_key == :base_format
|
100
107
|
end
|
@@ -107,6 +114,12 @@ class Card
|
|
107
114
|
format_class = Card::Format.format_class format: format_sym
|
108
115
|
Card::Set.modules[set_format_type_key][format_class][shortname] || []
|
109
116
|
end
|
117
|
+
|
118
|
+
def num_set_parts pattern_code
|
119
|
+
return 1 if pattern_code == :abstract
|
120
|
+
|
121
|
+
Pattern.find(pattern_code).anchor_parts_count
|
122
|
+
end
|
110
123
|
end
|
111
124
|
end
|
112
125
|
end
|
data/lib/card/set/registrar.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
class Card
|
4
4
|
module Set
|
5
5
|
# the set loading process has two main phases:
|
6
|
-
|
6
|
+
#
|
7
7
|
# 1. Definition: interpret each set file, creating/defining set and
|
8
8
|
# set_format modules
|
9
9
|
# 2. Organization: have base classes include modules associated with the
|
@@ -72,10 +72,8 @@ class Card
|
|
72
72
|
|
73
73
|
# makes sets ready for dynamic loading via #include_set_modules
|
74
74
|
def register_set_of_type set_module, set_type
|
75
|
-
|
76
|
-
|
77
|
-
mods[key] ||= []
|
78
|
-
mods[key] << set_module
|
75
|
+
list = modules[set_type][set_module.shortname] ||= []
|
76
|
+
list << set_module unless list.member? set_module
|
79
77
|
end
|
80
78
|
|
81
79
|
def process_base_format_modules base_format_modules
|
@@ -18,11 +18,12 @@ class Card
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def parent_event_name
|
21
|
-
[parent_set.
|
21
|
+
[parent_set.underscored_name, "requires_field", field].join("__").to_sym
|
22
22
|
end
|
23
23
|
|
24
24
|
def field_event_name action
|
25
|
-
[field, "required_by", parent_set.
|
25
|
+
[field, "required_by", parent_set.underscored_name, "on", action]
|
26
|
+
.join("__").to_sym
|
26
27
|
end
|
27
28
|
|
28
29
|
private
|
data/lib/card/set/type.rb
CHANGED
data/lib/card/set.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
3
|
class Card
|
4
|
-
#
|
5
4
|
# A _Set_ is a group of {Card Cards} to which _Rules_ may apply. Sets can be as
|
6
5
|
# specific as a single card, as general as all cards, or anywhere in between.
|
7
6
|
#
|
@@ -11,39 +10,86 @@ class Card
|
|
11
10
|
# web interface and are thus documented at https://decko.org/rules.
|
12
11
|
# - **Code rules** can be defined in a 'set module'.
|
13
12
|
#
|
14
|
-
#
|
15
|
-
#
|
13
|
+
# ## Set Modules
|
14
|
+
#
|
15
|
+
# ### File structure
|
16
|
+
#
|
17
|
+
# Set modules specify views, events, and other methods for a given set of cards.
|
18
|
+
# They are defined in a {Cardio::Mod mod's} _set_ directory. For example, suppose
|
19
|
+
# you've created a mod called *biz*, your deck has Company cards, and you want to
|
20
|
+
# extend the behavior of those cards.
|
21
|
+
#
|
22
|
+
# You can add a set module like so:
|
23
|
+
#
|
24
|
+
# card generate set biz type company
|
25
|
+
#
|
26
|
+
# This will create the following two files:
|
27
|
+
#
|
28
|
+
# mod/biz/set/type/company.rb
|
29
|
+
# mod/biz/spec/set/type/company.rb
|
30
|
+
#
|
31
|
+
# If you would like to break this code into smaller files, you can extend this
|
32
|
+
# pattern into another directory, eg:
|
33
|
+
#
|
34
|
+
# mod/biz/set/type/company/foo.rb
|
35
|
+
# mod/biz/set/type/company/bar.rb
|
36
|
+
#
|
37
|
+
# The general pattern can be expressed as follows:
|
38
|
+
#
|
39
|
+
# DECKNAME/mod/MODNAME/set/SET_PATTERN/ANCHOR[/FREENAME].rb
|
16
40
|
#
|
17
|
-
#
|
18
|
-
# and
|
41
|
+
# **Note:** _the set module's filename connects it to the set, so both the set_pattern
|
42
|
+
# and the set_anchor must correspond to the codename of a card in the database to
|
43
|
+
# function correctly. For example, the type/company directory corresponds to the Set
|
44
|
+
# card named `:company+:type`. Both the :company and :type codenames must exist for this
|
45
|
+
# to work properly._
|
46
|
+
#
|
47
|
+
# ### Writing/Editing set modules
|
48
|
+
#
|
49
|
+
# A set module is mostly standard ruby, but the files are quite concise because
|
50
|
+
#
|
51
|
+
# 1. the set module's file location is used to autogenerate ruby module definitions
|
52
|
+
# 2. A DSL (Domain-Specific Language) makes common tasks easy.
|
53
|
+
#
|
54
|
+
# You can, for example, edit `mod/biz/set/type/company.rb`, and add _only_ the
|
55
|
+
# following code:
|
56
|
+
#
|
57
|
+
# def hello
|
58
|
+
# "world"
|
59
|
+
# end
|
19
60
|
#
|
20
|
-
#
|
61
|
+
# No further code is needed for this method to be available to cards with the type
|
62
|
+
# Company (as specified by the file's location). This code will automatically be added
|
63
|
+
# to a ruby module named `Card::Set::Type::Company`. That module is extended with the
|
64
|
+
# {Card::Set} module, giving it access to the set module DSL.
|
21
65
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
66
|
+
# These important Card::Set subclasses explain more about the DSL
|
67
|
+
#
|
68
|
+
# - {Format} introduces format blocks
|
69
|
+
# - {Format::AbstractFormat} covers {Format::AbstractFormat#view view} definitions
|
70
|
+
# - {Event::Api} explains {Event::Api#event event} definitions
|
71
|
+
#
|
72
|
+
# ### Loading set modules
|
73
|
+
#
|
74
|
+
# Whenever you fetch or instantiate a card, the card will automatically
|
75
|
+
# include code from all the set modules associated with sets of which it is a member.
|
25
76
|
#
|
26
77
|
# For example, say you have a Plaintext card named 'Philipp+address', and you have set
|
27
78
|
# files for the following sets:
|
28
79
|
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
80
|
+
# * all cards
|
81
|
+
# * all Plaintext cards
|
82
|
+
# * all cards ending in +address
|
32
83
|
#
|
33
|
-
# When you run
|
84
|
+
# When you run any of these:
|
34
85
|
#
|
35
|
-
# mycard = Card.fetch
|
86
|
+
# mycard = Card.fetch "Philipp+address"
|
87
|
+
# mycard = "Philipp+address".card
|
88
|
+
# mycard = ["Philipp", "address"].card
|
36
89
|
#
|
37
90
|
# ...then mycard will include the set modules associated with each of those sets in the
|
38
91
|
# above order.
|
39
92
|
#
|
40
|
-
# Note that the set module's filename connects it to the set, so both the set_pattern
|
41
|
-
# and the set_anchor must correspond to the codename of a card in the database to
|
42
|
-
# function correctly.
|
43
|
-
#
|
44
|
-
# A set module is "just ruby", but is generally quite concise because Card uses
|
45
|
-
# a) the set module's file location to autogenerate ruby module names and
|
46
|
-
# b) Card::Set to provide API for the most common set methods.
|
47
93
|
#
|
48
94
|
module Set
|
49
95
|
include Event::Api
|