Skip to content

Commit

Permalink
Update docs and add tag system (#674)
Browse files Browse the repository at this point in the history
  • Loading branch information
meatball133 authored Aug 7, 2024
1 parent 3b17de2 commit d356328
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 98 deletions.
53 changes: 27 additions & 26 deletions concepts/modules/about.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Modules

[Modules][modules] in Crystal serve 2 purposes:
[Modules][modules] in Crystal serve two purposes:

The first purpose is to create a [namespace][namespace] to avoid name collisions.
But it also forms as a form of grouping code together, this is to make it easier to understand what the code is for.
However, it also groups code, making it easier to understand what the code is for.

The second purpose is to define [mixins][mixin] to share code to types.

Modules have similarities to classes, but the main difference is that modules cannot be instantiated, and thereby don't have instance variables.
Modules are similar to classes, but the main difference is that they cannot be instantiated and, thus, don't have instance variables.

To declare a module you use the `module` keyword followed by the name of the module.
To declare a module, you use the `module` keyword followed by the module's name.

```crystal
module Foo
Expand All @@ -18,41 +18,42 @@ end

## Namespace

A namespace is a way to group code together, this is to avoid name clashes, but also to make it easier to understand what the code is for.
When wanting to access for example a constant or a class that has been placed inside a namespace you use the `::` operator.
A namespace is a way to group code.
This avoids name clashes and makes it easier to understand what the code is for.
When wanting to access a constant or a class that has been placed inside a namespace, you use the `::` operator.

```crystal
module Foo
class Bar
end
  class Bar
  end
end
Foo::Bar.new
```

## Use it as a mixin

This can be useful when, for example, wanting multiple classes to have the same "base" functionality or when wanting to share code between classes that are not related.
This can be useful when, for example, multiple classes need the same "base" functionality or when code needs to be shared between unrelated classes.
Or when wanting to share code between classes that are not related.

There are 2 different ways to use a module as a mixin: the first one is to use the `include` keyword, the second one is to use the `extend` keyword.
There are two different ways to use a module as a mixin: the first is to use the `include` keyword, and the second is to use the `extend` keyword.

Both methods will make constants available to the type that includes or extends the module.

### Include

Include will make all methods in the module available as instance methods on the type that includes the module.
The `include` keyword should be written at the top of the type, followed by the name of the module.
The `include` keyword should be at the top of the type, followed by the module's name.

```crystal
module Foo
def foo
"foo"
end
  def foo
    "foo"
  end
end
class Bar
include Foo
  include Foo
end
Bar.new.foo # => "foo"
Expand All @@ -61,36 +62,36 @@ Bar.new.foo # => "foo"
### Extend

Extend works similarly to include, but instead of making the methods available as instance methods, it makes them available as class methods.
The `extend` keyword should be written at the top of the type followed by the name of the module.
The `extend` keyword should be written at the top of the type, followed by the module's name.

```crystal
module Foo
def foo
"foo"
end
  def foo
    "foo"
  end
end
class Bar
extend Foo
  extend Foo
end
Bar.foo # => "foo"
```

## Extend self

A quite common pattern in Crystal is to use the [`extend self`][extend self] pattern, in a module.
A typical pattern in Crystal uses the [`extend self`][extend self] pattern in a module.
This will make all methods in the module available as class methods on the module itself.
This means you don't have to assign each method to the module itself using the `def self.method_name` syntax.
This means you don't have to assign each method to the module using the `def self.method_name` syntax.


```crystal
module Foo
extend self
  extend self
def foo
"foo"
end
  def foo
    "foo"
  end
end
Foo.foo # => "foo"
Expand Down
53 changes: 27 additions & 26 deletions concepts/modules/introduction.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Modules

[Modules][modules] in Crystal serve 2 purposes:
[Modules][modules] in Crystal serve two purposes:

The first purpose is to create a [namespace][namespace] to avoid name collisions.
But it also forms as a form of grouping code together, this is to make it easier to understand what the code is for.
However, it also groups code, making it easier to understand what the code is for.

The second purpose is to define [mixins][mixin] to share code to types.

Modules have similarities to classes, but the main difference is that modules cannot be instantiated, and thereby don't have instance variables.
Modules are similar to classes, but the main difference is that they cannot be instantiated and, thus, don't have instance variables.

To declare a module you use the `module` keyword followed by the name of the module.
To declare a module, you use the `module` keyword followed by the module's name.

```crystal
module Foo
Expand All @@ -18,41 +18,42 @@ end

## Namespace

A namespace is a way to group code together, this is to avoid name clashes, but also to make it easier to understand what the code is for.
When wanting to access for example a constant or a class that has been placed inside a namespace you use the `::` operator.
A namespace is a way to group code.
This avoids name clashes and makes it easier to understand what the code is for.
When wanting to access a constant or a class that has been placed inside a namespace, you use the `::` operator.

```crystal
module Foo
class Bar
end
  class Bar
  end
end
Foo::Bar.new
```

## Use it as a mixin

This can be useful when, for example, wanting multiple classes to have the same "base" functionality or when wanting to share code between classes that are not related.
This can be useful when, for example, multiple classes need the same "base" functionality or when code needs to be shared between unrelated classes.
Or when wanting to share code between classes that are not related.

There are 2 different ways to use a module as a mixin: the first one is to use the `include` keyword, the second one is to use the `extend` keyword.
There are two different ways to use a module as a mixin: the first is to use the `include` keyword, and the second is to use the `extend` keyword.

Both methods will make constants available to the type that includes or extends the module.

### Include

Include will make all methods in the module available as instance methods on the type that includes the module.
The `include` keyword should be written at the top of the type, followed by the name of the module.
The `include` keyword should be at the top of the type, followed by the module's name.

```crystal
module Foo
def foo
"foo"
end
  def foo
    "foo"
  end
end
class Bar
include Foo
  include Foo
end
Bar.new.foo # => "foo"
Expand All @@ -61,36 +62,36 @@ Bar.new.foo # => "foo"
### Extend

Extend works similarly to include, but instead of making the methods available as instance methods, it makes them available as class methods.
The `extend` keyword should be written at the top of the type followed by the name of the module.
The `extend` keyword should be written at the top of the type, followed by the module's name.

```crystal
module Foo
def foo
"foo"
end
  def foo
    "foo"
  end
end
class Bar
extend Foo
  extend Foo
end
Bar.foo # => "foo"
```

## Extend self

A quite common pattern in Crystal is to use the [`extend self`][extend self] pattern, in a module.
A typical pattern in Crystal uses the [`extend self`][extend self] pattern in a module.
This will make all methods in the module available as class methods on the module itself.
This means you don't have to assign each method to the module itself using the `def self.method_name` syntax.
This means you don't have to assign each method to the module using the `def self.method_name` syntax.


```crystal
module Foo
extend self
  extend self
def foo
"foo"
end
  def foo
    "foo"
  end
end
Foo.foo # => "foo"
Expand Down
32 changes: 16 additions & 16 deletions exercises/concept/bellebrook-basket-league/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# Instructions

Bellebrook basketball league is a league of multiple teams, each with a roster of players.
Bellebrook Basketball League is a league of multiple teams, each with a roster of players.
A new season is about to start, and they need to create a new ticketing system to sell tickets for the games.
Last season they sold tickets at the entrance of the stadium, but popularity has exploded and they have decided to sell tickets online this season to handle the increased demand.
Last season, they sold tickets at the stadium's entrance, but popularity has exploded, and they have decided to sell tickets online this season to handle the increased demand.

The league has contacted you and asked you to create a system that can handle the ticket sales.
The league has contacted you and asked you to create a system to handle ticket sales.

## 1. Create a ticketing system

First, you need to create a ticketing system that can handle the ticket sales.
The ticketing system has to tell how many tickets are available for a given game.
First, you need to create a ticketing system to handle ticket sales.
The ticketing system needs to tell how many tickets are available for a game.

For each game an instance of a class called `TicketSystem` should be created.
An instance of a class called `TicketSystem` should be created for each game.
The initialized state should hold the following information:

1. How many tickets there are available for the game.
2. Which stadium the game is played at.

Construct an initialized state from arguments indicating the amount of tickets available and which stadium the match is played at.
Construct an initialized state from arguments indicating the number of tickets available and which stadium the match is played at.
The initialized state should consist of the instance variables `@tickets_available` and `@stadium`.
These should contain the first and second arguments given, respectively.

Expand All @@ -30,10 +30,10 @@ TicketSystem.new(100, "Bellebrook")

First, you need to create a method that returns the amount of tickets available for a given game.

Define a module with the name `TicketingReservation` above the already defined class.
Define a module named `TicketingReservation` above the already defined class.
This module should be included in the `TicketSystem` class.

Inside the module define a method called `tickets_available`.
Inside the module, define a method called `tickets_available`.
This method should return the amount of tickets available.

```crystal
Expand All @@ -44,13 +44,13 @@ ticket_system.tickets_available

## 3. Order tickets

You must create a method that checks if there is tickets available for a given game.
You must create a method that checks if tickets are available for a given game.
The game needs to have 100 tickets in reserve.
This is to make sure that there are always tickets available for the people who buy tickets at the entrance of the stadium.
This is to ensure that there are always tickets available for the people who buy tickets at the stadium entrance.

Inside the module `TicketingReservation`, define a method called `order_ticket?`.
The method should return `true` if there are at least 100 tickets available and `false` otherwise.
If there are at least 100 tickets available, the method should also decrease the amount of tickets available by 1.
The method should return `true` if at least 100 tickets are available and `false` otherwise.
If at least 100 tickets are available, the method should also decrease the number of tickets available by 1.

```crystal
ticket_system = TicketSystem.new(100)
Expand All @@ -60,16 +60,16 @@ ticket_system.order_ticket?

## 4. Order message

The ticketing system has to have easy to understand messages for the users.
The ticketing system has to have messages that are easy for users to understand.
And the messages should feel personal, so they should include the user's name.

If the ticket purchase was successful, the user should get a message telling them that the purchase was successful, their ticket number, and which stadium the game is played at.
The ticket number should be the number of tickets available before the order.

If the purchase was successful, the message should look like this: `{name}, your purchase was successful, your ticket number is #{ticket_number}, and the game is played at the {stadium_number} stadium.`.
If the purchase was unsuccessful, the message should look like this: `{name}, your purchase was unsuccessful, there are not enough tickets available.`.
If the purchase was unsuccessful, the message should look like this: `{name}, your purchase was unsuccessful, and there are not enough tickets available.`.

Inside the module `TicketingReservation`, define a method called `order_message` that takes an argument `name` that holds the purchaser's name.
Inside the module `TicketingReservation,` define a method called `order_message` that takes an argument `name` containing the purchaser's name.
The method should return a string with the message.

```crystal
Expand Down
Loading

0 comments on commit d356328

Please sign in to comment.