Module: Card::Model::SaveHelper

Included in:
Card::Migration
Defined in:
lib/card/model/save_helper.rb

Overview

API to create and update cards. It is intended as a helper for "external" scripts (seeding, testing, migrating, etc) and not for internal application code. The general pattern is: All methods use the ActiveRecord !-methods that throw exceptions if somethings fails. All !-methods in this module rename existing cards to resolve name conflicts)

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object



233
234
235
236
# File 'lib/card/model/save_helper.rb', line 233

def method_missing method, *args
  return super unless (cardtype_card = extract_cardtype_from_method_name method)
  Card.create! create_args(*args).merge(type_id: cardtype_card.id)
end

Instance Method Details

#add_coderule_item(name, prefix, type_id, to) ⇒ Object



213
214
215
216
217
218
219
220
# File 'lib/card/model/save_helper.rb', line 213

def add_coderule_item name, prefix, type_id, to
  codename = "#{prefix}_#{name.tr(' ', '_').underscore}"
  name = "#{prefix}: #{name}"

  ensure_card name, type_id: type_id,
              codename: codename
  Card[to].add_item! name
end

#add_name(name, content_or_args) ⇒ Object



163
164
165
166
167
168
169
# File 'lib/card/model/save_helper.rb', line 163

def add_name name, content_or_args
  if content_or_args.is_a?(String)
    { content: content_or_args, name: name }
  else
    content_or_args.reverse_merge name: name
  end
end

#add_script(name, opts = {}) ⇒ Object



203
204
205
206
207
208
209
210
# File 'lib/card/model/save_helper.rb', line 203

def add_script name, opts={}
  name.sub!(/^script\:?\s?/, '') # in case name is given with prefix
  # remove it so that we don't double it

  add_coderule_item name, "script",
                    opts[:type_id] || Card::CoffeeScriptID,
                    opts[:to] || "*all+*script"
end

#add_style(name, opts = {}) ⇒ Object



194
195
196
197
198
199
200
201
# File 'lib/card/model/save_helper.rb', line 194

def add_style name, opts={}
  name.sub!(/^style\:?\s?/, '') # in case name is given with prefix
  # remove it so that we don't double it

  add_coderule_item name, "style",
                    opts[:type_id] || Card::ScssID,
                    opts[:to] || "*all+*style"
end

#create_args(name_or_args, content_or_args = nil) ⇒ Object



153
154
155
156
157
# File 'lib/card/model/save_helper.rb', line 153

def create_args name_or_args, content_or_args=nil
  args = standardize_args name_or_args, content_or_args
  resolve_name_conflict args
  args
end

#create_card(name_or_args, content_or_args = nil) ⇒ Object Also known as: create



18
19
20
# File 'lib/card/model/save_helper.rb', line 18

def create_card name_or_args, content_or_args=nil
  Card.create! create_args(name_or_args, content_or_args)
end

#create_card!(name_or_args, content_or_args = nil) ⇒ Object Also known as: create!

if card with same name exists move it out of the way



120
121
122
123
# File 'lib/card/model/save_helper.rb', line 120

def create_card! name_or_args, content_or_args=nil
  args = standardize_args name_or_args, content_or_args
  create_card args.reverse_merge(rename_if_conflict: :old)
end

#create_or_update_card(name_or_args, content_or_args = nil) ⇒ Object Also known as: create_or_update



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/card/model/save_helper.rb', line 28

def create_or_update_card name_or_args, content_or_args=nil
  name = name_from_args name_or_args

  if Card[name]
    args = standardize_update_args name_or_args, content_or_args
    update_card(name, args)
  else
    args = standardize_args name_or_args, content_or_args
    create_card(args)
  end
end

#create_or_update_card!(name_or_args, content_or_args = nil) ⇒ Object Also known as: create_or_update!



130
131
132
133
# File 'lib/card/model/save_helper.rb', line 130

def create_or_update_card! name_or_args, content_or_args=nil
  args = standardize_args name_or_args, content_or_args
  create_or_update args.reverse_merge(rename_if_conflict: :new)
end

#delete_card(name) ⇒ Object Also known as: delete



40
41
42
43
# File 'lib/card/model/save_helper.rb', line 40

def delete_card name
  return unless (card = Card[name])
  card.delete!
end

#delete_code_card(name) ⇒ Object



45
46
47
48
# File 'lib/card/model/save_helper.rb', line 45

def delete_code_card name
  update name, codename: nil
  delete name
end

#ensure_attributes(card, args) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/card/model/save_helper.rb', line 177

def ensure_attributes card, args
  args = args.to_h.with_indifferent_access
  subcards = card.extract_subcard_args! args
  update_args =
    args.select do |key, value|
      if key =~ /^\+/
        subfields[key] = value
        false
      else
        card.send(key) != value
      end
    end
  return if update_args.empty? && subcards.empty?
  # FIXME: use ensure_attributes for subcards
  card.update_attributes! update_args.merge(subcards: subcards)
end

#ensure_card(name_or_args, content_or_args = nil) ⇒ Object Also known as: ensure

create if card doesn't exist updates existing card only if given attributes are different except the name

Examples:

if a card with name "under_score" exists

ensure_card "Under Score"                 # => no change
ensure_card "Under Score", type: :pointer # => changes the type to pointer
                                          #    but not the name


