Skip to content

Instantly share code, notes, and snippets.

@jacob-s-son
Created April 15, 2014 16:46
Show Gist options
  • Save jacob-s-son/10746739 to your computer and use it in GitHub Desktop.
Save jacob-s-son/10746739 to your computer and use it in GitHub Desktop.
#app/controllers/v1/api_controller.rb
class Api::V1::ApiController < ApplicationController
respond_to :json
skip_before_filter :verify_authenticity_token
before_filter :authorize_device
def start_sync
render json: { last_synced_at: @device.last_synced_at.to_i }
end
def stop_sync
@device.update_attributes(last_synced_at: DateTime.now - 1.minute)
render nothing: true, status: 200, content_type: 'text/html'
end
private
def authorize_device
@user = User.where(token: request.headers['api-user-token']).first
if @user
@device = Device.where(user_id: @user.id, external_id: request.headers['api-device-id'] )
.first_or_create(name: request.headers['api-device-name'], last_synced_at: DateTime.new(2012, 7, 1) )
end
head :forbidden unless @user && @device
end
end
#app/controllers/v1/api_controller.rb
class Api::V1::BooksController < Api::V1::ApiController
respond_to :json, :html
def create
if params['book'] and params['book']['epub']
params['epub'] = params['book']['epub']
end
book_params = BookParamsNormalizer.normalize_params(params, @user)
# params[:book][:metadata_extracted_flag] = true
if BookProcessor.process_with_params(book_params, @user)
render json: { status: "success" }
else
render json: { status: "fail" }
end
end
def bulk_update
@books = BookUpdater.update_and_return_updatable_books(params[:books].to_a, @user, @device)
end
def bulk_delete
BookDeleter.mark_as_deleted( @user, params[:books].to_a )
@books = @user.books.added_or_deleted_since( @device.last_synced_at )
end
end
# app/services/book_updater.rb
class BookUpdater
attr_accessor :books_data, :user, :device
class << self
def update_and_return_updatable_books(books_data, user, device)
new(books_data, user, device).update_and_return_updatable_books
end
end
def initialize(books_data, user, device)
self.books_data = books_data
self.user = user
self.device = device
end
def update_and_return_updatable_books
updated_books = books_data.inject([ '0' ]) do |updated_book_ids, book|
book_for_update = user.books.first_changed_by_updated_at(book["id"], Time.at(book["last_read_at"].to_i) )
if book_for_update
book_for_update.update_attributes( BookParamsNormalizer.normalize_params(book, @user) )
updated_book_ids << book["id"]
end
updated_book_ids
end
user.books.changed_and_added_since( device.last_synced_at ).where( "book_hash NOT IN ( ? )", updated_books )
end
end
# app/services/book_params_normalizer.rb
class BookParamsNormalizer
attr_accessor :params
FIELD_MAPPING = {
'addedts' => { name: 'added_at', converter: lambda {|value| Time.at(value.to_i) } },
'started' => { name: 'started_at', converter: lambda {|value| Time.at(value.to_i) } },
'last_read_at' => { name: 'last_read_at', converter: lambda {|value| Time.at(value.to_i) } },
'deleted_at' => { name: 'deleted_at', converter: lambda {|value| Time.at(value.to_i) } },
#settings #########
'normalbookfontsize' => { name: 'normal_book_font_size', converter: lambda {|value| value.to_f } },
'speedbookfontsize' => { name: 'speed_book_font_size', converter: lambda {|value| value.to_f } },
'speedbookwpm' => { name: 'speed_book_wpm', converter: lambda {|value| value.to_i } },
'speedbookwpl' => { name: 'speed_book_wpl', converter: lambda {|value| value.to_i } },
'speedbooklines' => { name: 'speed_book_lines', converter: lambda {|value| value.to_i } },
'normalbookfontname' => { name: 'normal_book_font_name' },
'speedbookfontname' => { name: 'speed_book_font_name' },
###################
'id' => { name: 'book_hash' },
'readingstatus' => { name: 'reading_status' },
'type' => { name: 'publication_type' }
# 'stats_reading_speed' => { name: 'speed_reading_speed', converter: lambda {|value| value.to_i } },
}
BOOK_SETTINGS = [
'normal_book_font_size',
'speed_book_font_size',
'speed_book_wpm',
'speed_book_wpl',
'speed_book_lines',
'normal_book_font_name',
'speed_book_font_name'
]
class << self
def normalize_params(params, current_user=nil)
new(params, current_user).normalize_params
end
end
def initialize(raw_params, current_user)
self.params = raw_params
self.params['user_id'] = current_user.id
end
def normalize_params
normalized_params = params.inject({}) do |memo, ( key, value )|
mapping = FIELD_MAPPING[key.to_s]
if mapping
memo[mapping[:name]] = mapping[:converter].try(:call, value) || value
elsif new_book.respond_to? key
memo[key] = value
end
memo
end
normalized_params['settings'] = BOOK_SETTINGS.inject({}) {|memo, setting| memo[setting] = normalized_params.delete(setting); memo }.to_json
normalized_params
end
def new_book
@new_book ||= Book.new
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment