Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 136 lines (110 sloc) 3.732 kB
ce50279 @cstorey Start working our way into the model.
authored
1 require 'hamsterdam'
3b5b6f8 @cstorey Show an answer when we hit "show answer".
authored
2 require 'hamster/queue'
3 require 'hamster/hash'
5936f5a @cstorey Have the DeckViewModel process ModelFieldAdded events.
authored
4 require 'hamster/vector'
e3607a2 @cstorey Add editable card view.
authored
5 require 'atomic'
ce50279 @cstorey Start working our way into the model.
authored
6
87ef0a5 @cstorey Initial revision of SRS app.
authored
7 module SRSRB
98037ea @cstorey Start splitting out view models by function.
authored
8 class CardEditorProjection
a07795c @cstorey Have the DeckViewModel listen for event store changes.
authored
9 def initialize event_store
10 self.event_store = event_store
88756ad @cstorey Use atomics pervasively in DeckViewModel, albeit mostly for the Atomi…
authored
11 self.cards = Atomic.new Hamster.hash
12 self._card_models = Atomic.new Hamster.hash
13 self._card_model_ids = Atomic.new Hamster.vector
14 self._card_model_id_by_card = Atomic.new Hamster.hash
e3607a2 @cstorey Add editable card view.
authored
15 self._editable_cards = Atomic.new(Hamster.hash)
a07795c @cstorey Have the DeckViewModel listen for event store changes.
authored
16 end
17
18 def start!
3809d5c @cstorey Refactor the event store interface to use a plain message send, not a…
authored
19 event_store.subscribe self
ce50279 @cstorey Start working our way into the model.
authored
20 end
3b5b6f8 @cstorey Show an answer when we hit "show answer".
authored
21
4dd3f6a @cstorey Update DeckViewModel#card_models when we get a ModelNamed event.
authored
22 def card_models
88756ad @cstorey Use atomics pervasively in DeckViewModel, albeit mostly for the Atomi…
authored
23 _card_model_ids.get
828587f @cstorey Modify the DeckViewModel card_model protocol to be marginally saner.
authored
24 end
25
26 def card_model id
88756ad @cstorey Use atomics pervasively in DeckViewModel, albeit mostly for the Atomi…
authored
27 _card_models.get.fetch(id)
4dd3f6a @cstorey Update DeckViewModel#card_models when we get a ModelNamed event.
authored
28 end
29
bf2dc9c @cstorey Add a system test for editing cards, and make some progress on it.
authored
30 def all_cards
88756ad @cstorey Use atomics pervasively in DeckViewModel, albeit mostly for the Atomi…
authored
31 cards.get.values
bf2dc9c @cstorey Add a system test for editing cards, and make some progress on it.
authored
32 end
33
e3607a2 @cstorey Add editable card view.
authored
34 def editable_card_for id
35 _editable_cards.get[id]
36 end
37
0d574bd @cstorey Emit versions when notifying event listeners of updates.
authored
38 def handle_event id, event, _version
dd37c86 @cstorey Make a start on adding cards.
authored
39 case event
3a6b69c @cstorey Teach the deck view about editing cards.
authored
40 when CardEdited then handle_card_edited id, event
4ca2991 @cstorey Get basic templating working. In drastic need of a cleanup though.
authored
41 when CardModelChanged then handle_card_model_changed id, event
4dd3f6a @cstorey Update DeckViewModel#card_models when we get a ModelNamed event.
authored
42 when ModelNamed then handle_model_named id, event
5936f5a @cstorey Have the DeckViewModel process ModelFieldAdded events.
authored
43 when ModelFieldAdded then handle_model_field_added id, event
4ca2991 @cstorey Get basic templating working. In drastic need of a cleanup though.
authored
44 when ModelTemplatesChanged then handle_model_templates_changed id, event
dd37c86 @cstorey Make a start on adding cards.
authored
45 end
46 end
47
98037ea @cstorey Start splitting out view models by function.
authored
48 def enqueue_card card
49 update_card(card.id) { card }
3c67534 @cstorey Deduplicate model updates in DeckViewModel.
authored
50 end
51
353cefc @cstorey Tidy card formatting and updating card state in DeckViewModel.
authored
52 def update_card id, &block
88756ad @cstorey Use atomics pervasively in DeckViewModel, albeit mostly for the Atomi…
authored
53 cards.update { |oldver|
54 oldver.fetch(id) { Card.new id: id }.
55 into { |old_card| block.call old_card }.
56 into { |new_card| oldver.put(id, new_card) }
57 }
353cefc @cstorey Tidy card formatting and updating card state in DeckViewModel.
authored
58 end
59
98037ea @cstorey Start splitting out view models by function.
authored
60 def card_for id
61 cards.get[id]
62 end
63
64 private
65 def handle_model_field_added id, event
66 update_model(id) { |old_model|
67 model = old_model || CardFormat.new(id: id)
68 model.set_fields model.fields.add(event.field)
69 }
70 end
71
3c67534 @cstorey Deduplicate model updates in DeckViewModel.
authored
72 def update_model id, &block
88756ad @cstorey Use atomics pervasively in DeckViewModel, albeit mostly for the Atomi…
authored
73 _card_models.update do |old_cards|
74 old_model = old_cards[id]
75 new_model = block.call old_model
76 old_cards.put id, new_model
77 end
3c67534 @cstorey Deduplicate model updates in DeckViewModel.
authored
78
88756ad @cstorey Use atomics pervasively in DeckViewModel, albeit mostly for the Atomi…
authored
79 _card_model_ids.update { |ids| ids.include?(id) ? ids : ids.add(id) }
4dd3f6a @cstorey Update DeckViewModel#card_models when we get a ModelNamed event.
authored
80 end
81
98037ea @cstorey Start splitting out view models by function.
authored
82 def handle_model_templates_changed id, event
83 update_model(id) { |model|
84 model ||= CardFormat.new id: id
85 model.set_question_template(event.question).set_answer_template(event.answer)
3c67534 @cstorey Deduplicate model updates in DeckViewModel.
authored
86 }
5936f5a @cstorey Have the DeckViewModel process ModelFieldAdded events.
authored
87 end
88
98037ea @cstorey Start splitting out view models by function.
authored
89 def handle_card_model_changed id, event
90 _card_model_id_by_card.update { |idx| idx.put(id, event.model_id) }
353cefc @cstorey Tidy card formatting and updating card state in DeckViewModel.
authored
91 end
92
98037ea @cstorey Start splitting out view models by function.
authored
93 def handle_card_edited id, event
94 model = model_for_card_id id
ce50279 @cstorey Start working our way into the model.
authored
95
98037ea @cstorey Start splitting out view models by function.
authored
96 question = model.format_question_with(event.card_fields)
97 answer = model.format_answer_with(event.card_fields)
98
99 update_card(id) { |card| card.set_question(question).set_answer(answer) }
100 _editable_cards.update { |oldver| oldver.put(id, EditableCard.new(id: id, fields: event.card_fields)) }
c2e3863 @cstorey Start sketching out how updates should work.
authored
101 end
e83313d @cstorey Ensure that the trigger for a card being updated in DeckViewModel is …
authored
102
98037ea @cstorey Start splitting out view models by function.
authored
103 def handle_model_named id, event
104 update_model(id) { |model| model ||= CardFormat.new(id: id); model.set_name(event.name) }
105 end
106
107 def model_for_card_id id
108 model_id = _card_model_id_by_card.get.fetch(id)
109 _card_models.get.find { |m| true }.last
e83313d @cstorey Ensure that the trigger for a card being updated in DeckViewModel is …
authored
110 end
e3607a2 @cstorey Add editable card view.
authored
111
98037ea @cstorey Start splitting out view models by function.
authored
112 attr_accessor :queue, :cards, :event_store, :_card_models, :_card_model_ids, :_card_model_id_by_card, :_editable_cards
113 end
114
e3607a2 @cstorey Add editable card view.
authored
115 class EditableCard < Hamsterdam::Struct.define(:id, :fields)
116 end
117
d1fddd0 @cstorey Rename CardModel → CardFormat.
authored
118 class CardFormat < Hamsterdam::Struct.define(:id, :name, :fields, :question_template, :answer_template)
5936f5a @cstorey Have the DeckViewModel process ModelFieldAdded events.
authored
119 def fields
120 super || Hamster.vector
121 end
353cefc @cstorey Tidy card formatting and updating card state in DeckViewModel.
authored
122
123 def format_question_with card_fields
124 format question_template, card_fields
125 end
126 def format_answer_with card_fields
127 format answer_template, card_fields
128 end
129
130 private
131 def format str, fields
132 str.gsub(/{{\s*(\w+)\s}}/) { |m| fields.fetch($1) }
133 end
4dd3f6a @cstorey Update DeckViewModel#card_models when we get a ModelNamed event.
authored
134 end
87ef0a5 @cstorey Initial revision of SRS app.
authored
135 end
Something went wrong with that request. Please try again.