The project is in a healthy, maintained state
Image upload component for Funicular
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

>= 0.5.0
 Project Readme

Funicular Image Uploader

Image upload component for Funicular.

The plugin only owns the browser-side interaction: file selection, object URL preview, optional FormData upload, and display of the current image URL. The Rails app owns persistence. The same component works with a controller that stores bytes in SQLite or one that attaches the upload to Active Storage.

Install

group :funicular do
  gem "funicular-image-uploader"
end

Render plugin assets from the Rails layout:

<%= funicular_plugin_include_tags %>

Deferred upload with a profile form

Use on_select when an image should be submitted together with other form fields:

component(
  Funicular::Plugins::ImageUploader::Component,
  src: current_user.has_avatar ? "/users/#{current_user.id}/avatar" : nil,
  input_id: "avatar-input",
  file_field: "avatar",
  image_class: "profile-avatar-image",
  input_class: "profile-avatar-input",
  on_select: ->(file, preview_url) { @selected_avatar_file = file }
)

If no classes are supplied, the plugin's default CSS styles the file selector, clear button, and upload button. Applications can pass class props when they need to align the component with their own design system.

The parent component can then send its form data with Funicular::FileUpload.upload_with_formdata.

Standalone upload

Use auto_upload: true when the image has its own endpoint:

component(
  Funicular::Plugins::ImageUploader::Component,
  src: "/users/#{current_user.id}/avatar",
  upload_url: "/users/#{current_user.id}/avatar",
  file_field: "avatar",
  auto_upload: true,
  on_upload: ->(result) { puts "uploaded" },
  on_error: ->(message, result) { puts message }
)

The endpoint should return JSON. If it includes image_url, the component uses that URL after upload. Override the key with response_url_key: "url".

Active Storage endpoint example

class Users::AvatarsController < ApplicationController
  before_action :require_login

  def update
    current_user.avatar.attach(params[:avatar])
    render json: {
      image_url: rails_blob_path(current_user.avatar, only_path: true)
    }
  end
end
resource :avatar, only: [:update], controller: "users/avatars"

For direct SQLite storage, read params[:avatar] in the controller and return the URL that serves the stored bytes.