Has Media

Media Managment Library for ActiveRecord and Carrierwave

Easy way to link media (ie image, audio, video, pdf, …) on other activerecords models

Use branch rails2.3 for Rails 2.3.x (gem install has_media -v=v0.1.3)

Use branch rails3 for Rails 3 (gem install has_media)

Installation

Rails 2.3.x

see github.com/klacointe/has_media/tree/rails2.3

Rails 3

  • gem install has_media

  • rails generate has_media:install

The generator will create :

  • migration for activerecord

  • initializer for HasMedia configuration

  • locales files

Model and Uploaders

You must defined model and uploader with the name given in the :only option

Examples are in the /examples directory…

Usage

Available methods are :

  • has_one_medium : Link to one medium

  • has_many_media : Link to many media

Available options are :

  • only : restrict medium type to link on

  • encode : if false is given, set the encode status of this medium to NO_ENCODING instead of ENCODE_WAIT, default to true

Example :

class MyModelWithMedia < ActiveRecord::Base

  has_one_medium  :image, :only => :image
  has_many_media  :images, :only => :image

  has_one_medium  :audio, :only => :audio
  has_many_media  :audios, :only => :audio

  has_one_medium  :image_no_encode, :only => :image, :encode => false

  has_one_medium  :pdf, :encode => false

end

Configuration

Configuration take place in config/initializers/has_media.rb

# Set the directory path to use to store media
HasMedia.directory_path = "media"

# Set the base uri to access media
HasMedia.directory_uri = "/media"

# Set custom error messages
HasMedia.errors_messages = {:type_error => I18n.t('has_media.errors.type_error')}

# Set the allowed medium types (used if no :only option given) for you application
# Set the allowed mime types for each medium type
HasMedia.medium_types = {
  "Image" => ["image/jpeg", "image/png"],
  "Video" => ["video/mp4"],
  "Audio" => ["audio/mp3"]
}

# Set the extension of encoded files to use for each medium types (used in file_uri and file_path)
HasMedia.encoded_extensions = {
  :image => 'png',
  :audio => 'ogg',
  :video => 'flv'
}

# Require you uploaders 
Dir.glob(File.dirname(__FILE__) + '/../app/uploaders/*.rb').each do |uploader|
  require uploader
end

# Change CarrierWave root path
CarrierWave.root = HasMedia.directory_path

Routes

Add routes for media in your config/routes.rb

resources :media, :only => [:destroy]

Helpers

Now you can use the has_media_field helper.

<%= form_for(@model, :html => {:multipart => true}) do |f| %>
  <%= has_media_field @model, :context %>
  <%= f.submit %>
<%- end %>

Generating views

If you need to overload has_media views, just run : rails generate has_media:views

This will copy has_media views in your application

Encode with resque

Just add a callback on media class you want to encode via resque.

Example :

file : app/models/my_model_with_media.rb

class MyModelWithMedia < ActiveRecord::Base
  has_one_medium  :avatar, :only => :my_media
end

file : app/models/my_media.rb

class MyMedia < Medium
  mount_uploader :file, MyMediaUploader
  after_save :enqueue_encoding

  def enqueue_encoding
    Resque.enqueue(EncodeMyMedia, self.original_file_path)
  end
end

file : resque/tasks/encode_my_media.rb

class EncodeMyMedia
  @queue = :my_media
  include Magick

  def self.perform(file)
    img = Image.read(file).first
    img.thumbnail(50, 50).write(file.gsub(/\.[^.]+$/, "") + "_thumb.png")
  end 
end

Then you can manage your media like this :

@model = MyModelWithMedia.new
@model.avatar = File.open("my_file.jpg")
@model.save
@model.avatar.original_file_uri 	=> "/media/my_media/:id/my_file.jpg"
@model.avatar.file_uri('thumb') 	=> "/media/my_media/:id/my_file_thumb.jpg"

Example application

github.com/klacointe/has_media_example

Testing

Factory example using factory_girl :

Factory.define :image, :class => Image do |f| 
  f.content_type 'image/jpeg'
  f.filename 'image.jpg'
  f.status 'accepted'
  f.encode_status 0
  f.add_attribute :context, 'images'
  f.file {ActionController::TestUploadedFile.new(File.join(Rails.root, '/spec/factories/image.jpg'), 'image/jpeg')}
end

Todo

  • Doc for testing (ActionController::TestUploadedFile is now obsolete in rails 3), add HasMediaTestHelper with stub_temp_file method

  • Add controller and views examples with overload system (form fields, display, …)

  • Generator for models and uploaders (Type in Image, Video, Audio, Pdf) : rails generate has_media_model Type Name

  • Document code

  • add example app on github

Contributors

klacointe, spk, shingara, nono

Copyright © 2009 AF83. See LICENSE for details.