Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instructor steps #1

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
14230cc
first test
bhserna Jun 11, 2016
d0356d1
enough code to make the first test pass
bhserna Jun 11, 2016
663cb24
second test
bhserna Jun 11, 2016
5d509d8
second test is green
bhserna Jun 11, 2016
b4e2bee
third test
bhserna Jun 11, 2016
21c48d5
third test is green
bhserna Jun 11, 2016
52b09b2
small refactor
bhserna Jun 11, 2016
4fa4321
moves inventory to its own file
bhserna Jun 11, 2016
05eb102
rendering with sinatra
bhserna Jun 11, 2016
1dbd496
view for new article
bhserna Jun 11, 2016
4dec278
inspect params
bhserna Jun 11, 2016
f3dc99a
expect and :add_inventory method
bhserna Jun 11, 2016
4bd6645
problem with the hash keys
bhserna Jun 12, 2016
9907550
expect string params
bhserna Jun 12, 2016
19f7cfc
adds create method to Store
bhserna Jun 12, 2016
7a6d0ee
refactor to introduce an InMemoryStore that will be used in the app a…
bhserna Jun 12, 2016
00b6294
a little design to expect errors when an article is added
bhserna Jun 12, 2016
94fdca0
sending the right status
bhserna Jun 12, 2016
72361a2
validates presence of name, but does not handle empty string
bhserna Jun 12, 2016
a6b849f
handle empty string
bhserna Jun 12, 2016
cd6d827
structure design to show form values
bhserna Jun 12, 2016
ea44a31
new article form
bhserna Jun 12, 2016
0cd7a7a
restore params
bhserna Jun 12, 2016
578e56e
form show errors but always shows error
bhserna Jun 12, 2016
9bf7761
how to show no errors on empty form?
bhserna Jun 12, 2016
b008014
little refactor to make ArticleForm to receive an Article
bhserna Jun 12, 2016
1e8f7e4
separate validation to be able to render the initial form without errors
bhserna Jun 12, 2016
2c598fc
validates presence of quantity but discovering a bug on Article.quant…
bhserna Jun 12, 2016
e4814aa
is working but... should Inventory include Presence?
bhserna Jun 12, 2016
708ac7d
refactor to introduce an ArticleValidator
bhserna Jun 12, 2016
1538b34
validates quantity is greater than or equals than 0
bhserna Jun 12, 2016
a6f159a
render quantity errors
bhserna Jun 12, 2016
8cecd6f
code uniq validation is ready but the validation code is a little funky
bhserna Jun 13, 2016
1cd67cc
validation is a little more clean but still a little funky
bhserna Jun 13, 2016
56a9a7e
introduction of method :send, to clean the code a little, but still n…
bhserna Jun 13, 2016
50753ee
using splat operator to accept a collection of attributes
bhserna Jun 13, 2016
076289f
intruction of define method to remove some duplication... funky code
bhserna Jun 13, 2016
06e2e78
attempt to build a more generic delegation method
bhserna Jun 13, 2016
f6d9ce9
know we have a generic delegate method, extracted in a Delegate module
bhserna Jun 13, 2016
d0ca88f
html and api design to increment article quantity
bhserna Jun 13, 2016
a3dcf64
first test to increment article quantity
bhserna Jun 13, 2016
de793e1
make the test green
bhserna Jun 13, 2016
c2bc607
uses Article#to_h to create record and fixes an spec
bhserna Jun 13, 2016
2f843dc
adds update method to store in order to run the app
bhserna Jun 13, 2016
a64b8c6
html and api to decrement quantity
bhserna Jun 13, 2016
23a9464
design and refactor to add a test to decrement article quantity
bhserna Jun 13, 2016
c4cf647
the fisrt test to decrement quantity is green
bhserna Jun 13, 2016
10cdb7b
adds an spec to test that the quantity can't go less than 0
bhserna Jun 13, 2016
7424efa
do not permit quantity go less than 0
bhserna Jun 13, 2016
41111ac
a better way to handle decrementing quantity knowledge
bhserna Jun 13, 2016
f7e2aa1
adds an in file store
bhserna Jun 13, 2016
7f9449e
moving files to a better file structure
bhserna Jun 13, 2016
f0b2ea4
Adds Gemfile
bhserna Jun 13, 2016
7974766
Use sqlite db as storage
bhserna Jun 13, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions 01_inventory/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
source 'https://rubygems.org'
gem "sinatra"
gem "rspec"

