Reputation: 14068
I have the following helper method that I'm using to upload some records to Dropbox. For each of the three models (logbooks, aircraft, and approaches), I'm doing the exact same thing. I'd like to make this more DRY and only have the code once, but I don't understand how to reference a model in an abstracted way.
Any recommendations?
#------------------------------------------------------------
# Upload entries to Dropbox
#------------------------------------------------------------
def upload_items(items, folder, client)
# Go through each item and upload it to Dropbox
items.each do |item|
if folder == 'logbook'
# Get the file from the database to upload
@logbook = current_user.logbooks.find_by_sync_id(item)
# Upload it
uploaded_file = client.put_file("/logbook/#{item}.json",@logbook.to_json, overwrite = true)
# Reset the updated_flag in the database
@logbook.update_attributes(updated_flag: 0)
elsif folder == 'aircraft'
# Get the file from the database to upload
@aircraft = current_user.aircrafts.find_by_sync_id(item)
# Upload it
uploaded_file = client.put_file("/aircraft/#{item}.json",@aircraft.to_json, overwrite = true)
# Reset the updated_flag in the database
@aircraft.update_attributes(updated_flag: 0)
elsif folder == 'approaches'
# Get the file from the database to upload
@approach = current_user.approaches.find_by_sync_id(item)
# Upload it
uploaded_file = client.put_file("/approaches/#{item}.json",@approach.to_json, overwrite = true)
# Reset the updated_flag in the database
@approach.update_attributes(updated_flag: 0)
end
end
end
Ruby 1.9.3, Rails 3.2.8
Upvotes: 0
Views: 137
Reputation: 23566
I would write this that way:
class DropboxUploader
attr_reader :folder, :client
def initializer(folder, client)
@folder = folder.to_sym
@client = client
end
def upload(items)
items.each { |item| update item }
end
def resource_name
folder.to_s.pluralize.to_sym
end
def file_path
"/#{folder}/#{item}.json"
end
private
def find_resource_for(item)
current_user.public_send(resource_name).find_by_sync_id(item)
end
def update(item)
resource = find_resource_for item
client.put_file(file_path, @aircraft.to_json, true)
resource.update_attributes(updated_flag: 0)
end
end
Not only DRY but more objective also (and easier to test).
EDIT: Usage goes as follows:
uploader = DropboxUploader.new(:aircraft, @client)
uploader.upload(@items)
Upvotes: 1
Reputation: 6808
This will do the job.
The critical part below is current_user.public_send(folder.to_sym)
which takes the folder name and converts it to a message to send to the current_user.
#------------------------------------------------------------
# Upload entries to Dropbox
#------------------------------------------------------------
def upload_items(items, folder, client)
# Go through each item and upload it to Dropbox
items.each do |item|
# Get the file from the database to upload
resource = current_user.public_send(folder.pluralize.to_sym).find_by_sync_id(item)
# Upload it
uploaded_file = client.put_file("/#{folder}/#{item}.json",resource.to_json, overwrite = true)
# Reset the updated_flag in the database
resource.update_attributes(updated_flag: 0)
end
end
Upvotes: 1
Reputation: 7078
This should be the direction:
Your Controller:
#------------------------------------------------------------
# Upload entries to Dropbox
#------------------------------------------------------------
def upload_items(items, folder, client)
# Go through each item and upload it to Dropbox
items.each do |item|
upload_to_dropbox(items, folder, client)
end
end
ApplicationController:
def upload_to_dropbox(item, folder, client)
# Get the file from the database to upload
@model = current_user.send(folder).find_by_sync_id(item)
# Upload it
uploaded_file = client.put_file("/aircraft/#{item}.json",@model.to_json, overwrite = true)
# Reset the updated_flag in the database
@model.update_attributes(updated_flag: 0)
end
Upvotes: 0