From 1f94440e091b90a5b00b37b3d6ba11ea15d28f71 Mon Sep 17 00:00:00 2001 From: khintk Date: Fri, 13 Apr 2018 11:35:17 -0500 Subject: [PATCH 1/4] Removed the feature which allows user to edit --- elm-todo/Todo.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elm-todo/Todo.elm b/elm-todo/Todo.elm index 3a07b24..20e99f6 100755 --- a/elm-todo/Todo.elm +++ b/elm-todo/Todo.elm @@ -240,7 +240,7 @@ viewEntry todo = ] [] , label - [ onDoubleClick (EditingEntry todo.id True) ] + [ onDoubleClick (EditingEntry todo.id False) ] [ text todo.description ] , button [ class "destroy" From 585790c1388ae312803e42f0b129d24f0ff04028 Mon Sep 17 00:00:00 2001 From: khintk Date: Fri, 13 Apr 2018 16:21:45 -0500 Subject: [PATCH 2/4] Finished Part 0 of the homework --- elm-todo/Todo.elm | 28 ++++------------------------ ruby-todo/lib/model.rb | 4 ++-- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/elm-todo/Todo.elm b/elm-todo/Todo.elm index 20e99f6..d61b2d4 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,8 +224,8 @@ viewEntry todo = ] [] , label - [ onDoubleClick (EditingEntry todo.id False) ] - [ text todo.description ] + [] + [ text todo.description] , button [ class "destroy" , onClick (Delete todo.id) @@ -253,9 +237,6 @@ viewEntry todo = , value todo.description , name "title" , id ("todo-" ++ toString todo.id) - , onInput (UpdateEntry todo.id) - , onBlur (EditingEntry todo.id False) - , onEnter (EditingEntry todo.id False) ] [] ] @@ -313,8 +294,7 @@ viewControlsClear entriesCompleted = infoFooter : Html msg infoFooter = footer [ class "info" ] - [ p [] [ text "Double-click to edit a todo" ] - , p [] + [ p [] [ text "Written by " , a [ href "https://github.com/evancz" ] [ text "Evan Czaplicki" ] ] diff --git a/ruby-todo/lib/model.rb b/ruby-todo/lib/model.rb index 75a6085..e64ca6a 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? && @@ -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? && From 9d3fe57a14a21e9974e51ff0e880d70c5bb6711c Mon Sep 17 00:00:00 2001 From: khintk Date: Fri, 13 Apr 2018 18:12:49 -0500 Subject: [PATCH 3/4] Finished the part 1 of the homework, enjoyed creating new models in order to pass on the information from the previous model --- ruby-todo/lib/engine.rb | 9 +++++++-- ruby-todo/lib/messages.rb | 29 +++++++++++++++++------------ ruby-todo/test/todo_test.rb | 10 ++++++++-- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/ruby-todo/lib/engine.rb b/ruby-todo/lib/engine.rb index a257c20..05e79bd 100644 --- a/ruby-todo/lib/engine.rb +++ b/ruby-todo/lib/engine.rb @@ -5,8 +5,13 @@ def self.run(*args) def self.run_with_history(model, messages) messages.map do |msg| - msg.apply_to(model) - model + model = msg.apply_to(model) + end + + # [msg1, msg2, msg3] + # [model with msg1, model with msg2, model with msg3] + # [model with msg1, model with msg1, msg2, model with msg1, msg2, msg3] + end end diff --git a/ruby-todo/lib/messages.rb b/ruby-todo/lib/messages.rb index abe85de..fe83ea8 100644 --- a/ruby-todo/lib/messages.rb +++ b/ruby-todo/lib/messages.rb @@ -2,13 +2,13 @@ module Msg class Add def apply_to(model) + newEntries = model.entries.clone + unless model.new_entry_field.blank? - model.entries << Entry.new( - description: model.new_entry_field, - id: model.next_id) + newEntries << Entry.new(description: model.new_entry_field,id: model.next_id) end - model.next_id += 1 - model.new_entry_field = "" + + Model.new(new_entry_field: "", entries: newEntries, next_id: model.next_id + 1 ) end end @@ -20,7 +20,7 @@ def initialize(str) attr_reader :str def apply_to(model) - model.new_entry_field = str + Model.new(new_entry_field: str, entries: model.entries.clone, next_id: model.next_id ) end end @@ -30,13 +30,18 @@ def initialize(id, is_completed) end attr_reader :id, :is_completed - def apply_to(model) - model.entries.each do |entry| + # [1,2,3,4].map do |digit| + # digit + 1 + # end == [2,3,4,5] + + Model.new(new_entry_field: model.new_entry_field, entries: model.entries.clone, next_id: model.next_id, entries: model.entries.clone.map do |entry| if entry.id == id - entry.completed = is_completed + entry = Entry.new(id: id, description: entry.description, completed: is_completed) end + entry end + ) end end @@ -46,15 +51,15 @@ def initialize(id) end attr_reader :id - def apply_to(model) - model.entries.reject! { |e| e.id == id } + Model.new(new_entry_field: model.new_entry_field, next_id: model.next_id, entries: model.entries.clone.reject! { |e| e.id == id } + ) end end class DeleteAllCompleted def apply_to(model) - model.entries.reject!(&:completed) + Model.new(new_entry_field: model.new_entry_field, next_id: model.next_id, entries: model.entries.clone.reject!(&:completed)) end end diff --git a/ruby-todo/test/todo_test.rb b/ruby-todo/test/todo_test.rb index f7436c7..afaacaa 100644 --- a/ruby-todo/test/todo_test.rb +++ b/ruby-todo/test/todo_test.rb @@ -27,11 +27,17 @@ describe Msg::Add do it "appends a new entry" do + + # print model.inspect + # print "\n\n\n" + new_model = Engine.run(model, [ Msg::UpdateNewEntryField.new("hop on one foot"), Msg::Add.new ]) + # print new_model.inspect + # print "\n\n\n" assert_equal 3, new_model.entries.size new_entry = new_model.entries.last assert_equal 12, new_entry.id @@ -91,7 +97,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"), @@ -104,7 +110,7 @@ Msg::UpdateNewEntryField.new("go backward in time"), Msg::Add.new, Msg::Check.new(0, true), - Msg::Check.new(3, true), + Msg::Check.new(3, true), Msg::Check.new(3, false), Msg::DeleteAllCompleted.new ]) From 92ac5ea406d7abdf22ba63bee66fece97b49b061 Mon Sep 17 00:00:00 2001 From: khintk Date: Sat, 14 Apr 2018 01:05:57 -0500 Subject: [PATCH 4/4] Finished Part 2 and learned a ton about the imutability with struct --- ruby-todo/lib/messages.rb | 2 +- swift-todo/Sources/Todo/Engine.swift | 7 +++-- swift-todo/Sources/Todo/Message.swift | 36 ++++++++++++++++------ swift-todo/Sources/Todo/Model.swift | 4 +-- swift-todo/Tests/TodoTests/TodoTests.swift | 4 +-- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/ruby-todo/lib/messages.rb b/ruby-todo/lib/messages.rb index fe83ea8..84afbf7 100644 --- a/ruby-todo/lib/messages.rb +++ b/ruby-todo/lib/messages.rb @@ -35,7 +35,7 @@ def apply_to(model) # digit + 1 # end == [2,3,4,5] - Model.new(new_entry_field: model.new_entry_field, entries: model.entries.clone, next_id: model.next_id, entries: model.entries.clone.map do |entry| + Model.new(new_entry_field: model.new_entry_field, next_id: model.next_id, entries: model.entries.clone.map do |entry| if entry.id == id entry = Entry.new(id: id, description: entry.description, completed: is_completed) end diff --git a/swift-todo/Sources/Todo/Engine.swift b/swift-todo/Sources/Todo/Engine.swift index e3b14a7..bf23d8c 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] { + var oldModel = model return messages.map { message in - message.apply(to: model) - return model + oldModel = message.apply(to: oldModel) + return oldModel } } } + + diff --git a/swift-todo/Sources/Todo/Message.swift b/swift-todo/Sources/Todo/Message.swift index 92dd868..6c242e2 100644 --- a/swift-todo/Sources/Todo/Message.swift +++ b/swift-todo/Sources/Todo/Message.swift @@ -7,6 +7,17 @@ import Foundation +//array = [a,b,c] +// +//map (function) +//array: a -> function(a) -> x +// +// +//function = { y in +// +// return x +//} + enum Message { case add case updateNewEntryField(String) @@ -14,30 +25,37 @@ enum Message { case delete(Int) case deleteAllCompleted - func apply(to model: Model) { + func apply(to model: Model) -> Model { + var mutableModel = model + switch(self) { case .add: if !model.newEntryField.isBlank() { - model.entries.append(Entry(id: model.nextID, description: model.newEntryField)) + mutableModel.entries.append(Entry(id: model.nextID, description: model.newEntryField)) } - model.nextID += 1 - model.newEntryField = "" + + mutableModel.nextID += 1 + mutableModel.newEntryField = "" case .updateNewEntryField(let str): - model.newEntryField = str + mutableModel.newEntryField = str case .check(let id, let isCompleted): - for entry in model.entries { + mutableModel.entries = mutableModel.entries.map { entry in + var mutableEntry = entry if(entry.id == id) { - entry.completed = isCompleted + mutableEntry.id = id + mutableEntry.completed = isCompleted } + return mutableEntry } case .delete(let id): - model.entries.remove { $0.id == id } + mutableModel.entries.remove { $0.id == id } case .deleteAllCompleted: - model.entries.remove { $0.completed } + mutableModel.entries.remove { $0.completed } } + return mutableModel } } 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..7346f27 100644 --- a/swift-todo/Tests/TodoTests/TodoTests.swift +++ b/swift-todo/Tests/TodoTests/TodoTests.swift @@ -77,7 +77,7 @@ 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 +145,6 @@ class TodoTests: XCTestCase { XCTAssertEqual(expected, actual, "History mismatch at step \(index)") } } -*/ + }