Coder Social home page Coder Social logo

attachinary's Introduction

Attachinary

Gem Version

Note: v1 is not backward compatible. Refer to wiki on how to upgrade.

Need lightweight attachment (photos and raw files) handler for any of your model, in either has_one or has_many relation, without altering your models' schema and with zero effort? Attachinary is the tool for you!

Why is Attachinary different:

  • Supports both ActiveRecord and Mongoid ORMs!
  • No need to alter your model schema every time you introduce new kind of attachment.
  • Handles both has_one and has_many use cases.
  • No need for ImageMagick (or similar) - your thumbnails are generated on the fly by Cloudinary.
  • Fully customizable, custom jQuery plugin for async file uploads with previews.
  • Files are uploaded directly to Cloudinary completely bypassing your app (without affecting its performance).
  • Very easy to use. Once set up, 1 line is enough to add attachment support to your model. No migrations, no Uploaders.
  • Lightweight form submission. Attachinary handles file upload asynchronously and the only thing that is passed to your server is metadata. That makes form postbacks fast and reliable.
  • Benefits of jQuery File Upload (drag'n'drop, selecting multiple files, progress indicators.. etc)
  • All the benefits of Cloudinary (resizing, cropping, rotating, rounding corners, face detection...).

Attachinary uses Cloudinary service. Gem is structured as mountable rails engine.

Installation

First, make sure that you have cloudinary gem installed and properly configured.

Add following line to your Gemfile:

gem 'attachinary'

Specify which ORM you wish to use by adding following line to your application.rb file (or custom initializer):

require "attachinary/orm/YOUR_ORM" # active_record or mongoid

If you're using ActiveRecord ORM, then run following lines to generate required table:

rake attachinary:install:migrations
rake db:migrate

Next, add following line in your routes.rb file:

mount Attachinary::Engine => "/attachinary"

It will generate '/attachinary/cors' which will be used for iframe file transfers (for unsupported browsers).

Finally, make sure that you have following line in head section of your application layout file:

<%= cloudinary_js_config %>

Usage

Lets say that we want all of our users to have single avatar and many photos in their gallery. We also want avatar to be required. We also want to limit the number of photos user can upload to 10. We can declare it like this:

class User < ActiveRecord::Base
	...
	has_attachment  :avatar, accept: [:jpg, :png, :gif]
	has_attachments :photos, maximum: 10

	validates :avatar, presence: true
	# ...
end

In our _form.html.erb template, we need to add only this:

<%= f.attachinary_file_field :avatar %>
<%= f.attachinary_file_field :photos %>

If you're using SimpleForm, you can even shorten this to:

<%= f.input :avatar, as: :attachinary %>
<%= f.input :photos, as: :attachinary %>

Finally, you have to include necessary javascript files. In your application.js, add following lines:

//= require jquery.ui.widget
//= require jquery.iframe-transport
//= require jquery.fileupload
//= require cloudinary/jquery.cloudinary
//= require attachinary

If you don't have the jQuery File Upload files, you can use following rake task to fetch (or update) them:

rake attachinary:fetch_fileupload

And, add this code on document ready:

$('.attachinary-input').attachinary()

Attachinary jquery plugin is based upon jQuery File Upload plugin but without any fancy UI (it leaves it up to you to decorate it).

Plugin is fully customizable. It uses John Resig's micro templating in the background, but you can override it with whatever you like. Check out the source code for more configuration options you can set.

Displaying avatar and photos

Here comes the good part. There is no need to transform images on your server. Instead, you can request image transformations directly from Cloudinary. First time you request image, it is created and cached on the Cloudinary server for later use. Here is sample code that you can use in your _user.html.erb partial:

<% if @user.avatar? %>
	<%= cl_image_tag(@user.avatar.path, { size: '50x50', crop: :thumb, gravity: :face }) %>
<% end %>

<% @user.photos.each do |photo| %>
	<%= cl_image_tag(photo.path, { size: '125x125', crop: :fit }) %>
<% end %>

Avatar will be automatically cropped to 50x50px to show only user face. You read it right: face detection :) All other user photos are just cropped to fit within 125x125.

Whenever you feel like changing image sizes, you don't need to set rake task that will take forever to re-process thousands of photos. You just change the dimension in your partial and thats it.

Additional methods

# uploading avatar by passing url
user.avatar_url = "http://path/to/avatar.jpg"

