calculator

This commit is contained in:
Dan Elbert 2016-01-31 00:00:32 -06:00
parent 9cc9fb2c2f
commit ffb2c92f74
13 changed files with 1705 additions and 5 deletions

View File

@ -18,4 +18,5 @@
//= require typeahead
//= require autosize
//= require chosen.jquery
//= require underscore
//= require_tree .

View File

@ -0,0 +1,73 @@
(function($) {
function State() {
this.input = null;
this.outputUnit = null;
this.changed = false;
}
State.prototype.setInput = function(value) {
if (value != this.input) {
this.changed = true;
this.input = value;
}
};
State.prototype.setOutputUnit = function(value) {
if (value != this.outputUnit) {
this.changed = true;
this.outputUnit = value;
}
};
State.prototype.is_changed = function() {
return this.changed;
};
State.prototype.reset = function() {
this.changed = false;
};
$(document).on("ready page:load", function() {
var state = new State();
var $input = $("#input");
var $output = $("#output");
var $outputUnit = $("#output_unit");
var performUpdate = _.debounce(function() {
$.getJSON(
"/calculator/calculate",
{input: $input.val(), output_unit: $outputUnit.val()},
function(data) {
if (data.errors.input) {
$input.closest(".form-group").addClass("has-error");
} else {
$input.closest(".form-group").removeClass("has-error");
}
if (data.errors.output_unit) {
$outputUnit.closest(".form-group").addClass("has-error");
} else {
$outputUnit.closest(".form-group").removeClass("has-error");
}
$output.val(data.output);
}
);
}, 500);
$input.add($outputUnit).on('change blur keyup', function(evt) {
state.setInput($input.val());
state.setOutputUnit($outputUnit.val());
if (state.is_changed()) {
performUpdate();
state.reset();
}
});
});
})(jQuery);

View File

@ -0,0 +1,45 @@
class CalculatorController < ApplicationController
def index
end
def calculate
input = params[:input]
output_unit = params[:output_unit]
parsed_input = nil
original_number = nil
data = {errors: {}, output: ''}
if input.present?
begin
parsed_input = UnitConversion.parse(input)
original_number = parsed_input.value
rescue UnitConversion::UnparseableUnitError => e
data[:errors][:input] = [e.message]
end
if parsed_input.present? && output_unit.present?
begin
parsed_input = parsed_input.convert_to output_unit
rescue Unitwise::ExpressionError => e
data[:errors][:output_unit] = [e.message]
end
end
if parsed_input
puts parsed_input.value
puts parsed_input.unit
data[:output] = UnitConversion.auto_unit(UnitConversion.quantity_format(parsed_input.value, original_number), parsed_input.unit.to_s)
end
else
data[:errors][:input] = ['Invalid input']
end
render json: data
end
end

View File

@ -2,7 +2,7 @@ class IngredientsController < ApplicationController
before_action :set_ingredient, only: [:edit, :update, :destroy]
before_filter :ensure_valid_user, only: [:new, :edit, :create, :update, :destroy]
before_filter :ensure_valid_user, except: [:index]
# GET /ingredients
# GET /ingredients.json

View File

@ -2,7 +2,7 @@ class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy, :scale]
before_filter :ensure_valid_user, only: [:new, :edit, :create, :update, :destroy]
before_filter :ensure_valid_user, except: [:show, :scale, :index]
# GET /recipes
def index
@ -24,7 +24,6 @@ class RecipesController < ApplicationController
# GET /recipes/new
def new
@recipe = Recipe.new
@recipe.recipe_ingredients << RecipeIngredient.new
end
# GET /recipes/1/edit

View File

@ -8,6 +8,7 @@ module ApplicationHelper
[
nav_item('Recipes', recipes_path, 'recipes'),
nav_item('Ingredients', ingredients_path, 'ingredients'),
nav_item('Calculator', calculator_path, 'calculator'),
nav_item('About', about_path, 'home')
]
end

View File

@ -118,6 +118,7 @@ module UnitConversion
end
def normalize_unit_names(unit_description)
return unit_description.to_sym if UNIT_ALIASES.include?(unit_description.to_sym)
unit_description.downcase.gsub(/[a-z]+/) do |match|
UNIT_ALIAS_MAP[match] || match
end

View File

@ -0,0 +1,26 @@
<div class="row">
<div class="col-xs-12">
<div class="page-header">
<h1>Calculator</h1>
</div>
<div class="row">
<div class="form-group col-xs-12 col-sm-8">
<%= label_tag :input, "Input", class: 'control-label' %>
<%= text_field_tag :input, nil, class: 'form-control', autofocus: true %>
</div>
<div class="form-group col-xs-12 col-sm-4">
<%= label_tag :output_unit, "Output Unit", class: 'control-label' %>
<%= text_field_tag :output_unit, nil, class: 'form-control' %>
</div>
<div class="form-group col-xs-12">
<%= label_tag :output, "Output", class: 'control-label' %>
<%= text_field_tag :output, nil, class: 'form-control', readonly: true %>
</div>
</div>
</div>
</div>

View File

@ -4,7 +4,7 @@
<div class="form-group">
<%= f.label :username, class: 'control-label' %>
<%= f.text_field :username, class: 'form-control' %>
<%= f.text_field :username, autofocus: true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :full_name, 'Name', class: 'control-label' %>

View File

@ -12,7 +12,7 @@
<div class="form-group">
<%= label_tag :username, "Username", class: 'control-label' %>
<%= text_field_tag :username, nil, class: 'form-control' %>
<%= text_field_tag :username, nil, autofocus: true, class: 'form-control' %>
</div>
<div class="form-group">

View File

@ -28,6 +28,11 @@ Rails.application.routes.draw do
get '/about' => 'home#about', as: :about
scope '/calculator', controller: :calculator, as: :calculator do
get '/' => :index
get '/calculate' => :calculate
end
root 'recipes#index'

View File

@ -21,6 +21,7 @@ RSpec.describe UnitConversion do
expect(UnitConversion.auto_unit('1/16', 'cup')).to eq ['1', 'tablespoon']
expect(UnitConversion.auto_unit('1/48', 'cup')).to eq ['1', 'teaspoon']
expect(UnitConversion.auto_unit('768', 'tsp')).to eq ['1', 'gallon']
expect(UnitConversion.auto_unit('6', '[tsp_us]')).to eq ['2', 'tablespoon']
end
it 'converts standard mass units correctly' do

1548
vendor/assets/javascripts/underscore.js vendored Normal file

File diff suppressed because it is too large Load Diff