Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify the Broadcasting API #17

Merged
merged 10 commits into from
Apr 19, 2021
Merged

Simplify the Broadcasting API #17

merged 10 commits into from
Apr 19, 2021

Conversation

tonysm
Copy link
Collaborator

@tonysm tonysm commented Apr 11, 2021

Changed

  • This aggressively changes the broadcasting API to match the turbo-rails gem API. Now the Broacasts trait no longer automatically broadcasts all the changes. Models will have to specify either the $broadcasts property as a boolean/array or $broadcastsTo property as string/array or a broadcastsTo() method that should return either models or broadcasting channel instances
  • Consolidates all the Turbo Stream broadcasted events to a single one
  • Changes the custom echo tag to listen to the new event

Removed

  • Removes the old jobs and events since they were combined as a single job and a single event

Once merged, this will be the new API for broadcasting:

Manually broadcasting:

class Message extends Model
{
  use Broadcasts;
}

Using the trait will no longer broadcast model changes. Now, users can manually trigger the broadcasts whenever/wherever they want to, like so:

$message->broadcastAppend()->later();

They can do that in a controller (after the resource is created or update, for instance) or in model events, like so:

class Message extends Model
{
  use Broadcasts;

  public static function booted()
  {
    static::created(queue(function(Message $message) {
      $message->broadcastAppend();
    }));
  }
}

This will broadcast the new message whenever one is created. This way gives you way more control over the broadcasts.

Automatically Broadcasting

In some cases, you may want to broadcast all changes happening to a model. You may achieve so by specifying adding a $broadcasts = true property to the model:

class Message extends Model
{
  use Broadcasts;

  protected $broadcasts = true;
}

This will broadcast Turbo Streams whenever the model is created, updated, or deleted. It will happen via background jobs, so you don't have to wait for the messages to be sent to your WebSocket service.

By default, this will send new instances of models using the append action. If you want to control which action it should use, you may specify the property as an array and tell in an insertsBy key which action it should use:

class Message extends Model
{
  use Broadcasts;

  protected $broadcasts = [
    'insertsBy' => 'prepend',
  ];
}

This will still send all the model changes (created, updated, and deleted), and new entries will use the prepend action.

Using only the $broadcasts property will send the Turbo Stream broadcast messages to this model's channel. You may want to send the Turbo Stream messages to related models or even to custom broadcasting channels. You may achieve so with either the $broadcastsTo property or a broadcastsTo() method, such as:

class Message extends Model
{
  use Broadcasts;

  protected $broadcastsTo = [
    'chatRoom',
  ];

  public function chatRoom()
  {
    return $this->belongsTo(ChatRoom::class);
  }
}

// or using the method:

class Message extends Model
{
  use Broadcasts;

  public function chatRoom()
  {
    return $this->belongsTo(ChatRoom::class);
  }

  protected function broadcastsTo()
  {
    return [
      $this->chatRoom, // to a model
      new PrivateChannel('custom-channel'), // to a channel. Or both.
    ];
  }
}

You may combine the $broadcasts = ['insertsBy' => 'prepend'] and the broadcastsTo to control how you want the new entries to be delivered to the broadcasting channels.

TODO

  • Add tests for the new broadcasting event
  • Clean up the jobs and events not used anymore
  • Update documentation

issue #15
This will be a breaking change.

@tortuetorche
Copy link
Contributor

Hi Tony,

Do you plan to expand the TurboStreamResponseMacro parameters?
Like you explained in the RFC:

class ChannelMessagesController
{
  public function store(Channel $channel)
  {
    //...

    if (request()->wantsTurboStream()) {
      return response()->turboStream(
        $message,
        target: 'channel_messages', // optional, default to plural name of the model
        partial: 'messages._message', // optional, defaults to {resource}._{name}
        data: [/** Control the data */],
      );
    }
    
    return redirect()->route('channels.show', $channel);
  }

 //...
}

If it's in your plan, can you also add the action parameter, please?

Have a good day,
Tortue Torche

@tonysm
Copy link
Collaborator Author

tonysm commented Apr 16, 2021

Hey, @tortuetorche

Yeah, I'm going to work on that next. This PR is only for the broadcasting part.

@tonysm tonysm merged commit acf8b5c into main Apr 19, 2021
@tonysm tonysm deleted the refactor-broadcast branch April 19, 2021 00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants