Files

117 lines
3.5 KiB
Ruby

# frozen_string_literal: true
class PostsController < ApplicationController
before_action :authenticate_member!, except: %i(index show)
before_action :find_post, only: %i(show edit update destroy)
load_and_authorize_resource except: %i(preview link_suggestions)
responders :flash
respond_to :html, :json
respond_to :rss, only: %i(index show)
def index
@author = Member.find_by!(slug: params[:member_slug]) if params[:member_slug].present?
@posts = posts
respond_with(@posts)
end
def show
respond_with(@post)
end
def new
@post = Post.new
@forum = Forum.find_by(id: params[:forum_id])
if params[:crop_id]
@crop = Crop.friendly.find(params[:crop_id])
@post.body = "[#{@crop.name}](crop)"
end
respond_with(@post)
end
def edit; end
# What the editor's "link to" list offers besides crops (which it gets from
# /crops/search.json): members, and the plantings of the member writing.
def link_suggestions
authorize! :create, Post
term = params[:term].to_s.strip
render json: { members: member_suggestions(term), plantings: planting_suggestions(term) }
end
# The body as it will look when posted, for the editor's Preview tab.
def preview
authorize! :create, Post
render partial: 'posts/body', formats: [:html], locals: { body: params[:body].to_s }
end
def create
params[:post][:author_id] = current_member.id
@post = Post.new(post_params)
flash[:notice] = t(@post.draft? ? 'posts.draft_saved' : 'posts.created') if @post.save
respond_with(@post)
end
def update
was_draft = @post.draft?
if @post.update(post_params)
flash[:notice] = t(was_draft && @post.published? ? 'posts.created' : 'posts.updated')
end
respond_with(@post)
end
def destroy
flash[:notice] = t('posts.deleted') if @post.destroy
respond_with(@post)
end
private
SUGGESTIONS = 5
def member_suggestions(term)
return [] if term.blank?
Member.kept.confirmed.where('login_name ILIKE ?', "#{Member.sanitize_sql_like(term)}%")
.order(:login_name).limit(SUGGESTIONS).map { |member| { name: member.login_name } }
end
def planting_suggestions(term)
return [] if term.blank?
like = "#{Planting.sanitize_sql_like(term)}%"
current_member.plantings.joins(:crop, :garden).includes(:crop, :garden)
.where('crops.name ILIKE :like OR gardens.name ILIKE :like', like:)
.order(created_at: :desc).limit(SUGGESTIONS)
.map { |planting| { slug: planting.slug, name: planting.to_s, crop: planting.crop.name } }
end
# A draft is only its author's: to anyone else it does not exist.
def find_post
@post = Post.with_drafts.includes(:author).find(params[:id])
raise ActiveRecord::RecordNotFound if @post.draft? && @post.author != current_member
end
def post_params
params.require(:post).permit(:body, :subject, :author_id, :forum_id, :card_photo_id, :draft)
end
# All of their own posts with drafts among them, or only the drafts.
def own_posts
return @author.posts unless @author == current_member
mine = Post.with_drafts.where(author: @author)
params[:drafts].present? ? mine.where(published_at: nil) : mine
end
def posts
if @author
# Members see their own drafts on their own page.
own_posts
else
Post
end.order(created_at: :desc)
.includes(:author, :crop_posts, :crops, comments: :author)
.paginate(page: params[:page], per_page: 12)
end
end