Showing posts with label File Upload. Show all posts
Showing posts with label File Upload. Show all posts

Sunday, 1 September 2013

Some Carrierwave Tip n Tricks

Finally wait is over I mean after nearly a rough patch of virtually no post for an year I back with a post again

As the title suggest it with regards to some tips and tricks that I manage to pull on carrierwave when working on a project

A) Upload Simultaneously to File and S3

I know there are tons of way to do this like upload the file first to server and then using the background process upload it to S3 blah blah .
Even directly upload to S3 is also an options since AMAZON S3 allow CORS

Well all this work great but I kind of not want to do them perhaps, may try some other approach
(Mind you nothing against the other approach mention thus after or already exists)

So what is my approach well basically nothing all you have to do customize your uploader a bit (not heavy customization though )

Consider this is your standard uploader look like  with default storage as :file

class MyUploader < CarrierWave::Uploader::Base
  storage :file
  ... blah ...
  ... blah ... 
  ... blah ... 
end
Now to simultaneously upload it to S3 all you have to do is place this in your uploader.
 version :s3_version do
     storage :fog
     def full_file_name
       super.sub(/s3_version_/,'')
     end
   end
So your uploader finally look like this
class MyUploader < CarrierWave::Uploader::Base
   storage :file
    ... blah ...
    ... blah ...

   version :s3_version do
     storage :fog
     def full_file_name
       super.sub(/s3_version_/,'')
     end
   end
end

That it define a version :s3_version (virtually any name you want) and then use storage as :fog in it (make sure to change the REGULAR EXPRESSION incase you chose a different version name other then s3_version)

Note : Also make sure to add the FOG setting for Carrierwave (S3 is just taken as an example it would work it all storage that fog provide)

Now most of you would argue that if say S3 isn't responding/ something goes wrong in S3 over net, then your local storage goes for a toss and I agree completely with that to so I urge viewer to please take a note of this . Well for me I happy taking that risk on my part . :)


B). Delete the record but don't delete the attachment

Well not all would agree with me on this but there are time when we been ask to delete the uploader record but not delete the file stored :)

There could be many reason like in my case there was a requirement that we need to retain the original copy of the client registered agreement even though the client not longer exists

As said there exists even a dozen tons of ways to achieve this as well but let me show you how I manage to pull off this.

All I did is I overwrite the method remove!  in my uploader and I also define a attr_accessor against my model (i.e attr_accessor :keep_file on my model)

Enough said time for code
class MyUploader < CarrierWave::Uploader::Base 
  def remove!
     unless model.keep_file
       super
     end
  end
end


Now to secure the storage file and only delete the record all I did is set  :keep_file => true and rest is taken care.

What I mean is record are destroyed but not the file from the storage system with this

There is another approach but I now tried and tested it that one would to overwrite the remove? 
method  something like this (Note I haven't tested this )
class MyUploader < CarrierWave::Uploader::Base 
  def remove?
    false
  end
end

C). Custom the CarrierWave Error Message

Ever since I question/answered my own question I'm seeing that I'm getting a lot of traction on it . What I have asked for is -

How to change the Carrierwave error message and set your own ?.

Well clearly the answer for that is define a key/value in your en.yml for desired carrierwave error message and that it

e.g Let say Carrierwave default message on extensions whilelists valdations is this
You are not allowed to upload %{extension} files, allowed types: %{allowed_types}

Now want is to change reason (reason with held with me :) ) . So all I have to do is this

in my en.yml define something like this
en:
  errors:
    messages:
       extension_white_list_error: 'My Custom Message'

A full list of carrierwave key/value pair can be found over here

That it guys hope you liked the tricks and found it useful

Thank You






Friday, 20 April 2012

process => process in CarrierWave

Well this one is for all those who ever used CarrierWave for uploading there files(no matter which files). Now how many of us had actually extended Carrierwave to process a file (i.e writing you own processing for the file e.g In term of image reducing or increasing the quality of image)

I happen to stumble upon this as all I want was to process a csv file which is suppose to be stored in Amazon S3(on upload) using CarrierWave .

Now the aim was to extract all the information from the CSV (sound simple right ) . Yes it is but I resist the thought of putting the file in Amazon S3 server(first) and then downloading the file and to my server and then extract the data from the CSV file and dump it into database. I want it to be more real time(since the file are small size file) I want user to know that the data in CSV is proper or not and can or cannot data in the CSV can be dumped into database citing validations.

So I realized back when I used to consider PaperClip as my first options, paperclip used to provide me options for processing the file here the link if you want to do it for paperclip Good Luck.

Yes I knew now I have to achieve something of this sort ,but how

Well looking at the uploader file generated by CarrierWave I found out that there is process method ,ok now what how do you apply it.
Inspecting the CarrierWave source code ( for default resize process ) I found out that all you need is to define a method wrapped inside a module .

Now it got it.

So to define a custom processing all you need is to define method wrapped in module and include that module in CarrierWave and pass your process method as an argument to CarrierWave process method define in uploader file
Here how I achieve this.
Inside CarrierWave Uploader
class AssetUploader < CarrierWave::Uploader::Base
   include CarrierWave::CSVProcessor
   process :process_csv
end

That it that all you need to do to define your own file processing.
Just go ahead an define your process_csv method inside module define in file inside config/initializers Voila mission accomplished.
Here how I did it (my file config/initializers/csv_processor.rb)
module CarrierWave
  module CSVProcessor
    def process_csv
      ....
      ....
      ....
    end
  end
end
Go hack now with CarrierWave.

By the way if you want to explore the thought of providing custom error message for CarrierWave here a link that you might want to look at

Hope that it help you in someway or other

What did I learn today?

Welcome to the what did I learn today series. The intention of this blog spot is to compose the stuff that I learnt day-to-day basics and jo...