From 21b751f572061abbc24cfd4e66d09f108ec9345a Mon Sep 17 00:00:00 2001 From: cmolho Date: Tue, 10 Apr 2018 21:16:10 -0500 Subject: [PATCH 1/4] Completed Elm section --- elm-todo/Todo.elm | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/elm-todo/Todo.elm b/elm-todo/Todo.elm index 3a07b24..3a122f1 100755 --- a/elm-todo/Todo.elm +++ b/elm-todo/Todo.elm @@ -45,7 +45,6 @@ type alias Model = type alias Entry = { description : String , completed : Bool - , editing : Bool , id : Int } @@ -62,7 +61,6 @@ newEntry : String -> Int -> Entry newEntry desc id = { description = desc , completed = False - , editing = False , id = id } @@ -76,7 +74,6 @@ to them. -} type Msg = UpdateNewEntryField String - | EditingEntry Int Bool | UpdateEntry Int String | Add | Delete Int @@ -102,19 +99,6 @@ update msg model = UpdateNewEntryField str -> { model | newEntryField = str } - EditingEntry id isEditing -> - let - updateEntry t = - if t.id == id then - { t | editing = isEditing } - else - t - - focus = - Dom.focus ("todo-" ++ toString id) - in - { model | entries = List.map updateEntry model.entries } - UpdateEntry id task -> let updateEntry t = @@ -229,7 +213,7 @@ viewKeyedEntry todo = viewEntry : Entry -> Html Msg viewEntry todo = li - [ classList [ ( "completed", todo.completed ), ( "editing", todo.editing ) ] ] + [ classList [ ( "completed", todo.completed ) ] ] [ div [ class "view" ] [ input @@ -240,7 +224,7 @@ viewEntry todo = ] [] , label - [ onDoubleClick (EditingEntry todo.id True) ] + [] [ text todo.description ] , button [ class "destroy" @@ -248,16 +232,6 @@ viewEntry todo = ] [] ] - , input - [ class "edit" - , value todo.description - , name "title" - , id ("todo-" ++ toString todo.id) - , onInput (UpdateEntry todo.id) - , onBlur (EditingEntry todo.id False) - , onEnter (EditingEntry todo.id False) - ] - [] ] From 7f853197881e01b9739eae1ac4c86466af396e37 Mon Sep 17 00:00:00 2001 From: cmolho Date: Thu, 12 Apr 2018 22:10:24 -0500 Subject: [PATCH 2/4] almost finished ruby-todo --- ruby-todo/lib/engine.rb | 7 +++++-- ruby-todo/lib/messages.rb | 39 +++++++++++++++++++++++++++++-------- ruby-todo/lib/model.rb | 2 +- ruby-todo/test/todo_test.rb | 2 +- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/ruby-todo/lib/engine.rb b/ruby-todo/lib/engine.rb index a257c20..971f80c 100644 --- a/ruby-todo/lib/engine.rb +++ b/ruby-todo/lib/engine.rb @@ -4,9 +4,12 @@ def self.run(*args) end def self.run_with_history(model, messages) + model_history = [] + new_model = model messages.map do |msg| - msg.apply_to(model) - model + new_model = msg.apply_to(new_model) + model_history << new_model end + model_history end end diff --git a/ruby-todo/lib/messages.rb b/ruby-todo/lib/messages.rb index abe85de..9bf9def 100644 --- a/ruby-todo/lib/messages.rb +++ b/ruby-todo/lib/messages.rb @@ -2,13 +2,17 @@ module Msg class Add def apply_to(model) - unless model.new_entry_field.blank? - model.entries << Entry.new( + new_entries = model.entries + unless model.new_entry_field.blank? + new_entries << Entry.new( description: model.new_entry_field, id: model.next_id) end - model.next_id += 1 - model.new_entry_field = "" + new_model = Model.new( + entries: new_entries, + new_entry_field: "", + next_id: model.next_id + 1) + new_model end end @@ -20,7 +24,10 @@ def initialize(str) attr_reader :str def apply_to(model) - model.new_entry_field = str + new_model = Model.new( + entries: model.entries, + new_entry_field: str) + new_model end end @@ -32,11 +39,17 @@ def initialize(id, is_completed) attr_reader :id, :is_completed def apply_to(model) - model.entries.each do |entry| + model_entries = model.entries + model_entries.each do |entry| if entry.id == id entry.completed = is_completed end end + new_model = Model.new( + entries: model_entries, + new_entry_field: model.new_entry_field, + next_id: model.next_id) + new_model end end @@ -48,13 +61,23 @@ def initialize(id) attr_reader :id def apply_to(model) - model.entries.reject! { |e| e.id == id } + old_entries = model.entries + new_model = Model.new( + entries: old_entries.reject! { |e| e.id == id }, + new_entry_field: model.new_entry_field, + next_id: model.next_id) + new_model end end class DeleteAllCompleted def apply_to(model) - model.entries.reject!(&:completed) + old_entries = model.entries + new_model = Model.new( + entries: old_entries.reject!(&:completed), + new_entry_field: model.new_entry_field, + next_id: model.next_id) + new_model end end diff --git a/ruby-todo/lib/model.rb b/ruby-todo/lib/model.rb index 75a6085..bdfccc1 100644 --- a/ruby-todo/lib/model.rb +++ b/ruby-todo/lib/model.rb @@ -5,7 +5,7 @@ def initialize(entries: [], new_entry_field: "", next_id: nil) (entries.lazy.map(&:id).max || -1) + 1 end - attr_accessor :entries, :new_entry_field, :next_id + attr_reader :entries, :new_entry_field, :next_id def ==(other) !other.nil? && diff --git a/ruby-todo/test/todo_test.rb b/ruby-todo/test/todo_test.rb index f7436c7..d3351dc 100644 --- a/ruby-todo/test/todo_test.rb +++ b/ruby-todo/test/todo_test.rb @@ -91,7 +91,7 @@ end it "supports time travel" do - skip "Mutable model does not support time travel" + # skip "Mutable model does not support time travel" actual_history = Engine.run_with_history(Model.new, [ Msg::UpdateNewEntryField.new("go forward in time"), From 642375a0ada9bb40a553cc553d025ebea3e42c9b Mon Sep 17 00:00:00 2001 From: cmolho Date: Fri, 13 Apr 2018 17:45:36 -0500 Subject: [PATCH 3/4] finished swift --- swift-todo/Sources/Todo/Engine.swift | 9 +++-- swift-todo/Sources/Todo/Message.swift | 40 +++++++++++++++++----- swift-todo/Sources/Todo/Model.swift | 4 +-- swift-todo/Tests/TodoTests/TodoTests.swift | 2 -- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/swift-todo/Sources/Todo/Engine.swift b/swift-todo/Sources/Todo/Engine.swift index e3b14a7..ad7a4c9 100644 --- a/swift-todo/Sources/Todo/Engine.swift +++ b/swift-todo/Sources/Todo/Engine.swift @@ -13,9 +13,12 @@ struct Engine { } static func runWithHistory(on model: Model, applying messages: [Message]) -> [Model] { - return messages.map { message in - message.apply(to: model) - return model + var models: [Model] = [] + var new_model = model + for message in messages { + new_model = message.apply(to: new_model) + models.append(new_model) } + return models } } diff --git a/swift-todo/Sources/Todo/Message.swift b/swift-todo/Sources/Todo/Message.swift index 92dd868..057f5c8 100644 --- a/swift-todo/Sources/Todo/Message.swift +++ b/swift-todo/Sources/Todo/Message.swift @@ -14,30 +14,52 @@ enum Message { case delete(Int) case deleteAllCompleted - func apply(to model: Model) { + func apply(to model: Model) -> Model { switch(self) { case .add: if !model.newEntryField.isBlank() { - model.entries.append(Entry(id: model.nextID, description: model.newEntryField)) + return Model(nextID: model.nextID + 1, + newEntryField: "", + entries: model.entries + [Entry(id: model.nextID, + description: model.newEntryField)]) } - model.nextID += 1 - model.newEntryField = "" + return Model(nextID: model.nextID + 1, + newEntryField: "", + entries: model.entries) case .updateNewEntryField(let str): - model.newEntryField = str + return Model(nextID: model.nextID, + newEntryField: str, + entries: model.entries) case .check(let id, let isCompleted): - for entry in model.entries { + var model_entries = model.entries + for (index, entry) in model_entries.enumerated() { if(entry.id == id) { - entry.completed = isCompleted + let new_entry = Entry(id: entry.id, + description: entry.description, + completed: isCompleted) + model_entries[index] = new_entry + return Model(nextID: model.nextID, + newEntryField: model.newEntryField, + entries: model_entries) } } + return model case .delete(let id): - model.entries.remove { $0.id == id } + var model_entries = model.entries + model_entries.remove { $0.id == id } + return Model(nextID: model.nextID, + newEntryField: model.newEntryField, + entries: model_entries) case .deleteAllCompleted: - model.entries.remove { $0.completed } + var model_entries = model.entries + model_entries.remove { $0.completed } + return Model(nextID: model.nextID, + newEntryField: model.newEntryField, + entries: model_entries) } } } diff --git a/swift-todo/Sources/Todo/Model.swift b/swift-todo/Sources/Todo/Model.swift index 1cca801..d50d863 100644 --- a/swift-todo/Sources/Todo/Model.swift +++ b/swift-todo/Sources/Todo/Model.swift @@ -1,4 +1,4 @@ -class Model { +struct Model { var entries: [Entry] var newEntryField: String var nextID: Int @@ -11,7 +11,7 @@ class Model { } } -class Entry { +struct Entry { var id: Int var description: String var completed: Bool diff --git a/swift-todo/Tests/TodoTests/TodoTests.swift b/swift-todo/Tests/TodoTests/TodoTests.swift index 9220517..7c7539b 100644 --- a/swift-todo/Tests/TodoTests/TodoTests.swift +++ b/swift-todo/Tests/TodoTests/TodoTests.swift @@ -77,7 +77,6 @@ class TodoTests: XCTestCase { XCTAssertEqual([11], newModel.entries.map { $0.id }) } -/* func testTimeTravel() { let actualHistory = Engine.runWithHistory(on: Model(), applying: [ .updateNewEntryField("go forward in time"), @@ -145,6 +144,5 @@ class TodoTests: XCTestCase { XCTAssertEqual(expected, actual, "History mismatch at step \(index)") } } -*/ } From 88c2439a3a01d6b8ac5d4fc8ac8d107ecd5007fe Mon Sep 17 00:00:00 2001 From: cmolho Date: Fri, 13 Apr 2018 19:32:15 -0500 Subject: [PATCH 4/4] fixed ruby --- ruby-todo/lib/engine.rb | 6 +----- ruby-todo/lib/messages.rb | 45 ++++++++++++++++++++------------------- ruby-todo/lib/model.rb | 2 +- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/ruby-todo/lib/engine.rb b/ruby-todo/lib/engine.rb index 971f80c..7f7c38a 100644 --- a/ruby-todo/lib/engine.rb +++ b/ruby-todo/lib/engine.rb @@ -4,12 +4,8 @@ def self.run(*args) end def self.run_with_history(model, messages) - model_history = [] - new_model = model messages.map do |msg| - new_model = msg.apply_to(new_model) - model_history << new_model + model = msg.apply_to(model) end - model_history end end diff --git a/ruby-todo/lib/messages.rb b/ruby-todo/lib/messages.rb index 9bf9def..e558672 100644 --- a/ruby-todo/lib/messages.rb +++ b/ruby-todo/lib/messages.rb @@ -2,17 +2,16 @@ module Msg class Add def apply_to(model) - new_entries = model.entries + model_entries = model.entries.clone unless model.new_entry_field.blank? - new_entries << Entry.new( + model_entries << Entry.new( description: model.new_entry_field, id: model.next_id) end - new_model = Model.new( - entries: new_entries, + Model.new( + entries: model_entries, new_entry_field: "", next_id: model.next_id + 1) - new_model end end @@ -24,10 +23,10 @@ def initialize(str) attr_reader :str def apply_to(model) - new_model = Model.new( - entries: model.entries, - new_entry_field: str) - new_model + Model.new( + entries: model.entries.clone, + new_entry_field: str, + next_id: model.next_id) end end @@ -39,17 +38,19 @@ def initialize(id, is_completed) attr_reader :id, :is_completed def apply_to(model) - model_entries = model.entries - model_entries.each do |entry| + model_entries = model.entries.clone + model_entries.each.with_index do |entry, index| if entry.id == id - entry.completed = is_completed + model_entries[index] = Entry.new( + description: entry.description, + id: entry.id, + completed: is_completed) end end - new_model = Model.new( + Model.new( entries: model_entries, new_entry_field: model.new_entry_field, next_id: model.next_id) - new_model end end @@ -61,23 +62,23 @@ def initialize(id) attr_reader :id def apply_to(model) - old_entries = model.entries - new_model = Model.new( - entries: old_entries.reject! { |e| e.id == id }, + model_entries = model.entries.clone + model_entries.reject! { |e| e.id == id } + Model.new( + entries: model_entries, new_entry_field: model.new_entry_field, next_id: model.next_id) - new_model end end class DeleteAllCompleted def apply_to(model) - old_entries = model.entries - new_model = Model.new( - entries: old_entries.reject!(&:completed), + model_entries = model.entries.clone + model_entries.reject!(&:completed) + Model.new( + entries: model_entries, new_entry_field: model.new_entry_field, next_id: model.next_id) - new_model end end diff --git a/ruby-todo/lib/model.rb b/ruby-todo/lib/model.rb index bdfccc1..e64ca6a 100644 --- a/ruby-todo/lib/model.rb +++ b/ruby-todo/lib/model.rb @@ -20,7 +20,7 @@ def initialize(id:, description:, completed: false) @description, @id, @completed = description, id, completed end - attr_accessor :description, :completed, :id + attr_reader :description, :completed, :id def ==(other) !other.nil? &&