03-02-2022
Meta Stuff
Sort out bspwm desktops - gah! Zoom and slack are driving me insane, and I'm almost there -
Today's Foci
Focus 1
- Understand how Ruby classes work through Sinatra/web-frameworks
- Access classes and use them via the web-framework
Focus 2
- Clarify MVC
- Detailed explanation of MVC model?
Debugging the Web
Debugging steps
- Tighten the loop
- Get visibility
Follow the Flow
p output the model and controller variables where relevant
check test against view
run app
FILENAME && LINE
p params!
I managed to explain something in the workshop - I wound about a little, but apparently it helped a small number of people - so that's a small win for today.
Remember HTML FORMS
- method = post
- action = send post to url /some/url
Using Sinatra, the variable needs to be sent in via an instance variable
Right, before lunch, I'm gonna study the workshop code we looked at. It seems to implement selenium and RSpec and Capybara together in a clear, concise fashion. ( apart from the kword subject! agh! )
Flying Solo
huh - I'm working solo today. What do I do?
I didn't get too deep into the selenium/RS/Capybara understanding and file format - so I'm gonna look into that somewhat.
But first I need to debug this thing!
OOOO, I didn't need to use the
.to not_include
syntax
I only needed
.to_not include
whoops!
So in continue to debug this error, I have p'd everything out - it looks like its in the right place so why isn't it working?
time for internet dev tools!
Huh - the app itself appears to be working as intended.
...
some time later
Huzzah! We got there.
How did I get there.
I couldn't see anything was wrong immediately - it appears to function on the surface. Even the app works properly by using the tags ( at least when I used it )
So how did I solve this?
I followed the flow, explicitly, and p'd out every related variable I could find.
As I was doing this, I kept wondering why the array was empty? If it works, it shouldn't be empty! But it wasnt the PostManager.(private)array I was looking for.
It returns the post's array attribute, stored in the post's 'tags' instance variable
some_post = (title="Coffee in C18", content="Clever things", tags = ["coffee", "clever"])
the code was returning post.title - so the array is empty
That in itself is interesting because of Ruby being made in C where C strings are character-arrays with an end token '0/'.
I'm supposing this is because Ruby turns almost everything into an object?
solution
class PostManager
def self.instance
@instance ||= self.new
end
def initialize
@posts = []
end
def add_post(post)
@posts << post
end
def all_posts
@posts
end
def all_posts_by_tag(tag)
p '===== tag ====='
p tag
@posts.select do |post|
p '===== post ====='
p post
p '===== post title ====='
p post.title
p '===== post tags(s) ====='
p post.tags
# previously, post.title.include?(tag)
post.tags.include?(tag)
end
end
end
Pairing Challenge Solo
Right - I'm going to continue with the pairing challenge - or maybe even start again - hmm.
Yeah. I'm gonna try that!
First, the user stories
As two Players,
So we can play a personalised game of Battle,
We want to Start a fight by entering our Names and seeing them
As Player 1,
So I can see how close I am to winning
I want to see Player 2's Hit Points
As Player 1,
So I can win a game of Battle,
I want to attack Player 2, and I want to get a confirmation
As Player 1,
So I can start to win a game of Battle,
I want my attack to reduce Player 2's HP by 10
As two Players,
So we can continue our game of Battle,
We want to switch turns
As Player 1,
So I can see how close I am to losing,
I want to see my own hit points
As Player 1,
So I can lose a game of Battle,
I want Player 2 to attack me, and I want to get a confirmation
As Player 1,
So I can start to lose a game of Battle,
I want Player 2's attack to reduce my HP by 10
As a Player,
So I can Lose a game of Battle,
I want to see a 'Lose' message if I reach 0HP first
As a Player,
So I can play a suspenseful game of Battle,
I want all Attacks to deal a random amount of damage
As a lonely Player,
So I can keep my Battle skills up to scratch
I want to play a Computerised opponent
As a Player,
So I can enjoy a game of Battle with more variety,
I want to choose from a range of attacks I could make
As a Player,
So I can better enjoy a game of Battle,
I want some of my attacks to Paralyse an opponent (chance of losing their next attack)
As a Player,
So I can better enjoy a game of Battle,
I want one of my attacks to have a chance of Poisoning my Opponent (Opponent takes a small random amount of damage at the beginning of their turn)
As a Player,
So I can better enjoy a game of Battle,
I want to make an attack that has a chance of sending my Opponent to Sleep (Opponent definitely misses next turn)
As a Player,
So I can extend my joyous experience of Battle,
I want to have an attack that heals some of my Hit Points
As a Player,
So I can enjoy my game of Battle,
I want a sexy user interface
Diagram Modelling - OOP
Noun | Verb | Prop? |
---|---|---|
Game | start | |
show_health | ||
change_turn | ||
lose_game | ||
win_game | ||
Player | name | |
health | ||
attack | ||
confirm_hit | ||
confirm_struck | ||
paralyze | ||
posion | ||
sleep | ||
heal | ||
Computer | name | |
health | ||
attack | ||
UI |
Noun | Property or Owner? |
---|---|
Actions | Owned by |
---|---|
Actions | Property it Reads or Changes |
---|---|
Class | CLASSNAME |
---|---|
Properties (instance variables) | |
Actions (methods) |
Looks like I need to look into class Aggregation Composition and Association
-
Aggregates exist independently - they're mutually exclusive
- Two People can exist independent of one another
- Aggregation doesn;t link state together
- Nor is there a parent-child relationship
-
Composition imples strong dependency - they're mutually inclusive A person cannot exist without a head, or torso
-
Reflexive Association
- Fruit class, and Mango instance, and Apple instance - the Mango and Apple are implicitly linked because they're both a little fruity
-
Directed Association
- direction of flow within classes
- a server passes information to a client
-
Composite Aggregation
- a two way relationship between objects
- a whole/part relationship
- If the composite is deleted, all subsiduary parts are deleted also
- In a windowing system, a frame belongs to a window
-
Aggregation relationship
- an object of one class can access or own an object of another class
- a car needs a wheel - but a wheel doesn't need a car
Right, I've had a crack at a UML diagram for the above Classes of Game, Player, and even Computer - I'll see if I can get it into this page later. It even saves as an SVG by default!
Walkthrough!
I haven't learned TDD in web yet - properly - and I think this walkthrough will show me some of that. I'm going through the walkthrough and then rebuilding it in my fashion. That seems to make sense to me.
Create a Modular Sinatra app using rackup
setup the RSpec environment something like
ENV['RACK_ENV'] = 'test'
# require our Sinatra app file
require File.join(File.dirname(__FILE__), '..', 'app.rb')
require 'capybara'
require 'capybara/rspec'
require 'rspec'
# tell Capybara about our app class
Capybara.app = SomeApp
set up a ./spec/features directory for the capybara testing
with capybara, use
feature 'with this feature' do
scenario 'do this thing' do
DO THE THING ( LOGIC )
end
end
When testing capybara:
What does the User do?
What does the User see?
use post when changing the server state
use capybara
don't render directly from POST
POST/redirect/GET
POST '/some/route'
...
LOGIC FOR DATA
...
redirect '/some/other/route'
GET 'some/other/route'
...
LOGIC / VIEW
...
To store short-term data on a server, use a session. Store the name of a used across multiple requests
save_and_open_page # saves and opens a browser to display the page