57
58
59
60
61
62
63
64
65
66
# File 'lib/card/model/save_helper.rb', line 57

def ensure_card name_or_args, content_or_args=nil
  args = standardize_args name_or_args, content_or_args
  name = args.delete(:name)
  if (card = Card[name])
    ensure_attributes card, args
    card
  else
    Card.create! args.merge(name: name)
  end
end

#ensure_card!(name_or_args, content_or_args = nil) ⇒ Object Also known as: ensure!

create if card doesn't exist updates existing card only if given attributes are different including the name For example if a card with name "under_score" exists then ensure_card "Under Score" renames it to "Under Score"



73
74
75
76
77
78
79
80
# File 'lib/card/model/save_helper.rb', line 73

def ensure_card! name_or_args, content_or_args=nil
  args = standardize_args name_or_args, content_or_args
  if (card = Card[args[:name]])
    ensure_attributes card, args
  else
    Card.create! args
  end
end

#ensure_trait(name, codename, args = {}) ⇒ Object

Creates or updates a trait card with codename and right rules. Content for rules that are pointer cards by default is converted to pointer format.

Examples:

ensure_trait "*a_or_b", :a_or_b,
             default: { type_id: Card::PointerID },
             options: ["A", "B"],
             input: "radio"


91
92
93
94
95
96
# File 'lib/card/model/save_helper.rb', line 91

def ensure_trait name, codename, args={}
  ensure_card name, codename: codename
  args.each do |setting, value|
    ensure_trait_rule name, setting, value
  end
end

#ensure_trait_rule(trait, setting, value) ⇒ Object



98
99
100
101
102
# File 'lib/card/model/save_helper.rb', line 98

def ensure_trait_rule trait, setting, value
  validate_setting setting
  card_args = normalize_trait_rule_args setting, value
  ensure_card [trait, :right, setting], card_args
end

#extract_cardtype_from_method_name(method) ⇒ Object



242
243
244
245
246
247
248
249
# File 'lib/card/model/save_helper.rb', line 242

def extract_cardtype_from_method_name method
  return unless method =~ /^create_(?<type>.+)$/
  cardtype_card = Card[Regexp.last_match[:type]] ||
                  Card[Regexp.last_match[:type].to_sym]
  return unless cardtype_card&.type_id == Card::CardtypeID ||
                cardtype_card.id == Card::SetID
  cardtype_card
end

#name_from_args(name_or_args) ⇒ Object



159
160
161
# File 'lib/card/model/save_helper.rb', line 159

def name_from_args name_or_args
  name_or_args.is_a?(Hash) ? name_or_args[:name] : name_or_args
end

#normalize_trait_rule_args(setting, value) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/card/model/save_helper.rb', line 111

def normalize_trait_rule_args setting, value
  return value if value.is_a? Hash
  if Card.fetch_type_id([setting, :right, :default]) == PointerID
    value = Array(value).to_pointer_content
  end
  { content: value }
end

#resolve_name_conflict(args) ⇒ Object



171
172
173
174
175
# File 'lib/card/model/save_helper.rb', line 171

def resolve_name_conflict args
  rename = args.delete :rename_if_conflict
  return unless args[:name] && rename
  args[:name] = Card.uniquify_name args[:name], rename
end

#respond_to_missing?(method, _include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


238
239
240
# File 'lib/card/model/save_helper.rb', line 238

def respond_to_missing? method, _include_private=false
  extract_cardtype_from_method_name(method) || super
end

#standardize_args(name_or_args, content_or_args) ⇒ Object

Returns args.

Returns:

  • args



136
137
138
139
140
141
142
# File 'lib/card/model/save_helper.rb', line 136

def standardize_args name_or_args, content_or_args
  if name_or_args.is_a?(Hash)
    name_or_args
  else
    add_name name_or_args, content_or_args || {}
  end
end

#standardize_update_args(name_or_args, content_or_args) ⇒ Object



144
145
146
147
148
149
150
151
# File 'lib/card/model/save_helper.rb', line 144

def standardize_update_args name_or_args, content_or_args
  return name_or_args if name_or_args.is_a?(Hash)
  if content_or_args.is_a?(String)
    { content: content_or_args }
  else
    content_or_args
  end
end

#update_card(name, content_or_args) ⇒ Object Also known as: update



22
23
24
25
26
# File 'lib/card/model/save_helper.rb', line 22

def update_card name, content_or_args
  args = standardize_update_args name, content_or_args
  resolve_name_conflict args
  Card[name].update_attributes! args
end

#update_card!(name, content_or_args) ⇒ Object Also known as: update!



125
126
127
128
# File 'lib/card/model/save_helper.rb', line 125

def update_card! name, content_or_args
  args = standardize_update_args name, content_or_args
  update_card name, args.reverse_merge(rename_if_conflict: :new)
end

#validate_setting(setting) ⇒ Object



104
105
106
107
108
109
# File 'lib/card/model/save_helper.rb', line 104

def validate_setting setting
  unless Card::Codename[setting] &&
         Card.fetch_type_id(setting) == SettingID
    raise ArgumentError, "not a valid setting: #{setting}"
  end
end

#with_user(user_name) ⇒ Object



12
13
14
15
16
# File 'lib/card/model/save_helper.rb', line 12

def with_user user_name
  Card::Auth.with current_id: Card.fetch_id(user_name) do
    yield
  end
end