Skip to content

Instantly share code, notes, and snippets.

@oneiros
Created October 12, 2018 07:37
Show Gist options
  • Save oneiros/0c5b5bd4a92978895f93c6562633e884 to your computer and use it in GitHub Desktop.
Save oneiros/0c5b5bd4a92978895f93c6562633e884 to your computer and use it in GitHub Desktop.
Lucky: Many-to-Many checkboxes
class Posts::Create < AdminAction
include TagParams
route do
PostForm.create(params, tag_ids: tag_ids) do |form, post|
if post
redirect to: Index
else
render NewPage, form: form
end
end
end
private def tag_ids
HTTP::Params.parse(request.body.to_s).fetch_all("post:tag_ids")
end
end
class Post < BaseModel
table :posts do
column title : String
column body : String
has_many taggings : Tagging
has_many tags : Tag, through: :taggings
end
end
class Tag < BaseModel
table :tags do
column name : String
has_many taggings : Tagging
has_many posts : Post, through: :taggings
end
end
class Tagging < BaseModel
table :taggings do
belongs_to post : Post
belongs_to tag : Tag
end
end
class Posts::NewPage < MainLayout
needs form : PostForm
def content
form_for Create do
field(form.title) do |title|
text_input title
end
field(form.body) do |body|
textarea body
end
tag_selection(form)
submit "Save"
end
end
private def tag_selection(form)
post = form.record
TagQuery.new.name.asc_order.each do |tag|
label do
if post.try { |p| p.tags.includes?(tag) }
input type: "checkbox", name: "post:tag_ids", value: tag.id.to_s, checked: "checked"
else
input type: "checkbox", name: "post:tag_ids", value: tag.id.to_s
end
text tag.name
end
end
end
end
class PostForm < Post::BaseForm
fillable title, body
needs tag_ids : Array(String)
after_save update_tags
def prepare
validate_required title
end
def update_tags(post)
LuckyRecord::Repo.run do |db|
ids_constraint = " AND tag_id NOT IN (#{tag_ids.join(", ")})" if tag_ids.any?
db.exec "DELETE FROM taggings WHERE post_id = #{post.id}#{ids_constraint}"
now = Time.utc_now
if tag_ids.any?
values_for_insert = tag_ids.map do |tag_id|
"(#{post.id}, #{tag_id}, '#{now}', '#{now}')"
end
db.exec "INSERT INTO taggings(post_id, tag_id, created_at, updated_at) VALUES #{values_for_insert.join(", ")} ON CONFLICT DO NOTHING"
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment