Skip to content
Permalink
Browse files

adds section on saving messages to database using ecto changeset

  • Loading branch information...
nelsonic committed Jan 7, 2018
1 parent 6f0e357 commit 81bd9cad4493501609305773516cb4c42da96927
103 README.md
@@ -118,16 +118,109 @@ This will create a couple of files:<br />

And inform you that you need to copy-paste a piece of code into your app: <br />
```sh
Add the channel to your `lib/chat_web/channels/user_socket.ex` handler, for example:
Add the channel to your `/lib/chat_web/channels/user_socket.ex` handler, for example:
channel "chat_room:lobby", ChatWeb.ChatRoomChannel
```
Cope that line
Open the file called `lib/chat_web/channels/user_socket.ex`
and paste it
Copy that line,
Open the file called `/lib/chat_web/channels/user_socket.ex`
and paste it it


### 3. Start Server
### 4. Update Template File

Open the file:
`/lib/chat_web/templates/layout/app.html.eex`
and add the following code:



### 5. Import Scocket in App.js

Open:
`/assets/js/app.js`
and uncomment the line:
```js
import socket from "./socket"
```
with the line _uncommented_ our app will import the `socket.js` file
which will give us WebSocket functionality.


### 6. Generate Database Schema to Store Chat History

Run the following command in your terminal:
```sh
mix phx.gen.schema Message messages name:string message:string
```
You should see the following output:
```sh
* creating lib/chat/message.ex
* creating priv/repo/migrations/20180107074333_create_messages.exs
Remember to update your repository by running migrations:
$ mix ecto.migrate
```

Let's break down that command for clarity:
+ `mix phx.gen.schema` - the mix command to create a new schema (database table)
+ `Message` - the singular name for record in our messages "collection"
+ `messages` - the name of the collection (_or database table_)
+ `name:string` - the name of the person sending a message, stored as a `string`.
+ `message:string` - the message sent by the person, also stored as a `string`.

The `creating lib/chat/message.ex` file is the "schema"
for our Message database table.

And the `creating priv/repo/migrations/20180107074333_create_messages.exs` file
is the "_migration_" that _creates_ the database table in our chose database.

#### 6.1 Run the Ecto Migration

In your terminal run the following command to create the Message

```sh
mix ecto.migrate
```
You should see the following in your terminal:
```sh
Compiling 1 file (.ex)
Generated chat app
[info] == Running Chat.Repo.Migrations.CreateMessages.change/0 forward
[info] create table messages
[info] == Migrated in 0.0s
```

#### 6.2 Review the Messages Table Schema

If you open your PostgreSQL GUI (_we use `Postico`_)
you will see that the messages table has been created:

![messages-table-schema-postico](https://user-images.githubusercontent.com/194400/34839040-2c6fcd0e-f6f8-11e7-807f-eb5e81b4192b.png)


#### 7. Save Messages to Database

Open the `lib/chat_web/channels/chat_room_channel.ex` file
and inside the function `def handle_in("shout", payload, socket) do`
add the following line:
```elixir
Chat.Message.changeset(%Chat.Message{}, payload) |> Chat.Repo.insert
```

So that your function ends up looking like this:
```elixir
def handle_in("shout", payload, socket) do
Chat.Message.changeset(%Chat.Message{}, payload) |> Chat.Repo.insert
broadcast socket, "shout", payload
{:noreply, socket}
end
```



### X. Start Server

```sh
mix phx.server
@@ -1 +1,9 @@
/* This file is for your main application css. */
/* This file is for your main application css. */

#message-list {
border: 1px solid #000;
height: 500px;
padding: 10px;
overflow: scroll;
margin-bottom: 10px;
}
@@ -18,4 +18,35 @@ import "phoenix_html"
// Local files can be imported directly using relative
// paths "./socket" or full ones "web/static/js/socket".

// import socket from "./socket"
import socket from "./socket"

let channel = socket.channel('chat_room:lobby', {});
let list = $('#message-list');
let message = $('#msg');
let name = $('#name');

message.on('keypress', event => {
if (event.keyCode == 13) {
channel.push('shout', {
name: name.val(),
message: message.val()
});
message.val('');
}
});

channel.on('shout', payload => {
list.append(`<b>${payload.name || 'new_user'}:</b> ${payload.message}<br>`);
list.prop({
scrollTop: list.prop('scrollHeight')
});
});

channel
.join()
.receive('ok', resp => {
console.log('Joined successfully', resp);
})
.receive('error', resp => {
console.log('Unable to join', resp);
});
@@ -0,0 +1,20 @@
defmodule Chat.Message do
use Ecto.Schema
import Ecto.Changeset
alias Chat.Message


schema "messages" do
field :message, :string
field :name, :string

timestamps()
end

@doc false
def changeset(%Message{} = message, attrs) do
message
|> cast(attrs, [:name, :message])
|> validate_required([:name, :message])
end
end
@@ -18,6 +18,7 @@ defmodule ChatWeb.ChatRoomChannel do
# It is also common to receive messages from the client and
# broadcast to everyone in the current topic (chat_room:lobby).
def handle_in("shout", payload, socket) do
Chat.Message.changeset(%Chat.Message{}, payload) |> Chat.Repo.insert
broadcast socket, "shout", payload
{:noreply, socket}
end
@@ -30,6 +30,7 @@
</main>

</div> <!-- /container -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="<%= static_path(@conn, "/js/app.js") %>"></script>
</body>
</html>
@@ -1,36 +1,11 @@
<div class="jumbotron">
<h2><%= gettext "Welcome to %{name}!", name: "Phoenix" %></h2>
<p class="lead">A productive web framework that<br />does not compromise speed and maintainability.</p>
<div id='message-list' class='row'>
</div>

<div class="row marketing">
<div class="col-lg-6">
<h4>Resources</h4>
<ul>
<li>
<a href="http://phoenixframework.org/docs/overview">Guides</a>
</li>
<li>
<a href="https://hexdocs.pm/phoenix">Docs</a>
</li>
<li>
<a href="https://github.com/phoenixframework/phoenix">Source</a>
</li>
</ul>
<div class='row form-group'>
<div class='col-md-3'>
<input type='text' id='name' class='form-control' placeholder='Name' />
</div>

<div class="col-lg-6">
<h4>Help</h4>
<ul>
<li>
<a href="http://groups.google.com/group/phoenix-talk">Mailing list</a>
</li>
<li>
<a href="http://webchat.freenode.net/?channels=elixir-lang">#elixir-lang on freenode IRC</a>
</li>
<li>
<a href="https://twitter.com/elixirphoenix">@elixirphoenix</a>
</li>
</ul>
<div class='col-md-9'>
<input type='text' id='msg' class='form-control' placeholder='Message' />
</div>
</div>
@@ -0,0 +1,13 @@
defmodule Chat.Repo.Migrations.CreateMessages do
use Ecto.Migration

def change do
create table(:messages) do
add :name, :string
add :message, :string

timestamps()
end

end
end

0 comments on commit 81bd9ca

Please sign in to comment.
You can’t perform that action at this time.