0
votes

I'm using the standard (canonical?) Phoenix chat example to build something. But because I'm going to be handling the back-end only, I don't want to go through the trouble of wrestling with JavaScript on the client side. I'd like to test my room creation and broadcast over 3-4 terminal sessions, which will act as users.

So here's what I tried straightaway:

iex(2)> Rtc.RoomChannel.join("rooms:gossip", "hey!", {})
{:ok, {}}

Hmmm, that's weird. I was supposed to get back a socket. Wait a minute! Silly me, I just passed an empty tuple instead of a socket, and got it back. Which means I just need to pass a valid socket as the third parameter. Cool! . . .

But how to get a socket? I then remembered that we have something called the user_socket in the channels directory, so I tried something like this:

iex(5)> h MyApp.UserSocket.connect
@callback connect(params :: map(), Phoenix.Socket.t()) :: {:ok, Phoenix.Socket.t()} | :error 

Aha! Now I know how to create sockets. So let's create one:

iex(6)> MyApp.UserSocket.connect(%{}, Phoenix.Socket.t())
** (UndefinedFunctionError) undefined function Phoenix.Socket.t/0
    (phoenix) Phoenix.Socket.t()

And indeed, there's no t() function in the Phoenix.Socket module.

Where have I gone wrong? Is it even possible to create sockets like this, or am I doomed to have a JavaScript client?

1
I don't know if this will fix all the problems but the correct way to create a struct is not Foo.t() but %Foo{}, so in this case, try %Phoenix.Socket{}?Dogbert
@Dogbert Nice! That seems to generate a valid socket. I wonder how you deduced the correct data structure, given that the documentation itself says t(). Could you please explain that add both things as an answer? :-)ankush981

1 Answers

1
votes

You should take a look at Phoenix.Socket module.This is how connect/2 callback is defined:

...
alias Phoenix.Socket

@callback connect(params :: map, Socket.t) :: {:ok, Socket.t} | :error

...
  @type t :: %Socket{id: nil,
                     assigns: %{},
                     channel: atom,
                     channel_pid: pid,
                     endpoint: atom,
                     handler: atom,
                     joined: boolean,
                     pubsub_server: atom,
                     ref: term,
                     topic: String.t,
                     transport: atom,
                     transport_name: atom,
                     serializer: atom,
                     transport_pid: pid}

Typespecs

Remote types

Any module is also able to define its own types and the modules in Elixir are no exception. For example, the Range module defines a t type that represents a range: this type can be referred to as Range.t. In a similar fashion, a string is String.t, any enumerable can be Enum.t, and so on.