# uploading photos by passing multiple urls
user.photo_urls = %w[ http://path/to/photo1.jpg http://path/to/photo2.jpg]

# uploading by passing IO object (e.g. direct file upload)
user.avatar = File.open("/path/to/file", 'r')

# if you want to provide additionals parameters from http://cloudinary.com/documentation/upload_images
# you need to use diffrent syntax
user.send(:avatar=, File.open("path/to/file", 'r'), :folder => Rails.env.to_s)

# # uploading photos by passing multiple urls and optional parameters that will be added to every file.
user.send(:photo_urls=, %w[ http://path/to/photo1.jpg http://path/to/photo2.jpg], folder: Rails.env.to_s, use_filename: true, image_metadata: true)

No-JS usage

If you don't want fancy JS features, all you have to do is just switch to :input file field:

<%= f.input :photo, as: :file %>
<%= f.input :images, as: :file, input_html: { multiple: true } %>

Preventing n+1 queries when loading attachinary associations

You can eager load attachinary associations.

For example, I have a user model that has photo and avatar as attachments.

# user.rb
  has_attachment :avatar
  has_attachments :photos

# users_controller.rb
  User.includes(:avatar_files, :photo_files).all

Conventions

  • always use singular identifier after has_attachment (e.g. has_attachment :photo)
  • always use plural identifier after has_attachments (e.g. has_attachments :images)
  • do not use colliding identifiers (e.g. has_attachment :photo and has_attachments :photos) on same model.

Requirements and Compatibility

  • Cloudinary
  • Ruby 1.9
  • Rails 3.2+
  • jQuery

Browser Compatibility

Attachinary jquery plugin uses JSON2 to generate JSON data. This works for all major browsers, but if you wish to support older ones (e.g. IE7-), include json2.js.

Credits and License

Developed by Milovan Zogovic.

This software is released under the MIT License.

attachinary's People

Contributors

assembler avatar danielnill avatar drewmca avatar itaibenari avatar jerome avatar joshdvir avatar maml avatar orlando avatar rochers avatar roomthirteen avatar skwp avatar tocker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

attachinary's Issues

Uncaught exception: uninitialized constant Mongoid while installation

When I try to install attachinary on Ruby 1.9.3 and rails-3.2.13

I got this error:

Uncaught exception: uninitialized constant Mongoid
/Users/jan/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/attachinary-1.2.6/lib/attachinary/orm/mongoid/file.rb:3:in `<class:File>'
/Users/jan/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/attachinary-1.2.6/lib/attachinary/orm/mongoid/file.rb:2:in `<module:Attachinary>'
/Users/jan/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/attachinary-1.2.6/lib/attachinary/orm/mongoid/file.rb:1:in `<top (required)>'
/Users/jan/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/attachinary-1.2.6/lib/attachinary/orm/mongoid.rb:4:in `require_relative'
/Users/jan/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/attachinary-1.2.6/lib/attachinary/orm/mongoid.rb:4:in `<top (required)>'
/Users/jan/RubymineProjects/untitled/config/application.rb:6:in `require'
/Users/jan/RubymineProjects/untitled/config/application.rb:6:in `<top (required)>'
/Users/jan/.gem/ruby/1.9.1/gems/railties-3.2.13/lib/rails/commands.rb:53:in `require'
/Users/jan/.gem/ruby/1.9.1/gems/railties-3.2.13/lib/rails/commands.rb:53:in `block in <top (required)>'
/Users/jan/.gem/ruby/1.9.1/gems/railties-3.2.13/lib/rails/commands.rb:50:in `tap'
/Users/jan/.gem/ruby/1.9.1/gems/railties-3.2.13/lib/rails/commands.rb:50:in `<top (required)>'
/Users/jan/RubymineProjects/untitled/script/rails:6:in `require'
/Users/jan/RubymineProjects/untitled/script/rails:6:in `<top (required)>'

Can you provide a solution for this please?

PS: Love your gem (it's really one ) :-)

Best way to test?

I am using attachinary with FactorGirl.

What is the best way to test uploads and also delete it?

What I've done is in my model_spec (user) which uses an avatar.

avatar { fixture_file_upload(Rails.root.join('spec', 'assets', 'images', '800x600horizontal.png'), 'image/png') }

Every test uploads an image. But wont delete it.

Image size on form

Hi,

thanks a lot for the gem, it is really useful. Is there a way to pass size parameters on a simple_form input so that the thumbnail display size for the uploaded images can be controlled on the form?

Something along these lines:
f.input :photos, as: :attachinary, width: '260', height: '260'

Or is there a way of setting a global default? It seems to default to 75 x 75.

Storing the metadata

While the gem already stores the picture dimensions, I think it would be great to also store all available metadata (EXIF, GPS, etc...). Am I the only one with this need?

Issue with Docs

Hi, firstly thanks this is great...

just a small amendment for the docs:

<%= cl_image_tag(@user.avatar.path, { size: '50x50', crop: :face }) %>

face is not a crop and dose not return an image.

<%= cl_image_tag(@user.avatar.path, { size: '50x50', crop: :fit, gravity: :face }) %>

thanks

Touch associated model

We make use of touch: true a lot.

@assembler, would you be open to adding belongs_to :attachinariable, touch: options[:touch] to Attachinary::File?

Image Positioning

If I'm using ruby has_attachments :photos, maximum: 10

Is it possible to assign a position to these photos after they are uploaded?

I would like to be able to manage the order the photos are displayed when calling:

<% @user.photos.each do |photo| %>
    <%= cl_image_tag(photo.path, { size: '125x125', crop: :fit }) %>
<% end %>

Delete images

As I've seen, images I delete in the file upload Form, get's not deleted on cloudinary...

do I have add something special to get this working..

many, many, thanks

PS: and YESSSS this is one of the greatest plugs here :-D

Input does not specify an ID.

I'm trying to validate my html and a frequent error I see is that the label tag generated with the input does not have a matching for field.

I have a post model where each post can have a child post. Each input ID needs to be unique so I append the parent ID before the typical ID name. I haven't had any trouble so far except that I can't set the upload field's ID
I'm able to set the label tag by using:
f.input :upload, :as => :attachinary, input_html: { id: "#{parent.id}_post_upload"}
However I would like to set both the label and the input field.

It seems that line 24 of lib/attachinary/view_helpers.rb is causing the issue:
options[:html][:id] = nil
Everything works as expected if I remove the line.

Thank you,

Eric Wright

IE9 and below: cors file is sent to the browser

After uploading the file through attachinary file input, the browser asks me if I want to save the "cors" file. Something seems wrong here. I thought it uses some fallback iframe mechanism in IE?

How do I store per-image meta data with my attachinary files?

I would like to store per-photo metadata with each file. Reasons like the following:

  1. I would like to set one photo within a group to be the "primary" photo, without necessarily reordering the photos.
  2. I would like to be able to rotate a photo 90 degrees, and have that rotation always applied in every view of the photo.
  3. I would like to set the cropping preference on a per-photo basis. Sometimes I have seen that crop: :faces doesn't gracefully degrade to :face or to :thumb

Possibly there are other things too, and I want to know how you would generally approach these issues, if you have another idea. My only thought was to store some meta info with each attachinary object.

Ability to specify template per attachinary call

I have multiple attachinary fields on one page which have different requirements for thumbnailing. I've solved this partially by creating a template:

%script{id: defined?(template_id) && template_id ? template_id : "attachinary-template", type: 'text/template'}
  :plain
    <ul>
    <% for(var i=0; i<files.length; i++){ %>
      <li>
        <img
          data-orig-width='<%= files[i].width %>',
          data-orig-height='<%= files[i].height %>',
          data-public-id='<%= files[i].public_id %>',
          src="<%= $.cloudinary.url(files[i].public_id, { "version": files[i].version, "angle": 'exif', "format": 'jpg', "crop": 'thumb', "gravity": 'south', "width": #{thumb_width}, "height": #{thumb_height} }) %>"
          alt="" width="#{thumb_width}" height="#{thumb_height}" />
        <a href="#" data-remove="<%= files[i].public_id %>">Remove</a>
      </li>
    <% } %>
    </ul>

You can see here that I pass in my height and width for the thumb.

    = render partial: 'shared/attachinary/template', locals: {template_id: "homepage_image_template", thumb_width: 720, thumb_height: 275}
    = render partial: 'shared/attachinary/template', locals: {template_id: "header_image_template", thumb_width: 960, thumb_height: 125}

However when I try to initialize attachinary with two different templates:

    $.attachinary.config.template = $("#header_image_template").html();
    $('#curated_set_collection_header_attributes_header_image').attachinary();

    $.attachinary.config.template = $("#homepage_image_template").html();
    $('#curated_set_collection_header_attributes_homepage_image').attachinary();

This does not work because I think it defers reading the template until the uploads are done. Ideally the attachinary() call would take a link to the template. I may tackle this issue myself but if you've thought about it already, I'd love some guidance @assembler - thanks!

undefined method `push' for #<Hash:0x007fed931530a0>

After some trial and error I must confirm that "EDITING and UPDATING" a model cause this issue:

NoMethodError in LocationsController#update

undefined method `push' for #<Hash:0x007fed931530a0>

app/controllers/locations_controller.rb:79:in block in update' app/controllers/locations_controller.rb:78:inupdate

The depending line is:

78:     respond_to do |format| 
79:       if @location.update_attributes(params[:location])

when I comment_out this line in the form

<%= attachinary_file_field_tag 'location[image]', @location, :image %>

and save/update the edited model all works fine.

I am working with the mongoid ORM (mongoid 2.4)

any suggestions?

Parameters

"image"=>"[{"format":"jpg",
"public_id":"qw8toyokwzstksukinu8",
"resource_type":"image",
"version":"1351470251",
"path":"v1351470251/qw8toyokwzstksukinu8.jpg"}]",
"logo"=>"[{"format":"jpg",
"public_id":"dsmsnc7a5qjnvprwmwkc",
"resource_type":"image",
"version":"1351470255",
"path":"v1351470255/dsmsnc7a5qjnvprwmwkc.jpg"}]"},
"commit"=>"Submit Location!",
"id"=>"508dc953b7807e1aa7000026"}

Stack Trace

mongoid (2.4.12) lib/mongoid/atomic/modifiers.rb:122:in block in add_operation' mongoid (2.4.12) lib/mongoid/atomic/modifiers.rb:121:ineach'
mongoid (2.4.12) lib/mongoid/atomic/modifiers.rb:121:in add_operation' mongoid (2.4.12) lib/mongoid/atomic/modifiers.rb:87:inblock in set'
mongoid (2.4.12) lib/mongoid/atomic/modifiers.rb:84:in each_pair' mongoid (2.4.12) lib/mongoid/atomic/modifiers.rb:84:inset'
mongoid (2.4.12) lib/mongoid/atomic.rb:277:in generate_atomic_updates' mongoid (2.4.12) lib/mongoid/atomic.rb:105:inblock (2 levels) in atomic_updates'
mongoid (2.4.12) lib/mongoid/atomic.rb:104:in each' mongoid (2.4.12) lib/mongoid/atomic.rb:104:inblock in atomic_updates'
mongoid (2.4.12) lib/mongoid/atomic.rb:102:in tap' mongoid (2.4.12) lib/mongoid/atomic.rb:102:inatomic_updates'
mongoid (2.4.12) lib/mongoid/persistence/operations.rb:157:in init_updates' mongoid (2.4.12) lib/mongoid/persistence/operations.rb:130:inupdates'
mongoid (2.4.12) lib/mongoid/persistence/operations/update.rb:44:in block in persist' mongoid (2.4.12) lib/mongoid/persistence/modification.rb:25:inblock (2 levels) in prepare'
activesupport (3.2.3) lib/active_support/callbacks.rb:403:in _run__2553662088574445908__update__1039413575395477817__callbacks' activesupport (3.2.3) lib/active_support/callbacks.rb:405:in__run_callback'
activesupport (3.2.3) lib/active_support/callbacks.rb:385:in _run_update_callbacks' activesupport (3.2.3) lib/active_support/callbacks.rb:81:inrun_callbacks'
mongoid (2.4.12) lib/mongoid/callbacks.rb:43:in run_callbacks' mongoid (2.4.12) lib/mongoid/persistence/modification.rb:24:inblock in prepare'
activesupport (3.2.3) lib/active_support/callbacks.rb:414:in _run__2553662088574445908__save__1039413575395477817__callbacks' activesupport (3.2.3) lib/active_support/callbacks.rb:405:in__run_callback'
activesupport (3.2.3) lib/active_support/callbacks.rb:385:in _run_save_callbacks' activesupport (3.2.3) lib/active_support/callbacks.rb:81:inrun_callbacks'
mongoid (2.4.12) lib/mongoid/callbacks.rb:43:in run_callbacks' mongoid (2.4.12) lib/mongoid/persistence/modification.rb:23:inprepare'
mongoid (2.4.12) lib/mongoid/persistence/operations/update.rb:43:in persist' mongoid (2.4.12) lib/mongoid/persistence.rb:91:inupdate'
mongoid (2.4.12) lib/mongoid/persistence.rb:156:in upsert' mongoid (2.4.12) lib/mongoid/persistence.rb:120:inupdate_attributes'
actionpack (3.2.3) lib/action_controller/metal/mime_responds.rb:270:in call' actionpack (3.2.3) lib/action_controller/metal/mime_responds.rb:270:inretrieve_collector_from_mimes'
actionpack (3.2.3) lib/action_controller/metal/mime_responds.rb:194:in respond_to' actionpack (3.2.3) lib/action_controller/metal/implicit_render.rb:4:insend_action'
actionpack (3.2.3) lib/abstract_controller/base.rb:167:in process_action' actionpack (3.2.3) lib/action_controller/metal/rendering.rb:10:inprocess_action'
actionpack (3.2.3) lib/abstract_controller/callbacks.rb:18:in block in process_action' activesupport (3.2.3) lib/active_support/callbacks.rb:425:in_run__2911065496874474384__process_action__533950475842813760__callbacks'
activesupport (3.2.3) lib/active_support/callbacks.rb:405:in __run_callback' activesupport (3.2.3) lib/active_support/callbacks.rb:385:in_run_process_action_callbacks'
activesupport (3.2.3) lib/active_support/callbacks.rb:81:in run_callbacks' actionpack (3.2.3) lib/abstract_controller/callbacks.rb:17:inprocess_action'
actionpack (3.2.3) lib/action_controller/metal/rescue.rb:29:in process_action' actionpack (3.2.3) lib/action_controller/metal/instrumentation.rb:30:inblock in process_action'
activesupport (3.2.3) lib/active_support/notifications.rb:123:in block in instrument' activesupport (3.2.3) lib/active_support/notifications/instrumenter.rb:20:ininstrument'
activesupport (3.2.3) lib/active_support/notifications.rb:123:in instrument' actionpack (3.2.3) lib/action_controller/metal/instrumentation.rb:29:inprocess_action'
actionpack (3.2.3) lib/action_controller/metal/params_wrapper.rb:205:in process_action' actionpack (3.2.3) lib/abstract_controller/base.rb:121:inprocess'
actionpack (3.2.3) lib/abstract_controller/rendering.rb:45:in process' actionpack (3.2.3) lib/action_controller/metal.rb:203:indispatch'
actionpack (3.2.3) lib/action_controller/metal/rack_delegation.rb:14:in dispatch' actionpack (3.2.3) lib/action_controller/metal.rb:246:inblock in action'
actionpack (3.2.3) lib/action_dispatch/routing/route_set.rb:73:in call' actionpack (3.2.3) lib/action_dispatch/routing/route_set.rb:73:indispatch'
actionpack (3.2.3) lib/action_dispatch/routing/route_set.rb:36:in call' journey (1.0.4) lib/journey/router.rb:68:inblock in call'
journey (1.0.4) lib/journey/router.rb:56:in each' journey (1.0.4) lib/journey/router.rb:56:incall'
......
.....
....
...
..
.

NoMethodError (undefined method `closed?' for #<Hash:0x007fb5fc01a158>):

I am having this issue when I try to delete an image from a form it doesn't seem to work. it takes forever and i get that error.

NoMethodError: undefined method `closed?' for #<Hash:0x007fb9734acde0>
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/payload.rb:109:in `close'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:66:in `ensure in execute'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:66:in `execute'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:33:in `execute'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/cloudinary-1.0.39/lib/cloudinary/uploader.rb:153:in `call_api'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/cloudinary-1.0.39/lib/cloudinary/uploader.rb:45:in `destroy'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/attachinary-1.0.1/lib/attachinary/orm/file_mixin.rb:29:in `destroy_file'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `_run__3239959436735024129__destroy__4204010408305771159__callbacks'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:405:in `__run_callback'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:385:in `_run_destroy_callbacks'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activesupport-3.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/callbacks.rb:254:in `destroy'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/transactions.rb:236:in `block in destroy'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/transactions.rb:208:in `transaction'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.8/lib/active_record/transactions.rb:236:in `destroy'
    from (irb):3
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.8/lib/rails/commands/console.rb:47:in `start'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.8/lib/rails/commands/console.rb:8:in `start'
    from /Users/zacksiri/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.8/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'

Support MongoDB/Mongoid as storage engine

Mongodb has become very popular choice for new web development, and mongoid is becomming the defacto standard for working with it from rails, support this combination is much appreciated

Uncaught TypeError: [Object] has no method 'attachinary'

hello all. I followed the installation instructions on the main page

using this way of calling the file upload:
<%= f.attachinary_file_field :photo %>

but when I load my form, I get this javascript error :

$('.attachinary-input').attachinary(); Uncaught TypeError: Object [object Object] has no method 'attachinary'

Which leads me to believe that the fileupload widget doesn't load at all and ends up being the cause of my error when I submit my form.

I made sure that the .attachinary method is actually called by doing a simple "alert", which has been called. So, if I get it right, its the ".attachinary-input" declaration that isn't completed correctly despite the Object being created.

I just don't know how to fix this, any help appreciated

I'm using rails 3.2.6
windows 7
Ruby 1.9.3
attachinary 1.1.0
carrierwave 0.7.0

default image when missing

I am currently using carrierwave cloudinary integration and i really want to change over to attachinary instead. The only feature that is missing when compared to carrierwave is default images. I would have to put if/else logic all over my views to account for this. Would love to figure an elegant way to avoid that.

thx!

-karl

Version 1.0.1 requires javascript. Image upload exploit.

Sorry to be a pain in the butt.
I've been using Attachinary without Javascript in the previous release without any trouble. It seems that 1.0.1 now does uploads in the background, which is a great feature, but I would prefer to upload files without required the user have Javascript.

Additionally, preloading images bypasses any validation. A user could just keep uploading images without even making a submission.

Nested has_many form

I am using nested_form for a form that has many photos. Is it possible to use attachinary in this way? Would like the user to be able to easily click links add and remove photos within a form.

thx!

-karl

jquery plugin throwing error

I am getting an error when trying the jquery plugin.

https://skitch.com/karlbaum/erdug/screen-shot-2012-06-30-at-9.55.30-am

Seems to be coming form the acceptFileTypes method here:

Attachinary.prototype.initFileUpload = function() {
var options;
options = {
maxFileSize: 10000000,
dataType: 'json',
acceptFileTypes: new RegExp("^" + (this.$input.attr('accept').split(",").join("|")) + "$", "i"),
headers: {
"X-Requested-With": "XMLHttpRequest"
}
};
this.$input.attr('name', 'file');
return this.$input.fileupload(options);
}; 

I am using the simple_form helper method:

<%= f.input :photo, as: :attachinary %>

How can I add angle: :exif to the template after upload ?

I find a problem that when user upload in mobile, the cloudinary will show the image in incorrect orientation. So I find out that I have to use angle: :exif to counter the orientation issue like below.

<%= cl_image_tag(item.photos[0].path, { size: '125x125', crop: :fit , angle: :exif}) %>

But when I upload ,I find I have to update the upload template form as well to correctly show the uploaded image thumbnail in correct orientation.

I find out that I can edit the template in below link in library, but I not sure how can I pass the updated template content in $('.attachinary-input').attachinary(); to make it work.

Many Thanks for your help


I need to change from

   $.attachinary = {
      index: 0,
      config: {
        disableWith: 'Uploading...',
        invalidFormatMessage: 'Invalid file format',
        template: "<ul>\n  <% for(var i=0; i<files.length; i++){ %>\n    <li>\n      <img\n        src=\"<%= $.cloudinary.url(files[i].public_id, { \"version\": files[i].version, \"format\": 'jpg', \"crop\": 'fill', \"width\": 75, \"height\": 75 }) %>\"\n        alt=\"\" width=\"75\" height=\"75\" />\n      <a href=\"#\" data-remove=\"<%= files[i].public_id %>\">Remove</a>\n    </li>\n  <% } %>\n</ul>",
        render: function(files) {
          return $.attachinary.Templating.template(this.template, {
            files: files
          });
        }
      }
    };


To : 

   $.attachinary = {
      index: 0,
      config: {
        disableWith: 'Uploading...',
        invalidFormatMessage: 'Invalid file format',
        template: "<ul>\n  <% for(var i=0; i<files.length; i++){ %>\n    <li>\n      <img\n        src=\"<%= $.cloudinary.url(files[i].public_id, { \"version\": files[i].version, \"angle\": 'exif', \"format\": 'jpg', \"crop\": 'fill', \"width\": 75, \"height\": 75 }) %>\"\n        alt=\"\" width=\"75\" height=\"75\" />\n      <a href=\"#\" data-remove=\"<%= files[i].public_id %>\">Remove</a>\n    </li>\n  <% } %>\n</ul>",
        render: function(files) {
          return $.attachinary.Templating.template(this.template, {
            files: files
          });
        }
      }
    };

How to do this: multiple file upload with multiple model creation

How can I do this with Attachinary?

Given that one project can have many references and each reference can have one attachment and I want to have a single form with multiple file upload which would be able to create multiple references (one per attachement sent).

So basically, from the project page, the user clicks on the upload button, select a few files then submit them. Then the system creates X references as needed, each one with as single associated file.

My current solution does not work perfectly because the event 'fileuploaddone' fires for every file and using the callback in "render" does not work because it is called for each uploaded file and it contains an array of each file uploaded so far. (so if you upload 3 files, first time it contains 1 file, the 2, then 3). So is there an event (or way to) to fire the event a single time per file or once when they have all been uploaded?

Javascript error - public_id is undefined

I've got attachinary functioning almost perfectly. When I go to render a form with an already uploaded file, I'm getting the following Javascript error in the latest build of Chrome on OSX:

  Uncaught TypeError: Cannot call method 'match' of undefined -- jquery.cloudinary.js:135

I believe the public_id is undefined even though I see a valid public_id in the hidden value JSON data in the form. Any ideas here?

Base and eager transformations are not sent to cloudinary

I've customized the attachinary template to include some base transformations. Here's an example of what my template looks like:

<script rel="attachinary-template" type='text/html'>
    <ul>
    <% for(var i=0; i<files.length; i++){ %>
      <li>
        <img
          data-orig-width='<%= files[i].width %>',
          data-orig-height='<%= files[i].height %>',
          data-public-id='<%= files[i].public_id %>',
          src="<%= $.cloudinary.url(files[i].public_id, { "transformation": ["max_1600",{"effect":"contrast:5"},{"effect":"unsharp_mask:50"}], "eager": [{"width":96,"height":96,"crop":"thumb","gravity":"south","angle":"exif"},{"quality":85,"width":210,"crop":"limit","angle":"exif"},{"quality":85,"height":640,"width":640,"crop":"limit","angle":"exif"}], "version": files[i].version, "angle": 'exif', "format": 'jpg', "crop": 'thumb', "gravity": 'south', "width": 96, "height": 96 }) %>"
          alt="" width="96" height="96" />
        <a href="#" data-remove="<%= files[i].public_id %>">Remove</a>
      </li>
    <% } %>
    </ul>
  </script>

You'll notice there's a 'max_1600' named transformation there and some eager transformations. I noticed this stuff did not end up correctly done at cloudinary. I started digging into cloudinary.js, by placing debugging calls inside generate_transformation_string

I see that this method is entered no less than 4 times after I upload my image..each time from the Attachinary.addFile method. I'm not sure why that method is invoked 4 times for a single file upload. But the first time it is invoked, the transformation strings appear correct based on my logging.

    log("Cloudinary.js Base transformation", base_transformations);
    log("Cloudinary.js Named transformation", named_transformation);

By the second time, they are wiped out and those arrays are empty. I am digging further but this is mind boggling. First - why addFile fired 4 times, and second, why this transformation generation code is not idempotent.

Error when running rake attachinary:install:migration

When I follow the installation steps mentioned on this page (and running "bundle install"), the command "rake attachinary:install:migration" returns the following:

rake aborted!
Don't know how to build task 'attachinary:install:migration'

(See full trace by running task with --trace)

Pretty new to all this, so am I doing something wrong here?

[FEATURE] Preprocessing image size

Hi Ben,

it would be great if an "image resizing before sending to cloudinary" could be done in some way. (maybe "carrierwave like")

I think it do not need more explanation

best regards

toggling the file input

Should'nt the file input be hidden when there is already a picture and only show up when the user clicks on the 'remove' button?

Is it possible to limit file sizes?

I'm able to check the tempfile listed in the params with params[:post][:upload_file].tempfile.size but is it possible to limit the file size in the model?

Thank you

jCrop as cropping feature

Hi assembler,

what do you think of implementing "jCrop".

jCrop is an free jQuery small lib which does capture the coordinates of a picture, by drag and drop the canvas.
These coordinates can be added to the image model and can get called in the view "cloudinary_image_tag" to crop the images (or not)

What do you think of that, mentioned as a feature

It looks like a very easy improvement (like the mongoid one :-) )

http://deepliquid.com/content/Jcrop.html

best regards

and thanks for your great "gem"

Multiple upload doesn't work after move from 1.1.0 to 1.2.1

I can't upload many files in one action after updating attachinary & cloudinary. When I selected more then one file only one was uploaded

Gemfile.lock:
attachinary (1.1.0)
cloudinary (~> 1.0.40)

=>

attachinary (1.2.1)
  cloudinary (~> 1.0.41)

Adding images to existing array?

There seems to be no easy way to attach a new image to an array. If I have

has_attachments :photos

Then
model.photo_urls = [...] works

But what if I want to add an image to this array? I would have to get the urls to all the existing images first?
model.photo_urls = model.photos.map(&:fullpath) + ['new image path']

rails_admin runs first and has_attachment is missing

Because the has_attachment method is added on initialization of a rails_engine any other rails_engine that references those classes before attachinary has been initialized will cause an error. This happens for me with rails_admin as it references the UserProfile class.

/Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activerecord-3.2.3/lib/active_record/dynamic_matchers.rb:50:in `method_missing': undefined method `has_attachment' for #<Class:0x00000103f9e300> (NoMethodError)
    from /Users/karl/workspace/viewthespace/app/models/user_profile.rb:15:in `<class:UserProfile>'
    from /Users/karl/workspace/viewthespace/app/models/user_profile.rb:1:in `<top (required)>'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:469:in `load'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:469:in `block in load_file'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:639:in `new_constants_in'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:468:in `load_file'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:353:in `require_or_load'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:502:in `load_missing_constant'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:192:in `block in const_missing'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:190:in `each'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:190:in `const_missing'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/rake-0.9.2/lib/rake/ext/module.rb:36:in `const_missing'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/aws-s3-0.6.2/lib/aws/s3/extensions.rb:206:in `const_missing_from_s3_library'
    from /Users/karl/workspace/viewthespace/config/initializers/rails_admin.rb:91:in `block in <top (required)>'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/rails_admin-0.0.3/lib/rails_admin.rb:29:in `call'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/rails_admin-0.0.3/lib/rails_admin.rb:29:in `config'
    from /Users/karl/workspace/viewthespace/config/initializers/rails_admin.rb:34:in `<top (required)>'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:245:in `load'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:245:in `block in load'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:236:in `load_dependency'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:245:in `load'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/engine.rb:588:in `block (2 levels) in <class:Engine>'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/engine.rb:587:in `each'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/engine.rb:587:in `block in <class:Engine>'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/initializable.rb:30:in `instance_exec'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/initializable.rb:30:in `run'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/initializable.rb:55:in `block in run_initializers'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/initializable.rb:54:in `each'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/initializable.rb:54:in `run_initializers'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/application.rb:136:in `initialize!'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/railtie/configurable.rb:30:in `method_missing'
    from /Users/karl/workspace/viewthespace/config/environment.rb:5:in `<top (required)>'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:251:in `require'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:251:in `block in require'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:236:in `load_dependency'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:251:in `require'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/application.rb:103:in `require_environment!'
    from /Users/karl/.rvm/gems/ruby-1.9.3-p125-perf@viewthespace/gems/railties-3.2.3/lib/rails/commands.rb:40:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'```

Environment label tags

I'm curious as to what the significance of the environment flags (e.g. production_env) are for your purposes.

For us, we don't want to mix staging environment and production environment. It'd be awful to see some of the staging photos in production so without added support from @cloudinary, we'll just create a separate account for each with them.

Why are uploads sequential?

I see that attachinary.js forces sequentialUploads to be true. The jquery fileupload plugin's default is false (parallel uploads). Is there any reason to force sequential here?

undefined local variable or method `attachinary'

When calling the simple_form_helper:

<%= f.input :photo, as: :attachinary %>

I get:

/bundler/gems/attachinary-ac2ea8ecf135/lib/attachinary/view_helpers.rb:18:in `attachinary_file_field_tag'
/bundler/gems/attachinary-ac2ea8ecf135/lib/attachinary/simple_form.rb:15:in `input'
/gems/simple_form-1.5.2/lib/simple_form/components/label_input.rb:11:in `label_input'
/gems/simple_form-1.5.2/lib/simple_form/inputs/base.rb:68:in `block in render'
/gems/simple_form-1.5.2/lib/simple_form/inputs/base.rb:66:in `each'
/gems/simple_form-1.5.2/lib/simple_form/inputs/base.rb:66:in `render'
/gems/simple_form-1.5.2/lib/simple_form/form_builder.rb:95:in `input'
app/views/user_profiles/edit.html.erb:16:in `block in _app_views_user_profiles_edit_html_erb__2701085985821458579_2188684080'
/gems/actionpack-3.2.3/lib/action_view/helpers/capture_helper.rb:40:in `block in capture'
/gems/actionpack-3.2.3/lib/action_view/helpers/capture_helper.rb:187:in `with_output_buffer'
/gems/haml-3.1.4/lib/haml/helpers/xss_mods.rb:109:in `with_output_buffer_with_haml_xss'
/gems/actionpack-3.2.3/lib/action_view/helpers/capture_helper.rb:40:in `capture'
/gems/haml-3.1.4/lib/haml/helpers/action_view_mods.rb:105:in `capture_with_haml'
/gems/actionpack-3.2.3/lib/action_view/helpers/form_helper.rb:606:in `fields_for'
/gems/client_side_validations-3.1.3/lib/client_side_validations/action_view/form_helper.rb:45:in `fields_for'
/gems/actionpack-3.2.3/lib/action_view/helpers/form_helper.rb:377:in `form_for'
/gems/haml-3.1.4/lib/haml/helpers/action_view_mods.rb:183:in `form_for_with_haml'
/gems/haml-3.1.4/lib/haml/helpers/xss_mods.rb:132:in `form_for_with_haml_xss'

.

.

undefined local variable or method `user'

At first, glad, you did it with "mongoid"

I really, really appreciate it.

But I struggle on the form

With this

<%= f.attachinary_file_field_tag 'location[avatar]', user, attachinary: avatar %>

I got this:

ActionView::Template::Error (undefined local variable or method `user' for #<#<Class:0x007fc82f44e748>:0x007fc8302cc540>): 

all done like in the readme...

User model exists...

and contains

has_attachment  :avatar, accept: [:jpg, :png, :gif]

I do no use simple_form, should I?

Allow upload via URL

@assembler, what do you think about adding this to the bindEventHandlers?

@$input.bind 'attachinary:urladded', (event, data) =>
  @$input.fileupload("option", "formData").file = data
  @$input.fileupload("add", files: [data])

  delete @$input.fileupload("option", "formData").file

Is that possible to bind the fileuploadstart event in jquery ?

In jquery mobile environment, the submit button has special handle that it is not directly show as the input submit tag , so the following doesn't work.

$submit.data('old-val', $submit.val());
$submit.val(_this.config.disableWith);

I have tried to use the following code to bind the fileuploadstart but it seems not working.

    $('.ui-submit').find('.ui-btn-inner').find('.ui-btn-text').bind('fileuploadstart', function(e, data) {  
            $('.ui-submit').find('.ui-btn-inner').find('.ui-btn-text').text("Uploading..."); 
    });

Range error: Maximum call stack exceeded

Just started using attachinary, but I am getting a recursion somewhere, I assume.

when I do this:
<%= f.file_field :images %>
This works fine. replacing with attachinary
<%= f.attachinary_file_field :images %>

causes the error. In Chrome it causes the inspector to crash. this is the error from Safari. It points at this line in query
function isArraylike( obj ) {
var length = obj.length,
type = jQuery.type( obj ); <---------

What could I be doing to cause this? I have no idea where to start. I have followed assembler's instructions on github, reviewed and re-reviewed the steps.

In my model, I have added
has_attachments :images, maximum:4

I am on rails 3.2

How to pass a tranformation name in the input form

Hi,
i'm trying to pass a transformation name (i want to store a lower version(size,weight) of the file and not the orginal submitted file) in the simple_form input and after various tries i can't get it working. could you please help me ?
thanks !

Support for Rails 4?

Use of attr_accessible has been deprecated in Rails 4 -- are there plans to update this Gem soon to support it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.