gem 'activerecord'
gem 'activesupport'
gem 'sqlite3'
57 changes: 57 additions & 0 deletions 01_inventory/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
GEM
remote: https://rubygems.org/
specs:
activemodel (4.2.6)
activesupport (= 4.2.6)
builder (~> 3.1)
activerecord (4.2.6)
activemodel (= 4.2.6)
activesupport (= 4.2.6)
arel (~> 6.0)
activesupport (4.2.6)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
arel (6.0.3)
builder (3.2.2)
diff-lcs (1.2.5)
i18n (0.7.0)
json (1.8.3)
minitest (5.9.0)
rack (1.6.4)
rack-protection (1.5.3)
rack
rspec (3.2.0)
rspec-core (~> 3.2.0)
rspec-expectations (~> 3.2.0)
rspec-mocks (~> 3.2.0)
rspec-core (3.2.0)
rspec-support (~> 3.2.0)
rspec-expectations (3.2.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-mocks (3.2.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-support (3.2.1)
sinatra (1.4.7)
rack (~> 1.5)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
sqlite3 (1.3.11)
thread_safe (0.3.5)
tilt (1.3.3)
tzinfo (1.2.2)
thread_safe (~> 0.1)

PLATFORMS
ruby

DEPENDENCIES
activerecord
activesupport
rspec
sinatra
sqlite3
10 changes: 10 additions & 0 deletions 01_inventory/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require "active_record"
require "active_support/all"

namespace :db do
desc "migrate your database"
task :migrate do
require "./store/db_store/config"
ActiveRecord::Migrator.migrate('store/db_store/migrate')
end
end
42 changes: 42 additions & 0 deletions 01_inventory/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require "sinatra"
require_relative "lib/inventory"
require_relative "store/db_store/config"
require_relative "store/db_store"

store = DbStore.new
inventory = Inventory.new(store)

get '/' do
@articles = inventory.articles_list
erb :index
end

get '/articles/new' do
@form = inventory.new_article_form
erb :new_article
end

post '/articles' do
status = inventory.add_article(params)

if status.success?
redirect "/"
else
@form = status.form_with_errors
erb :new_article
end
end

post '/articles/:code/increment' do
inventory.increment_article_quantity(params[:code])
redirect "/"
end

post '/articles/:code/decrement' do
inventory.decrement_article_quantity(params[:code])
redirect "/"
end

after do
ActiveRecord::Base.clear_active_connections!
end
172 changes: 172 additions & 0 deletions 01_inventory/lib/inventory.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
require "ostruct"

class Inventory
def initialize(store)
@store = store
end

def articles_list
store.all_articles.map { |raw| Article.new(raw) }
end

def new_article_form
ArticleForm.new(Article.new)
end

def add_article(params)
article = Article.new(params)
errors = ArticleValidator.new(article, store).validate!

if errors.empty?
store.create(article.to_h)
SuccessArticleStatus.new
else
ErrorArticleStatus.new(ArticleForm.new(article, errors))
end
end

def increment_article_quantity(code)
article = Article.new(store.find_with_code(code))
article.increment_quantity!
store.update(article.to_h)
end

def decrement_article_quantity(code)
article = Article.new(store.find_with_code(code))
article.decrement_quantity! do |article|
store.update(article.to_h)
end
end

private

attr_reader :store
end

module Presence
def present?(attr)
!attr.nil? && attr != ""
end
end

module Delegate
def delegate(*keys, to:, sufix: false)
keys.each do |key|
method_name = sufix && "#{key}_#{to}" || key
define_method method_name do
self.send(to).send(key)
end
end
end
end

class ArticleValidator
include Presence

def initialize(article, store)
@store = store
@article = article
end

def validate!
self.errors = {}
validate_presence_of! :name, :code, :quantity
validate_uniqness_of_code!
validate_quantity_is_greater_than_or_equals_than_zero!
errors
end

private

attr_reader :article, :store
attr_accessor :errors

def validate_presence_of!(*attr_keys)
attr_keys.each do |attr_key|
unless present?(article.send(attr_key))
errors[attr_key] = "can't be blank"
end
end
end

def validate_uniqness_of_code!
if present?(article.code) && store.find_with_code(article.code)
errors[:code] = "already taken"
end
end

def validate_quantity_is_greater_than_or_equals_than_zero!
if present?(article.quantity) && article.quantity < 0
errors[:quantity] = "should be greater or equals than 0"
end
end
end

class ArticleForm
extend Delegate

delegate :name, :code, :quantity, to: :article
delegate :name, :code, :quantity, to: :errors, sufix: true

def initialize(article, errors = {})
@article = article
@errors = OpenStruct.new(errors)
end

private

attr_reader :article, :errors
end

class ErrorArticleStatus
attr_reader :form_with_errors

def initialize(form)
@form_with_errors = form
end

def success?
false
end
end

class SuccessArticleStatus
def success?
true
end
end

class Article
include Presence

attr_reader :name, :code, :quantity

def initialize(data = {})
@name = data["name"]
@code = data["code"]
self.quantity = data["quantity"]
end

def to_h
{"name" => name,
"code" => code,
"quantity" => quantity}
end

def increment_quantity!
self.quantity = quantity + 1
end

def decrement_quantity!(&block)
if quantity > 0
self.quantity = quantity - 1
block.call(self)
end
end

private

def quantity=(value)
@quantity = value.to_i if present?(value)
end
end
Loading