class MaterialsController < ApplicationController def index page = (params[:page].presence || 1).to_i limit = (params[:limit].presence || 20).to_i page = 1 if page < 1 limit = 1 if limit < 1 offset = (page - 1) * limit tag_id = params[:tag_id].presence parent_id = params[:parent_id].presence q = Material.includes(:tag, :created_by_user).with_attached_file q = q.where(tag_id:) if tag_id q = q.where(parent_id:) if parent_id count = q.count materials = q.order(created_at: :desc, id: :desc).limit(limit).offset(offset) render json: { materials: materials.map { |m| material_json(m) }, count: count } end def show material = Material .includes(:tag) .with_attached_file .find_by(id: params[:id]) return head :not_found unless material render json: material.as_json(methods: [:content_type]).merge( file: if material.file.attached? rails_storage_proxy_url(material.file, only_path: false) end, tag: TagRepr.base(material.tag)) end def create return head :unauthorized unless current_user tag_name_raw = params[:tag].to_s.strip file = params[:file] url = params[:url].to_s.strip.presence return head :bad_request if tag_name_raw.blank? || (file.blank? && url.blank?) tag_name = TagName.find_undiscard_or_create_by!(name: tag_name_raw) tag = tag_name.tag tag = Tag.create!(tag_name:, category: :material) unless tag material = Material.new(tag:, url:, created_by_user: current_user, updated_by_user: current_user) material.file.attach(file) if material.save render json: material_json(material), status: :created else render json: { errors: material.errors.full_messages }, status: :unprocessable_entity end end def update return head :unauthorized unless current_user return head :forbidden unless current_user.gte_member? material = Material.with_attached_file.find_by(id: params[:id]) return head :not_found unless material tag_name_raw = params[:tag].to_s.strip file = params[:file] url = params[:url].to_s.strip.presence return head :bad_request if tag_name_raw.blank? || (file.blank? && url.blank?) tag_name = TagName.find_undiscard_or_create_by!(name: tag_name_raw) tag = tag_name.tag tag = Tag.create!(tag_name:, category: :material) unless tag material.update!(tag:, url:, updated_by_user: current_user) if file material.file.attach(file) else material.file.purge(file) end if material.save render json: material.as_json(methods: [:content_type]).merge( file: if material.file.attached? rails_storage_proxy_url(material.file, only_path: false) end, tag: TagRepr.base(material.tag)) else render json: { errors: material.errors.full_messages }, status: :unprocessable_entity end end def destroy return head :unauthorized unless current_user return head :forbidden unless current_user.gte_member? material = Material.find_by(id: params[:id]) return head :not_found unless material material.discard head :no_content end private def material_json(material) MaterialRepr.base(material).merge( 'filename' => material.file.attached? ? material.file.filename.to_s : nil, 'byte_size' => material.file.attached? ? material.file.byte_size : nil, 'content_type' => material.file.attached? ? material.file.content_type : nil, 'url' => material.file.attached? ? url_for(material.file) : nil ) end end