Skip to content

Instantly share code, notes, and snippets.

@sylow
Last active February 27, 2017 03:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sylow/c42c5b4d87371974ce8ce087d3ff1687 to your computer and use it in GitHub Desktop.
Save sylow/c42c5b4d87371974ce8ce087d3ff1687 to your computer and use it in GitHub Desktop.
has_many :through in Rails with TB2
# --- model
class Announcement < ActiveRecord::Base
belongs_to :user
has_many :announcement_rooms, dependent: :delete_all
has_many :rooms, through: :announcement_rooms
end
# --- controller
def new
result = run Announcement::Create::Present
render html: cell(Announcement::Cell::Create, @form,
context: default_context(),
layout: School::Cell::Layout)
end
def create
run Announcement::Create do |op|
return redirect_to(teacher_announcements_path)
end
render html: cell(Announcement::Cell::Create, @form,
context: default_context(),
layout: School::Cell::Layout)
end
# --- contract
require "reform/form/dry"
module Announcement::Contract
class Create < Reform::Form
feature Reform::Form::Dry
property :text
validation :default do
required(:text).filled
end
collection :rooms,
skip_if: lambda { |fragment, *| fragment["selected"] == 'false' },
prepopulator: ->(options) {
self.rooms = Room.all
},
populator: ->(fragment:, **) {
unless item = Room.find_by(id: fragment["id"])
return skip!
end
if fragment["selected"] == "false"
rooms.delete(item)
return skip!
end
rooms.append(item)
} do
property :id
property :name
property :set, virtual: true
end
# ---Operation
class Announcement::Create < Trailblazer::Operation
class Present < Trailblazer::Operation
step Model( Announcement, :new )
step Policy::Pundit( AnnouncementPolicy, :create? )
step :assign_current_user!
step Contract::Build( constant: Announcement::Contract::Create )
step :prepopulate!
def prepopulate!(options)
options["contract.default"].prepopulate!
end
def assign_current_user!(options)
options["model"].user = options["current_user"]
end
end
step Nested( Present )
step Contract::Validate(key: "announcement")
failure Contract::Persist(method: :sync)
step Contract::Persist()
end
# ---- create.slim (form)
h3 Anons yaratma
= cell(School::Cell::Errors, model)
= form_for [:teacher, model], html: {class: 'ui form'} do |f|
.field
label
| Anons
= f.text_area :text
.inline.fields
label for='role' Sinifi
- f.fields_for :rooms do |room|
.field
.ui.checkbox.checkbox
= room.hidden_field :id
= room.check_box :selected, {checked: announcement.rooms.collect(&:id).include?(room.object.id)}, "true", "false"
label = room.object.name
input class="ui button" type="submit" value='Kaydet'
@sylow
Copy link
Author

sylow commented Feb 27, 2017

  • I want to show rooms as check boxes

But when validation fails after form submit, it is duplicating selected room checkboxes on the form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment