class Recipe < ApplicationRecord
has_many :ingredients, inverse_of: :recipe, dependent: :destroy
accepts_nested_attributes_for :ingredients,
allow_destroy: true,
reject_if: :all_blank
<%# Subscribe every viewer of this post to its broadcasts %>
<%= turbo_stream_from @post %>
<%# Update the acting user's button to reflect the toggle %>
<%= turbo_stream.replace dom_id(@post, :like_button) do %>
<%= render "posts/like_button", post: @post %>
<div class="bookmarks">
<h1>Saved Bookmarks</h1>
<table>
<tbody id="bookmarks">
<%= render partial: "bookmark", collection: @bookmarks %>
module TurboResponder
extend ActiveSupport::Concern
private
def respond_with_turbo(resource, on_success:, partial:, notice: nil)
class SubscriptionsController < ApplicationController
before_action :set_subscription, only: %i[show destroy]
def new
@subscription = Subscription.new
end
module LayoutlessTurboFrame
extend ActiveSupport::Concern
included do
layout :layout_for_turbo
end
module TimeAgoHelper
def time_ago_tag(time, locale: I18n.locale, **options)
return if time.blank?
time = time.to_time
fallback = l(time, format: :short)
<!DOCTYPE html>
<html>
<head>
<title><%= content_for(:title) || "App" %></title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= form_with model: @document, data: { controller: "upload" } do |form| %>
<div class="field">
<%= form.label :file, "Attach a document" %>
<%= form.file_field :file,
direct_upload: true,
data: { upload_target: "input" } %>
class Comment < ApplicationRecord
belongs_to :post
belongs_to :author, class_name: "User"
has_rich_text :body
<%= turbo_stream_from [current_member, :notifications] %>
<div id="notification_badge">
<%= render 'notifications/badge', count: current_member.notifications.unread.count %>
</div>
class TasksController < ApplicationController
def destroy
@task = Task.find(params[:id])
@task.destroy!
respond_to do |format|