Module: Card::Machine
- Included in:
- Set::Right::Script, Set::Right::Style, Set::Type::CoffeeScript, Set::Type::Css, Set::Type::JavaScript, Set::Type::Skin
- Defined in:
- mod/machines/lib/card/machine.rb
Overview
What are Machines?
Machine and MachineInput together implement a kind of observer pattern. Machine processes a collection of input cards to generate an output card (a Set::Type::File card by default). If one of the input cards is changed the output card will be updated.
The classic example: A style card observes a collection of css and sccs card to generate a file card with a css file that contains the assembled compressed css.
Using Machines
Include the Machine module in the card set that is supposed to produce the output card. If the output card should be automatically updated when a input card is changed the input card has to be in a set that includes the MachineInput module.
The default machine:
- uses its item cards as input cards or the card itself if there are no item cards;
- can be changed by passing a block to collect_input_cards
- takes the raw view of the input cards to generate the output;
- can be changed by passing a block to machine_input (in the input card set)
- stores the output as a .txt file in the '+machine output' card;
- can be changed by passing a filetype and/or a block to store_machine_output
How does it work?
Machine cards have a '+machine input' and a '+machine output' card. The '+machine input' card is a pointer to all input cards. Including the MachineInput module creates an 'on: save' event that runs the machines of all cards that are linked to that card via the +machine input pointer.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
- .define_machine_events(host_class) ⇒ Object
- .define_machine_views(host_class) ⇒ Object
- .included(host_class) ⇒ Object
- .set_default_input_collection_method(host_class) ⇒ Object
- .set_default_input_preparation_method(host_class) ⇒ Object
- .set_default_machine_behaviour(host_class) ⇒ Object
- .set_default_output_storage_method(host_class) ⇒ Object
Instance Method Summary collapse
- #cache_output_part(input_card, output) ⇒ Object
- #ensure_machine_output ⇒ Object
- #fetch_cache_card(input_card, new = nil) ⇒ Object
- #input_item_cards ⇒ Object
- #lock ⇒ Object
- #lock! ⇒ Object
- #lock_cache_key ⇒ Object
- #locked? ⇒ Boolean
- #machine_output_path ⇒ Object
- #machine_output_url ⇒ Object
- #regenerate_machine_output ⇒ Object
- #reset_machine_output ⇒ Object
- #run_engine(input_card) ⇒ Object
- #run_machine(joint = "\n") ⇒ Object
- #unlock! ⇒ Object
- #update_input_card ⇒ Object
- #update_machine_output ⇒ Object
Class Method Details
.define_machine_events(host_class) ⇒ Object
75 76 77 78 79 80 81 |
# File 'mod/machines/lib/card/machine.rb', line 75 def define_machine_events host_class event_suffix = host_class.name.tr ":", "_" event_name = "reset_machine_output_#{event_suffix}".to_sym host_class.event event_name, after: :expire_related, on: :save do reset_machine_output end end |
.define_machine_views(host_class) ⇒ Object
83 84 85 86 87 88 89 |
# File 'mod/machines/lib/card/machine.rb', line 83 def define_machine_views host_class host_class.format do view :machine_output_url do |_args| machine_output_url end end end |
.included(host_class) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'mod/machines/lib/card/machine.rb', line 60 def included host_class host_class.extend(ClassMethods) host_class.output_config = { filetype: "txt" } # for compatibility with old migrations return unless Codename[:machine_output] host_class.card_accessor :machine_output, type: :file host_class.card_accessor :machine_input, type: :pointer set_default_machine_behaviour host_class define_machine_views host_class define_machine_events host_class end |
.set_default_input_collection_method(host_class) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'mod/machines/lib/card/machine.rb', line 118 def set_default_input_collection_method host_class host_class.collect_input_cards do # traverse through all levels of pointers and # collect all item cards as input items = [self] new_input = [] already_extended = {} # avoid loops loop_limit = 5 until items.empty? item = items.shift next if item.trash || already_extended[item.id].to_i > loop_limit if item.item_cards == [item] # no pointer card new_input << item else # item_cards instantiates non-existing cards # we don't want those items.insert(0, item.item_cards.reject(&:unknown?)) items.flatten! new_input << item if item != self && item.known? already_extended[item] = already_extended[item].to_i + 1 end end new_input end end |
.set_default_input_preparation_method(host_class) ⇒ Object
98 99 100 |
# File 'mod/machines/lib/card/machine.rb', line 98 def set_default_input_preparation_method host_class host_class.prepare_machine_input {} end |
.set_default_machine_behaviour(host_class) ⇒ Object
91 92 93 94 95 96 |
# File 'mod/machines/lib/card/machine.rb', line 91 def set_default_machine_behaviour host_class set_default_input_collection_method host_class set_default_input_preparation_method host_class set_default_output_storage_method host_class host_class.machine_engine { |input| input } end |
.set_default_output_storage_method(host_class) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'mod/machines/lib/card/machine.rb', line 102 def set_default_output_storage_method host_class host_class.store_machine_output do |output| filetype = host_class.output_config[:filetype] file = Tempfile.new [id.to_s, ".#{filetype}"] file.write output file.rewind Card::Auth.as_bot do p = machine_output_card p.file = file p.save! end file.close file.unlink end end |
Instance Method Details
#cache_output_part(input_card, output) ⇒ Object
176 177 178 179 180 181 |
# File 'mod/machines/lib/card/machine.rb', line 176 def cache_output_part input_card, output Auth.as_bot do cache_card = fetch_cache_card(input_card, true) cache_card.update_attributes! content: output end end |
#ensure_machine_output ⇒ Object
255 256 257 258 259 |
# File 'mod/machines/lib/card/machine.rb', line 255 def ensure_machine_output output = fetch trait: :machine_output return if output && output.selected_content_action_id update_machine_output end |
#fetch_cache_card(input_card, new = nil) ⇒ Object
171 172 173 174 |
# File 'mod/machines/lib/card/machine.rb', line 171 def fetch_cache_card input_card, new=nil new &&= { type_id: PlainTextID } Card.fetch input_card.name, name, :machine_cache, new: new end |
#input_item_cards ⇒ Object
240 241 242 |
# File 'mod/machines/lib/card/machine.rb', line 240 def input_item_cards machine_input_card.item_cards end |
#lock ⇒ Object
203 204 205 206 207 208 209 210 211 212 |
# File 'mod/machines/lib/card/machine.rb', line 203 def lock if ok?(:read) && !(was_already_locked = locked?) Auth.as_bot do lock! yield end end ensure unlock! unless was_already_locked end |
#lock! ⇒ Object
222 223 224 |
# File 'mod/machines/lib/card/machine.rb', line 222 def lock! Card.cache.write lock_cache_key, true end |
#lock_cache_key ⇒ Object
214 215 216 |
# File 'mod/machines/lib/card/machine.rb', line 214 def lock_cache_key "UPDATE-LOCK:#{key}" end |
#locked? ⇒ Boolean
218 219 220 |
# File 'mod/machines/lib/card/machine.rb', line 218 def locked? Card.cache.read lock_cache_key end |
#machine_output_path ⇒ Object
250 251 252 253 |
# File 'mod/machines/lib/card/machine.rb', line 250 def machine_output_path ensure_machine_output machine_output_card.file.path end |
#machine_output_url ⇒ Object
244 245 246 247 248 |
# File 'mod/machines/lib/card/machine.rb', line 244 def machine_output_url ensure_machine_output machine_output_card.file.url # (:default, timestamp: false) # to get rid of additional number in url end |
#regenerate_machine_output ⇒ Object
197 198 199 200 201 |
# File 'mod/machines/lib/card/machine.rb', line 197 def regenerate_machine_output lock do run_machine end end |
#reset_machine_output ⇒ Object
183 184 185 186 187 188 |
# File 'mod/machines/lib/card/machine.rb', line 183 def reset_machine_output Auth.as_bot do (moc = machine_output_card) && moc.real? && moc.delete! update_input_card end end |
#run_engine(input_card) ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'mod/machines/lib/card/machine.rb', line 155 def run_engine input_card return if input_card.is_a? Card::Set::Type::Pointer if (cached = fetch_cache_card(input_card)) return cached.content end input = if input_card.respond_to? :machine_input input_card.machine_input else input_card.format._render_raw end output = engine(input) cache_output_part input_card, output output end |
#run_machine(joint = "\n") ⇒ Object
146 147 148 149 150 151 152 153 |
# File 'mod/machines/lib/card/machine.rb', line 146 def run_machine joint="\n" before_engine output = input_item_cards.map do |input_card| run_engine input_card end.select(&:present?).join(joint) after_engine output end |
#unlock! ⇒ Object
226 227 228 |
# File 'mod/machines/lib/card/machine.rb', line 226 def unlock! Card.cache.write lock_cache_key, false end |
#update_input_card ⇒ Object
230 231 232 233 234 235 236 237 238 |
# File 'mod/machines/lib/card/machine.rb', line 230 def update_input_card if DirectorRegister.running_act? input_card = attach_subcard! machine_input_card input_card.content = "" engine_input.each { |input| input_card << input } else machine_input_card.items = engine_input end end |
#update_machine_output ⇒ Object
190 191 192 193 194 195 |
# File 'mod/machines/lib/card/machine.rb', line 190 def update_machine_output lock do update_input_card run_machine end end |