Build a Dropbox-like File Sharing Site with Ruby on Rails: Premium
plus

Build a Dropbox-like File Sharing Site with Ruby on Rails: Premium

Tutorial Details
  • Topic: RoR
  • Difficulty: Advanced
  • Estimated Completion Time: 2 Hours
Download Source Files

In this massive and advanced Premium Nettuts+ tutorial, we’ll learn how to build a file-sharing web application, like Dropbox, using Ruby on Rails. Become a Premium member to read this tutorial, as well as hundreds of other advanced tutorials and screencasts.

Sign Up Page
Folder Deleted
Invite Form
Shared Folder View
Sign Up Page

Join Net Premium

NETTUTS+ Screencasts and Bonus Tutorials

For those unfamiliar, the family of Tuts+ sites runs a premium membership service. For $19 per month, you gain access to exclusive premium tutorials, screencasts, and freebies from Nettuts+, Psdtuts+, Phototuts+, Aetuts+, Audiotuts+, Vectortuts+, and CgTuts+ For the price of a pizza, you’ll learn from some of the best minds in the business. Become a Premium member to read this tutorial, as well as hundreds of other advanced tutorials and screencasts.

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Kyle

    Awesome! Can’t wait to go thru this.

    Thanks for the tut.

  • http://www.emersonlackey.com Emerson

    So sweet, I’ll definitely be checking this tutorial out! I’ve been really enjoying Rails 3 this past month. Also, I dig the fact that you’re using Ryan Bate’s Nifty Scaffold!

    • http://www.phyowaiwin.com Phyo Wai Win

      Thanks.

      Yes, I love using the Nifty Scaffold. Who doesn’t? :)

  • http://www.helloeverything.co.uk David – Web Designer

    Excellent, looking forward to this tut, please keep up the high quality Ruby on Rails tuts (as many as possible!) please…

  • http://demicloud.com Thomas Heinrichsdobler

    Hi there,
    I’m afraid there’s a glitch in the tutorial. When the instructions say “Now, let’s create our first model, User, using “devise”.”, the code block is simply the same code block as before, where routes are modified.
    Perhaps you could look into this.

    Thank you,
    Thomas

    • http://www.phyowaiwin.com Phyo Wai Win

      Hi Thomas,

      Thanks for spotting and letting us know about it. The command should be rails g devise User

      I’ll ask Jeffrey to fix this.

      Sorry about that.

      • http://www.rockhopperdigital.com Benjamin Zalasky

        This is exactly what I was looking for… : )

      • Craig

        Hmmm, ive just subscribed and downloaded to follow the tut. This is still as per Thomas’s comment – can you let me know what should be there instead?

        Thanks

      • Stewart

        Thanks! That’s what I was looking for,

      • Jay Bradfield

        The following issue is still there:

        “When the instructions say “Now, let’s create our first model, User, using “devise”.”, the code block is simply the same code block as before, where routes are modified.”

        Thanks for posting the proper code here, I found it by googling “Now, let’s create our first model, User, using “devise”.”

        However, I am sure it would help others to just have the right code snippet in the tutorial.

  • http://www.rebatesense.com RebateSense

    Wanted to take on RoR for sure and so gonna spend the $$ for the membership for sure this time. Looking forward to it. An end to end video tut would be ++

  • Ron Or-El

    Hello there, I got to step 4: Uploading Files but when I try to upload a file I’m getting this message:

    Template is missing

    Missing template assets/create with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths “/Users/ronor-el/sharebox/app/views”, “/Users/ronor-el/.rvm/gems/ruby-1.9.2-p136/gems/devise-1.1.5/app/views”

    Any idea on how to fix it and proceed from here?

    Thanks a lot.

    • http://www.phyowaiwin.com Phyo Wai Win

      It seems you have changed something in your AssetController, which now redirects to assets/create.html.erb that doesn’t exist by default.

      In “create” action of AssetController, you should have something like this near the end.

      if @asset.save

      redirect_to @asset
      else
      render :action => ‘new’
      end

      You’ve probably have changed something there. If you change it back to what it was before like that, you should be fine.

      • Ron Or-El

        Indeed. At first what I got was this error:

        /Users/ronor-el/sharebox/app/controllers/assets_controller.rb:19: syntax error, unexpected tDOT3, expecting keyword_end

        ^
        /Users/ronor-el/sharebox/app/controllers/assets_controller.rb:28: syntax error, unexpected tDOT3, expecting keyword_end

        ^
        /Users/ronor-el/sharebox/app/controllers/assets_controller.rb:33: syntax error, unexpected tDOT3, expecting keyword_end

        ^

        So I deleted those ‘…’ from the code and then I’m getting the Template Missing error.

        I’m guessing there are some pieces of code missing there right? I could try and copy it from the source file but then I would have learnt nothing :)

        This is how this section shows up in the tutorial:
        class AssetsController < ApplicationController
        before_filter :authenticate_user! #authenticate for users before any methods is called

        def index
        @assets = current_user.assets
        end

        def show
        @asset = current_user.assets.find(params[:id])
        end

        def new
        @asset = current_user.assets.new
        end

        def create
        @asset = current_user.assets.new(params[:asset])

        end

        def edit
        @asset = current_user.assets.find(params[:id])
        end

        def update
        @asset = current_user.assets.find(params[:id])

        end

        def destroy
        @asset = current_user.assets.find(params[:id])

        end
        end

        Thanks a lot for that one. It’s really good to get some hands on Ruby tutorials.

      • http://www.phyowaiwin.com Phyo Wai Win

        Ah, The “…” in that case is meant for all the rest of the code inside each action there. You shouldn’t have deleted those lines of code actually. The “…” is not meant to be taken literally there I am afraid.

        Most codes in the source files are highly commented so you’ll be able to pick it up from there quickly. Just follow along the tut.

        In future tutorials, I’ll be sure to explain what those “…” are actually meant for to minimize the confusion.

      • Ron Or-El

        Oh ok I got it now. Works now. Thanks!

      • Ron Or-El

        After further investigation I found out what was the problem. In section 4 you specify that this code:

        attr_accessible :user_id, :uploaded_file

        belongs_to :user

        #set up “uploaded_file” field as attached_file (using Paperclip)
        has_attached_file :uploaded_file

        validates_attachment_size :uploaded_file, :less_than => 10.megabytes
        validates_attachment_presence :uploaded_file

        should be inserted in app/models/user.rb but it should be app/models/asset.rb

        That fixed things for me.
        Cheerz :)

  • http://www.drivvedwebbyra.se Fredrik

    hmmm i might have to get premium from now on.. really want to learn this!

  • alex

    is there a way to have this dropbox like site auto update an offline folder the same way that dropbox does?

    • http://www.phyowaiwin.com Phyo Wai Win

      That’ll involve some native OS application (code) to do the sync the folders from your machine to the site. Dropbox has softwares from Windows, Mac, Linux and even Mobile.

      You might probably be able to get away with Flash integration on it but it won’t be offline like you said.

  • Julio

    When are you gonna put this tutorial on the marketplace? I want it so bad! …

    • http://www.phyowaiwin.com Phyo Wai Win

      I did try to put it up there about 2 days ago. But it got rejected because they will put all Premium tuts in this account http://marketplace.tutsplus.com/user/NetPremium . The process has started since the beginning of the year. So I am afraid you have to wait to buy it from that account.

      Thanks.

  • Jacob Warren

    When I get to step 5 “Integrating Amazon S3,” I run into a weird UnknownAttributeError in AssetsController#Create, where the unknown attribute is “uploaded_file”

    It only happens when I change my code to :

    has_attached_file :uploaded_file,
    :path => “assets/:id/:basename.:extension”,
    :storage => :s3,
    :s3_credentials => “#{Rails_ROOT}/config/amazon_s3.yml”,
    :bucket => “shareboxapp”

    It also doesn’t upload to the S3 server.

    • http://www.phyowaiwin.com Phyo Wai Win

      Do you have :uploaded_file symbol in your attr_accessible list like below (mentioned in Step 4)?
      attr_accessible :uploaded_file

      Also, you should make sure you create a uniquely-named bucket in your S3 account manually first and use it in your code.

      • Juan

        I’ve the same problem, when try to upload. I’ve already put the :uploaded_file symbol as attr_accessible and create a unique bucket. Plus in the assets index I’ve this error too: undefined method `file_name’ for #

        Thanks man, amazing tut!

      • Juan

        Ok, so the undefined method `file_name’ in the Assets index was because I’ve a file already uploade in the rails asset folder. But the problem unknown attribute: uploaded_file is still there.

        Thanks,

      • http://www.cosly.com John Stevens

        Yes I have the same issue.
        ActiveRecord::UnknownAttributeError (unknown attribute: uploaded_file):
        app/controllers/assets_controller.rb:18:in `create’

        I also have an european bucket and for that I fixed it with the solution rkachowski came up with.

        has_attached_file :uploaded_file,
        :path => “assets/:id/:basename.:extension”,
        :storage => :s3,
        :s3_credentials => “#{Rails_ROOT}/config/amazon_s3.yml”,
        :bucket => “shareboxapp”,
        :s3_options => {
        :server => “s3-eu-west-1.amazonaws.com”
        }

  • Julio

    But don’t give up trying, please!! (=

  • eoy

    Really excellent tutorial, I’m hoping to see more Rails content here!

  • rkachowski

    Thanks for the tutorial! It’s exactly what I was looking for.

    Aside from hitting the problems mentioned above in the comments, there’s also quite a problem with accessing eu based S3 buckets via paperclip. After a few hours of searching I came across this post http://davidjrice.co.uk/2010/10/26/amazon-s3-european-bucket-issues-paperclip-attachment_fu.html which outlines the process to reenable that functionality. The step is optional but that would have floored me if i couldn’t get it working!

    thanks again

    • http://www.phyowaiwin.com Phyo Wai Win

      Good find there! I didn’t realize about that since I was using non-eu based buckets. Thanks.

  • Jun

    Hello there, great tutorial.

    I’ve had no problem following it, although once finished and after uploading a couple of files and playing with it I end up with the following exception:

    undefined method ‘ancestors’ for nil:NilClass

    The application trace points me out at the two following lines: app/models/user.rb
    folder.ancestors.each do |ancestor_folder|
    and displays the error ‘has_share_access?’

    and app/controllers/assets_controller.rb in the ‘get’ action
    asset ||= Asset.find(params[:id]) if current_user.has_share_access?(Asset.find_by_id(params[:id]).folder

    I’ve been trying to fix that error for days without success.

  • Kent

    I’m just getting all kinds of errors, one minute it works and the next minute it don’t.

    Signed up for the $9 month membership ONLY just to get this tut and script and looks like I wasted my money!

  • cloudboxx

    I’m getting errors on top of errors when trying to upload a file. I can create a folder fine just get error on uploading files.

    I paid $9 for this membership JUST to get this tut and script and it don’t work.

    What a waist on money!

  • http://jayphen.com Jayphen

    Alas I’m stuck at the same point above with the uploaded_file error.

    • Jayphen

      Okay, figured it out.

      In /app/models/asset.rb, make sure s3 credentials are set as such:

      :s3_credentials => “#{RAILS_ROOT}/config/amazon_s3.yml”

      In the tutorial, Rails is lowercase in RAILS_ROOT

  • Kurt

    when i try to upload a file i get this – http://cl.ly/5Jqs http://cl.ly/5IuD

  • http://orryb.com Orry

    Thanks for this great tutorial! So far it’s been great but I’ve found lots of little errors/typos that have driven me crazy.

    Right now, I’m stuck on step 13 trying to get the share button to send an email from the modal dialogue. In the Home Controller you say to add this :

    #since this action is mainly for ajax (javascript request), we’ll respond with js file back (refer to share.js.erb)
    respond_to do |format|
    format.js {
    }
    end

    shouldn’t it be share,js? I’ve tried changing it, but I still can’t get it work. Any ideas?

    • Fernando Aleman

      I actually ran into this same error and it turns out the error is actually in the “share.js.erb” file. The solution is to go into the “share.js.erb” file and change:

      $(“#container”).prepend(”
      Successfully shared the folder
      “);

      to:

      $(“#container”).prepend(“<div id=’flash_notice’>Successfully shared the folder</div>”);

      Hope this helps!

  • http://emilkjelsrud.com Emil Kjelsrud

    Hi! Thanks for a great tutorial! I was able to follow along for the most part, but I’m really struggling to get the shared folders working. When I’m suppose to paste the following code block in the Folder Model, I get a quite expected error.

    #a method to check if a folder has been shared or not
    def shared?
    !self.shared_assets.empty?
    end

    When this code is executed from the index view to determine if the folder is shared or not, it throws the following error:

    undefined method `shared_assets’ for #<Folder:0xa14b7ac>

    And that’s quite right isn’t it? The tutorial never defines the shared_assets method. Can someone please help me? I would love to get this app rolling :)

  • http://emilkjelsrud.com Emil Kjelsrud

    Never mind… got it working by changing !self.shared_assets.empty to !self.shared_folders.empty :)

    Thanks anyway
    Cheers

  • http://emilkjelsrud.com Emil Kjelsrud

    @Orry
    I know its been a while but if anyone else have the same problem I’ll post the solution here.
    in share.js.erb change to following line:

    $(“#container”).prepend(“Successfully shared the folder”);

    to

    $(“#container”).prepend(‘Successfully shared the folder’);

    It’s the nested quotation marks that’s causing the headache ;)

  • Steven

    Does this tutorial have a test suite as part of it?

    • http://emilkjelsrud.com Emil Kjelsrud

      Sadly, it doesn’t.

  • http://www.EugeneFineHomes.com Sean Pearson

    I already use Dropbox, but I can’t wait to give this a try.

  • Fernando Aleman

    I think this tutorial is great for the most part. I have found some of the same errors above and have been correcting my own downloaded tutorial as I go. I have been able to fix most of the errors that I found in the tutorial, but there is only one thing I can’t figure out. When I use Amazon S3 for file storage, I am able to upload the files and see that they uploaded correctly on Amazon S3. However, once I click on the link to download the file, the file gets corrupted and I am not able to open it on my local computer. This is the same for images files, pdf’s, docs etc. Once again, I verified that the files did appear correctly on Amazon S3, so it seems there is an error somewhere on the code to download the file. Has anyone else experienced this? Does anyone have a fix for this?

    • Dainel Vera

      I just finish the tutorial and im having the same problem, they upload to s3 just fine, but when downloaded they get corrupted

    • Andy Mortimer

      Did you ever manage to get the image download part to work I get the exact something I click the link and then the image is corrupt

      • Dainel Vera

        no, if i use

        asset.uploaded_file.url it works, but is gives the s3 link.

        but i do

        download_url(asset) like he said in the tutorial, it does hide the link but it corrupts the files.

      • Dainel Vera

        also error from the url i being cause by this, still dont have a fix

        data = open(URI.parse(URI.encode(asset.uploaded_file.url)))

  • Dainel Vera

    When i visit /users/sign_out im getting the following error, has this happen to anyone ??

    Routing Error

    No route matches “/users/sign_out”

    • Dainel Vera

      Got it to work, just change

      to

      ‘delete’ %>

  • Tharnid

    Routing Error
    No route matches “/users/sign_out”

    I am getting that where do I change it to ‘delete’ %>

    I didn’t see anything about creating/editing the sign_out view

    • Dainel Vera

      the complete line is

      <%= link_to “Log out”, logout_path, :method => ‘delete’ %>

  • ryan

    @Jun, regarding the

    undefined method ‘ancestors’ for nil:NilClass

    error you’re receiving. I had the same problem, and noticed that it was only happening for files that were in the top level folder (which, actually, isn’t a folder… and that’s the issue). If you browse into your database, you’ll see that assets in the top level folder have a “NULL” value for its parent folder_id.

    In my particular case, I don’t want people uploading files to the top level, so I’m removing the upload button there, and each asset with the be assigned a folder_id by the nature of where they are uploaded. If you want assets in the top-level, I’d recommend making that level an official folder so it has a folder_id assigned to the asset.

  • Cindy

    @Dainel I’m experiencing a similar error at

    data = open(URI.parse(URI.encode(asset.uploaded_file.url)))

    The error I get is : “can’t convert URI::Generic into String”. Have you found a fix for it?

  • Dom

    Fantastic Tutorial. For the most part it was a breeze and was able to work through the errors on my own. However, I am also stuck on step 13 and emailing shared folders.

    When I click the “Share” button next to the file the dialogue opens up fine. When I click the “SHARE” button on the dialogue WITHOUT typing anything in the email or message field, it closes and the alert shows up correctly. The icons also change.

    The problem is when I enter an email address and message, for some reason, the “SHARE” button no longer works or closes the dialogue. The folder seems to be set as shared in the background but but the dialogue just wont close. Emails aren’t sent, either. It feels like a Javascript error to me. I just can’t find it.

    Here is my share.js.erb file:

    //closing the dialog box
    $(“#invitation_form”).dialog(“close”);

    //making sure we don’t display the flash notice more than once
    $(“#flash_notice”).remove();

    //showing a flash message
    $(“#container”).prepend(“&ltdiv id=’flash_notice’&gtSuccessfully shared the folder&lt/div&gt”);

    //Removing the css class ‘folder’
    $(“#folder_&lt%= params[:folder_id] %&gt”).removeClass(“folder”);

    //Adding the css class ‘shared_folder’
    $(“#folder_&lt%= params[:folder_id] %&gt”).addClass(“shared_folder”);

    Here is my application.js file:

    $(function () {
    //open the invitation form when a share button is clicked
    $( “.share a” )
    .button()
    .click(function() {

    //assign this specific Share link element into a variable called “a”
    var a = this;

    //First, set the title of the Dialog box to display the folder name
    $(“#invitation_form”).attr(“title”, “Share ‘” + $(a).attr(“folder_name”) + “‘ with others” );

    //a hack to display the different folder names correctly
    $(“#ui-dialog-title-invitation_form”).text(“Share ‘” + $(a).attr(“folder_name”) + “‘ with others”);

    //then put the folder_id of the Share link into the hidden field “folder_id” of the invite form
    $(“#folder_id”).val($(a).attr(“folder_id”));

    //the dialog box customization
    $( “#invitation_form” ).dialog({
    height: 300,
    width: 600,
    modal: true,
    buttons: {
    //First button
    “Share”: function() {
    //get the url to post the form data to
    var post_url = $(“#invitation_form form”).attr(“action”);

    //serialize the form data and post it the url with ajax
    $.post(post_url,$(“#invitation_form form”).serialize(), null, “script”);

    return false;
    },
    //Second button
    Cancel: function() {
    $( this ).dialog( “close” );
    }
    },
    close: function() {

    }
    });

    return false;
    });
    });

  • Dom

    Amazon is corrupting my files, too. Grrr. I gotta say again, though, one of the best tutorials I have come across. For a tut this massive and long it was surprisingly free of typos and errors. Thanks again.

  • Richard Lewis

    Hi

    The tutorial was exactly what i was looking, but like everyone else encountered numerous problems, however got there in there end and wouldnt of known where to start if it wasnt for this tutorial.. Anyway my problem now is that when i upload a document within a folder I can then view that document in every folder in the sharebox? Has anyone else experienced this or does anyone have a solution?

    Thanks

  • http://eol-store.com/ Leon T

    Could someone upload it for me to use. I dont want to make an account.

  • https://www.facebook.com/ShadowLegion24 JohnRey

    is this still working ? and if i get premium membership will they will provide support in case i have questions about this ? thanks i really need this ^_^

  • jason

    anyone else get this..

    TypeError: ‘undefined’ is not a function (evaluating ‘$( “.share a” )

    when clicking on the ‘share’ link next to a folder. URL ends up with a # at the end but no change otherwise in the screen.