简体   繁体   中英

Paperclip - dropbox. How can I setup a conditional has_attached_file?

I am creating an application that lets users store data in their personal dropbox in a protected folder that the application controls. So each user needs to store and access files in their own personal dropbox account.

To do this I'd like to leverage the paperclip-dropbox gem for storage. It allows paperclip to directly upload to dropbox: https://github.com/janko-m/paperclip-dropbox .

Here is the code that sets the authorization information for the paperclip-dropbox gem. NOTE : current_user does not work at the moment. I'm just putting that there to outline what would need to happen for the current setup to work.

Image.rb

has_attached_file :avatar,
                  :storage => :dropbox,
                  :dropbox_credentials => {app_key: DROPBOX_KEY,
                                           app_secret: DROPBOX_SECRET,
                                           access_token: current_user.token,
                                           access_secret: current_user.secret, 
                                           user_id: current_user.uid, 
                                           access_type: "app_folder"}

Notice the dropbox authentication requires the current_user to get that particular set of credentials.

I know that the current_user is not supposed to be accessed from the model and I'd like to keep it that way so could anyone help me figure out how to do that with this current setup? Or suggest a better alternative?

Basically, I need to conditionally change the access_token, access_secret, & user_id on a per user basis.

Thanks!

I'm going to answer my own question because the other answers were too vague to accept - although they were on the right path. I think the community would prefer an answer with more code to back it up.

So here goes. To change the has_attached_file on a dynamic basis, you have to have a user_id column in the attachment model so that you're not calling current_user (which isn't possible without ugly hacks). Then you need a belongs_to as well to complete the user association. Let's assume I'm attaching an audio file to a Song model for this example.

The key to getting the dynamically set variables is to initialize the attachment with the after_initialize callback.

Song.rb

belongs_to :user    
has_attached_file :audio
after_initialize :init_attachment

def init_attachment
    self.class.has_attached_file :audio,
    :storage => :dropbox,
    :dropbox_credentials => {app_key: DROPBOX_KEY,
                             app_secret: DROPBOX_SECRET,
                             access_token: self.user.token,
                             access_token_secret: self.user.secret,
                             user_id: self.user.id
                             access_type: "app_folder"},
    :dropbox_options => {}
end

You are, of course, free to setup your association differently, but this is a working code example for the question posed.

I think first thing you should do is to set association Image.belongs_to :user - you could then use simply user.token etc. instead of referencing current_user .

Now the hard part. You can't simply type:

access_token: user.token

because self is Image class which simply doesn't respond to user method (it's instance method). My idea is to modify this gem so it could accept lambdas as arguments with attachment instance (for example) passed to this lambda on call. The problem is I don't know if it's hard to modify this gem that way yet.

Just found this resource you might gain benefit from: Ruby on Rails - Paperclip and dynamic parameters

More specifically for you, I thought this might shed some light onto what you're doing:

# AssetsController
def create
  @project = Project.find(params[:project_id])
  @asset = @project.assets.build(params[:asset])
  @asset.uploaded_by = current_user

  respond_to do |format|
    # all this is unrelated and can stay the same
  end
end

Notice the "@asset.uploaded_by" is set in the controller? Maybe you could pass similar variables to your model? I don't know how I would do it specifically, but you'd basically be able to set the save options before you try and save the file, giving you the ability to dynamically set the options

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM