├── .gitignore ├── .travis.yml ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── app └── controller │ └── redactor2_rails │ ├── files_controller.rb │ └── images_controller.rb ├── bin ├── console └── setup ├── config └── routes.rb ├── lib ├── generators │ └── redactor2 │ │ ├── config_generator.rb │ │ ├── install_generator.rb │ │ └── templates │ │ ├── active_record │ │ └── carrierwave │ │ │ ├── devise_migration.rb │ │ │ ├── migration.rb │ │ │ └── redactor2 │ │ │ ├── asset.rb │ │ │ ├── file.rb │ │ │ └── image.rb │ │ ├── base │ │ └── carrierwave │ │ │ └── uploaders │ │ │ ├── redactor2_rails_file_uploader.rb │ │ │ └── redactor2_rails_image_uploader.rb │ │ ├── config.js │ │ └── mongoid │ │ └── carrierwave │ │ └── redactor2 │ │ ├── asset.rb │ │ ├── file.rb │ │ └── image.rb ├── redactor2_rails.rb └── redactor2_rails │ ├── backend │ └── carrierwave.rb │ ├── devise.rb │ ├── engine.rb │ ├── http.rb │ ├── orm │ ├── active_record.rb │ ├── base.rb │ └── mongoid.rb │ └── version.rb ├── redactor2_rails.gemspec └── vendor └── assets └── javascripts └── redactor2_rails ├── config.js └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.2.3 4 | before_install: gem install bundler -v 1.10.6 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in redactor2_rails.gemspec 4 | gemspec 5 | gem 'rails', '>= 3.2' 6 | 7 | platforms :ruby do 8 | group :active_record do 9 | gem 'carrierwave' 10 | gem 'mini_magick' 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Oleg Sulyanov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Imperavi Redactor for Rails 3.x - 4 Asset Pipeline 2 | 3 | redactor2_rails integrates Imperavi Redactor for Rails Asset Pipeline (Rails 4, 3.x versions are supported) 4 | 5 | [![Gem Version](https://badge.fury.io/rb/redactor2_rails.svg)](https://badge.fury.io/rb/redactor2_rails) 6 | 7 | In order to use this gem, you must purchase a license from Imperavi 8 | (https://imperavi.com/redactor/buy), download Redactor II files from them, 9 | and place redactor.js file in the following location: 10 | 11 | `app/assets/javascripts/` 12 | 13 | And redactor.css file in the following location: 14 | 15 | `app/assets/stylesheets/` 16 | 17 | ## Installation 18 | 19 | Add this line to your application's Gemfile: 20 | 21 | gem 'redactor2_rails' 22 | 23 | And then execute: 24 | 25 | $ bundle 26 | 27 | Or install it yourself as: 28 | 29 | $ gem install redactor2_rails 30 | 31 | ### Generate models for store uploading files 32 | 33 | #### ActiveRecord + carrierwave 34 | Add this lines to your application's Gemfile: 35 | 36 | gem "carrierwave" 37 | gem "mini_magick" 38 | 39 | And then execute: 40 | 41 | $ rails generate redactor2:install 42 | 43 | or 44 | 45 | $ rails generate redactor2:install --devise 46 | 47 | # --devise option generate user_id attribute for asset(Imeg, File) models. 48 | # For more details show Devise gem. 49 | # Now, Pictures and Documents uploading available only for signed in users 50 | # All uploaded files will stored with current user_id 51 | # User will choose only own uploaded Images and Files 52 | 53 | $ rake db:migrate 54 | 55 | #### Mongoid + carrierwave 56 | Add this lines to your application's Gemfile: 57 | 58 | gem "carrierwave" 59 | gem "carrierwave-mongoid", :require => "carrierwave/mongoid" 60 | gem "mini_magick" 61 | 62 | $ rails generate redactor2:install 63 | 64 | ### Include the Redactor assets 65 | 66 | Add to your `application.js`: 67 | 68 | //= require redactor2_rails 69 | //= require redactor 70 | 71 | Add to your `application.css`: 72 | 73 | *= require redactor 74 | 75 | ### Initialize Redactor 76 | 77 | For each textarea that you want to use with Redactor, 78 | add the "redactor" class and ensure it has a unique ID: 79 | 80 | <%= text_area_tag :editor, "", :class => "redactor", :rows => 40, :cols => 120 %> 81 | 82 | You need to put your textarea inside the form with `authenticity_token` field. 83 | 84 | ### Custom Your redactor 85 | 86 | If you need change some config in redactor, you can 87 | 88 | $ rails generate redactor2:config 89 | 90 | Then generate `app/assets/javascripts/redactor2_rails/config.js`. 91 | 92 | See the [Redactor Documentation](http://imperavi.com/redactor/docs/settings/) for a full list of configuration options. 93 | 94 | 95 | If You Want To setup a new language in Redactor you should do three things: 96 | 97 | In you file `app/assets/javascripts/redactor2_rails/config.js` set option 98 | 99 | "lang":'ru' 100 | 101 | Place lang files in the following location: 102 | 103 | `app/assets/javascripts/langs/` 104 | 105 | and 106 | 107 | Add to your `application.js`: 108 | 109 | //= require langs/ru 110 | 111 | #### Setting a max image size with carrierwave 112 | 113 | If you want to set a maximum image size used when a user uploads an image via carrierwave, open the uploader file and add add the following: 114 | 115 | # app/uploaders/redactor2_rails_picture_uploader.rb:33 116 | 117 | process :resize_to_limit => [500, -1] 118 | 119 | The above example will set the image to have a maximum width of 500px. 120 | 121 | ### Using plugins 122 | 123 | After including the desired plugins they can be configured in the redactor config file as normal. 124 | 125 | To add it into the editor add 'plugins' attributes to config.js file and specify which ones do you want to use: 126 | 127 | $('.redactor').redactor( 128 | { "plugins": ['fullscreen', 129 | 'textdirection', 130 | 'clips'] 131 | }); 132 | 133 | Full details of these can be found at [Redactor Plugins](http://imperavi.com/redactor/plugins/) 134 | 135 | ### Defining a Devise User Model 136 | 137 | By default redactor2_rails uses the `User` model. 138 | 139 | You may use a different model by: 140 | 141 | 1. Run a migration to update the user_id column in the 142 | 2. Overriding the user class in an initializer. 143 | 3. Overriding the authentication helpers in your controller. 144 | 145 | Create a new Migration: `rails g rename_user_id_to_new_user_id` 146 | 147 | # db/migrate/...rename_user_id_to_new_user_id.rb 148 | 149 | class RenameUserIdToNewUserId < ActiveRecord::Migration 150 | def up 151 | rename_column :redactor2_assets, :user_id, :admin_user_id 152 | end 153 | 154 | def down 155 | rename_column :redactor2_assets, :admin_user_id, :user_id 156 | end 157 | end 158 | 159 | # config/initializers/redactor2.rb 160 | # Overrides the user class 161 | 162 | module RedactorRails 163 | def self.devise_user 164 | %s(admin_user) # name of your user class 165 | end 166 | 167 | # You may override this to support legacy schema. 168 | # def self.devise_user_key 169 | # "#{self.devise_user.to_s}_id".to_sym 170 | # end 171 | end 172 | 173 | # app/controllers/application_controller.rb 174 | 175 | class ApplicationController < ActionController::Base 176 | ... 177 | 178 | def redactor2_authenticate_user! 179 | authenticate_admin_user! # devise before_filter 180 | end 181 | 182 | def redactor2_current_user 183 | current_admin_user # devise user helper 184 | end 185 | end 186 | 187 | ## Statement 188 | 189 | `redactor2_rails` base on [SammyLin/redactor-rails](https://github.com/SammyLin/redactor-rails) project. 190 | 191 | 192 | ## Contributing 193 | 194 | 1. Fork it 195 | 2. Create your feature branch (`git checkout -b my-new-feature`) 196 | 3. Commit your changes (`git commit -am 'Added some feature'`) 197 | 4. Push to the branch (`git push origin my-new-feature`) 198 | 5. Create new Pull Request 199 | 200 | ## License 201 | 202 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 203 | 204 | You may use `Redactor` for non-commercial websites for free, however, we do not guarantee any technical support. 205 | 206 | Redactor has [3 different licenses](http://imperavi.com/redactor/download/) for commercial use. 207 | For details please see [License Agreement](http://imperavi.com/redactor/license/). 208 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | -------------------------------------------------------------------------------- /app/controller/redactor2_rails/files_controller.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::FilesController < ApplicationController 2 | before_action :redactor2_authenticate_user! 3 | 4 | def create 5 | @file = Redactor2Rails.file_model.new 6 | 7 | file = params[:file] 8 | @file.data = Redactor2Rails::Http.normalize_param(file, request) 9 | if @file.has_attribute?(:"#{Redactor2Rails.devise_user_key}") 10 | @file.send("#{Redactor2Rails.devise_user}=", redactor2_current_user) 11 | @file.assetable = redactor2_current_user 12 | end 13 | 14 | if @file.save 15 | render json: { url: @file.url, name: @file.filename } 16 | else 17 | render json: { error: @file.errors } 18 | end 19 | end 20 | 21 | private 22 | 23 | def redactor2_authenticate_user! 24 | if Redactor2Rails.file_model.new.has_attribute?(Redactor2Rails.devise_user) 25 | super 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /app/controller/redactor2_rails/images_controller.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::ImagesController < ApplicationController 2 | before_action :redactor2_authenticate_user! 3 | 4 | def create 5 | @image = Redactor2Rails.image_model.new 6 | 7 | file = params[:file] 8 | @image.data = Redactor2Rails::Http.normalize_param(file, request) 9 | if @image.has_attribute?(:"#{Redactor2Rails.devise_user_key}") 10 | @image.send("#{Redactor2Rails.devise_user}=", redactor2_current_user) 11 | @image.assetable = redactor2_current_user 12 | end 13 | 14 | if @image.save 15 | render json: { id: @image.id, url: @image.url(:content) } 16 | else 17 | render json: { error: @image.errors } 18 | end 19 | end 20 | 21 | private 22 | 23 | def redactor2_authenticate_user! 24 | if Redactor2Rails.image_model.new.has_attribute?(Redactor2Rails.devise_user) 25 | super 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'bundler/setup' 4 | require 'redactor2_rails' 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require 'irb' 14 | IRB.start 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | bundle install 6 | 7 | # Do any other automated setup that you need to do here 8 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Redactor2Rails::Engine.routes.draw do 2 | resources :images, only: :create 3 | resources :files, only: :create 4 | end 5 | -------------------------------------------------------------------------------- /lib/generators/redactor2/config_generator.rb: -------------------------------------------------------------------------------- 1 | require 'rails/generators' 2 | 3 | module Redactor2 4 | module Generators 5 | class ConfigGenerator < ::Rails::Generators::Base 6 | desc 'Generates redactor2_rails config' 7 | 8 | def self.source_root 9 | @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates')) 10 | end 11 | 12 | def create_config 13 | template 'config.js', File.join('app/assets/javascripts/redactor2_rails', 'config.js') 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/generators/redactor2/install_generator.rb: -------------------------------------------------------------------------------- 1 | require 'rails/generators' 2 | require 'rails/generators/migration' 3 | module Redactor2 4 | module Generators 5 | class InstallGenerator < ::Rails::Generators::Base 6 | include ::Rails::Generators::Migration 7 | desc 'Generates redactor2_rails models, uploaders and migration' 8 | 9 | class_option :orm, type: :string, default: 'active_record', 10 | desc: 'ORM (active_record/mongoid)' 11 | 12 | class_option :upload_processor, type: :string, default: 'carrierwave', 13 | desc: 'Image processor (carrierwave)' 14 | 15 | def self.source_root 16 | @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates')) 17 | end 18 | 19 | def self.next_migration_number(_dirname) 20 | Time.now.strftime('%Y%m%d%H%M%S') 21 | end 22 | 23 | def mount_engine 24 | route "mount Redactor2Rails::Engine => '/redactor2_rails'" 25 | end 26 | 27 | def create_models 28 | %i[asset image file].each do |filename| 29 | template "#{generator_dir}/redactor2/#{filename}.rb", 30 | File.join('app/models', redactor2_dir, "#{filename}.rb") 31 | end 32 | 33 | if upload_processor.to_s == 'carrierwave' 34 | %i[image file].each do |filename| 35 | template "#{uploaders_dir}/uploaders/redactor2_rails_#{filename}_uploader.rb", 36 | File.join('app/uploaders', "redactor2_rails_#{filename}_uploader.rb") 37 | end 38 | end 39 | end 40 | 41 | def create_migrations 42 | if orm.to_s == 'active_record' 43 | if ARGV.include?('--devise') 44 | migration_template "#{generator_dir}/devise_migration.rb", File.join('db/migrate', 'create_redactor2_assets.rb') 45 | else 46 | migration_template "#{generator_dir}/migration.rb", File.join('db/migrate', 'create_redactor2_assets.rb') 47 | end 48 | end 49 | end 50 | 51 | protected 52 | 53 | def redactor2_dir 54 | 'redactor2_rails' 55 | end 56 | 57 | def generator_dir 58 | @generator_dir ||= [orm, upload_processor].join('/') 59 | end 60 | 61 | def uploaders_dir 62 | @uploaders_dir ||= %w[base carrierwave].join('/') 63 | end 64 | 65 | def orm 66 | options[:orm] || 'active_record' 67 | end 68 | 69 | def upload_processor 70 | options[:upload_processor] || 'carrierwave' 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/active_record/carrierwave/devise_migration.rb: -------------------------------------------------------------------------------- 1 | class CreateRedactor2Assets < ActiveRecord::Migration 2 | def self.up 3 | create_table :redactor2_assets do |t| 4 | # Change column name and override Redactor2Rails.devise_user_key 5 | t.integer :user_id 6 | 7 | t.string :data_file_name, null: false 8 | t.string :data_content_type 9 | t.integer :data_file_size 10 | 11 | t.integer :assetable_id 12 | t.string :assetable_type, limit: 30 13 | t.string :type, limit: 30 14 | 15 | t.integer :width 16 | t.integer :height 17 | 18 | t.timestamps 19 | end 20 | 21 | add_index 'redactor2_assets', %w[assetable_type type assetable_id], name: 'idx_redactor2_assetable_type' 22 | add_index 'redactor2_assets', %w[assetable_type assetable_id], name: 'idx_redactor2_assetable' 23 | end 24 | 25 | def self.down 26 | drop_table :redactor2_assets 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/active_record/carrierwave/migration.rb: -------------------------------------------------------------------------------- 1 | class CreateRedactor2Assets < ActiveRecord::Migration 2 | def self.up 3 | create_table :redactor2_assets do |t| 4 | t.string :data_file_name, null: false 5 | t.string :data_content_type 6 | t.integer :data_file_size 7 | 8 | t.integer :assetable_id 9 | t.string :assetable_type, limit: 30 10 | t.string :type, limit: 30 11 | 12 | t.integer :width 13 | t.integer :height 14 | 15 | t.timestamps 16 | end 17 | 18 | add_index 'redactor2_assets', %w[assetable_type type assetable_id], name: 'idx_redactor2_assetable_type' 19 | add_index 'redactor2_assets', %w[assetable_type assetable_id], name: 'idx_redactor2_assetable' 20 | end 21 | 22 | def self.down 23 | drop_table :redactor2_assets 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/active_record/carrierwave/redactor2/asset.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::Asset < ActiveRecord::Base 2 | include Redactor2Rails::Orm::ActiveRecord::AssetBase 3 | 4 | delegate :url, :current_path, :size, :content_type, :filename, to: :data 5 | validates_presence_of :data 6 | end 7 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/active_record/carrierwave/redactor2/file.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::File < Redactor2Rails::Asset 2 | mount_uploader :data, Redactor2RailsFileUploader, mount_on: :data_file_name 3 | 4 | def url_content 5 | url(:content) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/active_record/carrierwave/redactor2/image.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::Image < Redactor2Rails::Asset 2 | mount_uploader :data, Redactor2RailsImageUploader, mount_on: :data_file_name 3 | 4 | def url_content 5 | url(:content) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/base/carrierwave/uploaders/redactor2_rails_file_uploader.rb: -------------------------------------------------------------------------------- 1 | 2 | class Redactor2RailsFileUploader < CarrierWave::Uploader::Base 3 | include Redactor2Rails::Backend::CarrierWave 4 | 5 | # storage :fog 6 | storage :file 7 | 8 | def store_dir 9 | "system/redactor2_assets/files/#{model.id}" 10 | end 11 | 12 | def extension_white_list 13 | Redactor2Rails.files_file_types 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/base/carrierwave/uploaders/redactor2_rails_image_uploader.rb: -------------------------------------------------------------------------------- 1 | 2 | class Redactor2RailsImageUploader < CarrierWave::Uploader::Base 3 | include Redactor2Rails::Backend::CarrierWave 4 | 5 | # Include RMagick or ImageScience support: 6 | # include CarrierWave::RMagick 7 | include CarrierWave::MiniMagick 8 | # include CarrierWave::ImageScience 9 | 10 | # Choose what kind of storage to use for this uploader: 11 | # storage :fog 12 | storage :file 13 | 14 | # Override the directory where uploaded files will be stored. 15 | # This is a sensible default for uploaders that are meant to be mounted: 16 | def store_dir 17 | "system/redactor2_assets/images/#{model.id}" 18 | end 19 | 20 | # Provide a default URL as a default if there hasn't been a file uploaded: 21 | # def default_url 22 | # "/images/fallback/" + [version_name, "default.png"].compact.join('_') 23 | # end 24 | 25 | # Process files as they are uploaded: 26 | # process :scale => [200, 300] 27 | # 28 | # def scale(width, height) 29 | # # do something 30 | # end 31 | 32 | process :read_dimensions 33 | 34 | # Create different versions of your uploaded files: 35 | version :thumb do 36 | process resize_to_fill: [100, 100] 37 | end 38 | 39 | version :content do 40 | process resize_to_limit: [800, 800] 41 | end 42 | 43 | # Add a white list of extensions which are allowed to be uploaded. 44 | # For images you might use something like this: 45 | def extension_white_list 46 | Redactor2Rails.images_file_types 47 | end 48 | 49 | # Override the filename of the uploaded files: 50 | # Avoid using model.id or version_name here, see uploader/store.rb for details. 51 | # def filename 52 | # "something.jpg" if original_filename 53 | # end 54 | end 55 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/config.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | // Pass authenticity_token 3 | var params = '[name="authenticity_token"]'; 4 | // Set global settings 5 | $.Redactor.settings = { 6 | //plugins: ['source', 'fullscreen', 'textdirection', 'clips'], 7 | imageUpload: '/redactor2_rails/images', 8 | imageUploadFields: params, 9 | fileUpload: '/redactor2_rails/files', 10 | fileUploadFields: params 11 | }; 12 | // Initialize Redactor 13 | $('.redactor').redactor(); 14 | }); 15 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/mongoid/carrierwave/redactor2/asset.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::Asset 2 | include Mongoid::Document 3 | include Mongoid::Timestamps 4 | 5 | include Redactor2Rails::Orm::Mongoid::AssetBase 6 | 7 | delegate :url, :current_path, :size, :content_type, :filename, to: :data 8 | validates_presence_of :data 9 | end 10 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/mongoid/carrierwave/redactor2/file.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::File < Redactor2Rails::Asset 2 | mount_uploader :data, Redactor2RailsFileUploader, mount_on: :data_file_name 3 | 4 | def url_content 5 | url(:content) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/generators/redactor2/templates/mongoid/carrierwave/redactor2/image.rb: -------------------------------------------------------------------------------- 1 | class Redactor2Rails::Image < Redactor2Rails::Asset 2 | mount_uploader :data, Redactor2RailsImageUploader, mount_on: :data_file_name 3 | 4 | def url_content 5 | url(:content) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/redactor2_rails.rb: -------------------------------------------------------------------------------- 1 | require 'redactor2_rails/version' 2 | require 'orm_adapter' 3 | 4 | module Redactor2Rails 5 | IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg', 'image/pjpeg', 'image/tiff', 'image/x-png'].freeze 6 | 7 | FILE_TYPES = ['application/msword', 'application/pdf', 'text/plain', 'text/rtf', 'application/vnd.ms-excel'].freeze 8 | 9 | autoload :Http, 'redactor2_rails/http' 10 | autoload :Devise, 'redactor2_rails/devise' 11 | 12 | module Backend 13 | autoload :CarrierWave, 'redactor2_rails/backend/carrierwave' 14 | end 15 | require 'redactor2_rails/orm/base' 16 | require 'redactor2_rails/orm/active_record' 17 | require 'redactor2_rails/orm/mongoid' 18 | require 'redactor2_rails/engine' 19 | 20 | mattr_accessor :images_file_types, :files_file_types, :devise_user, :image_model, :file_model 21 | @@images_file_types = %w[jpg jpeg png gif tiff] 22 | @@files_file_types = %w[pdf doc docx xls xlsx rtf txt] 23 | 24 | def self.image_model 25 | @image_model || Redactor2Rails::Image 26 | end 27 | 28 | def self.file_model 29 | @file_model || Redactor2Rails::File 30 | end 31 | 32 | def self.devise_user 33 | @devise_user || :user 34 | end 35 | 36 | def self.devise_user_key 37 | "#{devise_user}_id".to_sym 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/redactor2_rails/backend/carrierwave.rb: -------------------------------------------------------------------------------- 1 | require 'mime/types' 2 | require 'mini_magick' 3 | 4 | module Redactor2Rails 5 | module Backend 6 | module CarrierWave 7 | def self.included(base) 8 | base.send(:include, InstanceMethods) 9 | base.send(:extend, ClassMethods) 10 | end 11 | 12 | module ClassMethods 13 | def self.extended(base) 14 | base.class_eval do 15 | process :extract_content_type 16 | process :set_size 17 | end 18 | end 19 | end 20 | 21 | module InstanceMethods 22 | # process :strip 23 | def strip 24 | manipulate! do |img| 25 | img.strip 26 | img = yield(img) if block_given? 27 | img 28 | end 29 | end 30 | 31 | # process :quality => 85 32 | def quality(percentage) 33 | manipulate! do |img| 34 | img.quality(percentage) 35 | img = yield(img) if block_given? 36 | img 37 | end 38 | end 39 | 40 | def extract_content_type 41 | content_type = if file.content_type == 'application/octet-stream' || 42 | file.content_type.blank? 43 | MIME::Types.type_for(original_filename).first 44 | else 45 | file.content_type 46 | end 47 | 48 | model.data_content_type = content_type.to_s 49 | end 50 | 51 | def set_size 52 | model.data_file_size = file.size 53 | end 54 | 55 | def read_dimensions 56 | if model.image? && model.has_dimensions? 57 | magick = ::MiniMagick::Image.new(current_path) 58 | model.width = magick[:width] 59 | model.height = magick[:height] 60 | end 61 | end 62 | end 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /lib/redactor2_rails/devise.rb: -------------------------------------------------------------------------------- 1 | module Redactor2Rails 2 | module Devise 3 | def redactor2_authenticate_user! 4 | authenticate_user! 5 | end 6 | 7 | def redactor2_current_user 8 | current_user 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/redactor2_rails/engine.rb: -------------------------------------------------------------------------------- 1 | module Redactor2Rails 2 | class Engine < Rails::Engine 3 | isolate_namespace Redactor2Rails 4 | 5 | initializer 'redactor2_devise' do |_app| 6 | ActionController::Base.send :include, Redactor2Rails::Devise 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/redactor2_rails/http.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'digest/sha1' 3 | require 'mime/types' 4 | 5 | module Redactor2Rails 6 | module Http 7 | # Create tempfile from hash 8 | class UploadedFile 9 | attr_accessor :original_filename, :content_type, :tempfile, :headers 10 | 11 | def initialize(hash) 12 | @original_filename = hash[:filename] 13 | @content_type = hash[:type] 14 | @headers = hash[:head] 15 | @tempfile = hash[:tempfile] 16 | raise(ArgumentError, ':tempfile is required') unless @tempfile 17 | end 18 | 19 | def open 20 | @tempfile.open 21 | end 22 | 23 | def path 24 | @tempfile.path 25 | end 26 | 27 | def read(*args) 28 | @tempfile.read(*args) 29 | end 30 | 31 | def rewind 32 | @tempfile.rewind 33 | end 34 | 35 | def size 36 | @tempfile.size 37 | end 38 | end 39 | 40 | # Usage (paperclip example) 41 | # @asset.data = QqFile.new(params[:qqfile], request) 42 | class QqFile < ::Tempfile 43 | def initialize(filename, request, tmpdir = Dir.tmpdir) 44 | @original_filename = filename 45 | @request = request 46 | 47 | super Digest::SHA1.hexdigest(filename), tmpdir 48 | fetch 49 | end 50 | 51 | def fetch 52 | write(body) 53 | rewind 54 | self 55 | end 56 | 57 | attr_reader :original_filename 58 | 59 | def content_type 60 | types = MIME::Types.type_for(original_filename) 61 | types.empty? ? @request.content_type : types.first.to_s 62 | end 63 | 64 | def body 65 | if @request.raw_post.respond_to?(:force_encoding) 66 | @request.raw_post.force_encoding('UTF-8') 67 | else 68 | @request.raw_post 69 | end 70 | end 71 | end 72 | 73 | # Convert nested Hash to HashWithIndifferentAccess and replace 74 | # file upload hash with UploadedFile objects 75 | def self.normalize_param(*args) 76 | value = args.first 77 | if Hash === value && value.key?(:tempfile) 78 | UploadedFile.new(value) 79 | elsif value.is_a?(String) 80 | QqFile.new(*args) 81 | else 82 | value 83 | end 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /lib/redactor2_rails/orm/active_record.rb: -------------------------------------------------------------------------------- 1 | require 'redactor2_rails/orm/base' 2 | 3 | module Redactor2Rails 4 | module Orm 5 | module ActiveRecord 6 | module AssetBase 7 | def self.included(base) 8 | base.send(:include, Base::AssetBase::InstanceMethods) 9 | base.send(:extend, ClassMethods) 10 | end 11 | 12 | module ClassMethods 13 | def self.extended(base) 14 | base.class_eval do 15 | self.table_name = 'redactor2_assets' 16 | 17 | belongs_to :assetable, polymorphic: true, required: false 18 | belongs_to Redactor2Rails.devise_user, foreign_key: Redactor2Rails.devise_user_key, required: false 19 | 20 | if defined?(ActiveModel::ForbiddenAttributesProtection) && base.ancestors.include?(ActiveModel::ForbiddenAttributesProtection) 21 | # Ok 22 | elsif defined?(ActiveModel::MassAssignmentSecurity) && base.ancestors.include?(ActiveModel::MassAssignmentSecurity) 23 | attr_accessible :data, :assetable_type, :assetable_id, :assetable 24 | end 25 | end 26 | end 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/redactor2_rails/orm/base.rb: -------------------------------------------------------------------------------- 1 | module Redactor2Rails 2 | module Orm 3 | module Base 4 | module AssetBase 5 | module InstanceMethods 6 | def has_dimensions? 7 | respond_to?(:width) && respond_to?(:height) 8 | end 9 | 10 | def image? 11 | Redactor2Rails::IMAGE_TYPES.include?(data_content_type) 12 | end 13 | 14 | def image 15 | url 16 | end 17 | 18 | def thumb 19 | url(:thumb) 20 | end 21 | 22 | def as_json_methods 23 | %i[image thumb] 24 | end 25 | 26 | def as_json(_options = nil) 27 | options = { 28 | methods: as_json_methods, 29 | root: false 30 | } 31 | 32 | super options 33 | end 34 | end 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/redactor2_rails/orm/mongoid.rb: -------------------------------------------------------------------------------- 1 | require 'redactor2_rails/orm/base' 2 | 3 | module Redactor2Rails 4 | module Orm 5 | module Mongoid 6 | module AssetBase 7 | def self.included(base) 8 | base.send(:include, Base::AssetBase::InstanceMethods) 9 | base.send(:extend, ClassMethods) 10 | end 11 | 12 | module ClassMethods 13 | def self.extended(base) 14 | base.class_eval do 15 | store_in collection: 'redactor2_assets' 16 | 17 | belongs_to :assetable, polymorphic: true 18 | 19 | field :data_file_name, type: String 20 | field :data_content_type, type: String 21 | field :data_file_size, type: Integer 22 | 23 | field :type, type: String 24 | 25 | field :width, type: Integer 26 | field :height, type: Integer 27 | 28 | index(assetable: 1, type: 1) 29 | index(assetable: 1) 30 | end 31 | end 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/redactor2_rails/version.rb: -------------------------------------------------------------------------------- 1 | module Redactor2Rails 2 | VERSION = "0.1.4" 3 | end 4 | -------------------------------------------------------------------------------- /redactor2_rails.gemspec: -------------------------------------------------------------------------------- 1 | 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'redactor2_rails/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = 'redactor2_rails' 8 | spec.version = Redactor2Rails::VERSION 9 | spec.authors = ['Oleg Sulyanov'] 10 | spec.email = ['oleg@sulyanov.com'] 11 | 12 | spec.summary = 'Imperavi Redactor for Rails 3.x - 4 Asset Pipeline' 13 | spec.homepage = 'https://github.com/osulyanov/redactor2_rails' 14 | spec.license = 'MIT' 15 | 16 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } 17 | spec.bindir = 'bin' 18 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 19 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 20 | spec.require_paths = ['lib'] 21 | 22 | spec.add_dependency('devise') 23 | spec.add_dependency('mime-types') 24 | spec.add_dependency('orm_adapter') 25 | 26 | spec.add_development_dependency 'bundler', '~> 1.10' 27 | spec.add_development_dependency 'rake', '~> 10.0' 28 | end 29 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/redactor2_rails/config.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | // Pass authenticity_token 3 | var params = '[name="authenticity_token"]'; 4 | // Set global settings 5 | $.Redactor.settings = { 6 | //plugins: ['source', 'fullscreen', 'textdirection', 'clips'], 7 | imageUpload: '/redactor2_rails/images', 8 | imageUploadFields: params, 9 | fileUpload: '/redactor2_rails/files', 10 | fileUploadFields: params 11 | }; 12 | // Initialize Redactor 13 | $('.redactor').redactor(); 14 | }); 15 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/redactor2_rails/index.js: -------------------------------------------------------------------------------- 1 | //= require ./config 2 | --------------------------------------------------------------------------------