From 521bcef8cf7d01a1af43bfe328a32fbfc95816e6 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 19:25:38 -0300 Subject: [PATCH 01/27] [developent]: Add info about bower --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index fba4dd25..299f7f95 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ We recommend you use one ruby version manager as [rbenv](http://rbenv.org/) | [r - 2. In home path this project you should download all dependencies with bundler `bundle install` - 3. After run bundler you should you database config, one example file is in config/database.yml.sample, maybe you want use it with `cp config/database.yml.sample config/database.yml`. - 4. After configured database you go run `bundle exec rake db:migrate` to generate ou database schema. +- 5. This project manage frontend dependencies with [bower](https://bower.io/), to build dependencies use `bower install` To run tests you user `bundle exec rspec spec`, to run webserver use `bundle exec rails server`, you server should listen in http://localhost:3000/ @@ -32,5 +33,7 @@ you server should listen in http://localhost:3000/ - Rails 4.2.7 - SQLite 3 (in ubuntu run `sudo apt-get install -y sqlite3 libsqlite3-dev`) - Gem Bundler (`gem install bundler`) +- NodeJS +- Bower (`npm install bower -g`) From 720bea7ccb8d583495070896658d2ed1ce9ed131 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 20:42:05 -0300 Subject: [PATCH 02/27] [sidekiq]: Add gem sidekiq --- Gemfile | 2 ++ Gemfile.lock | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/Gemfile b/Gemfile index 79edf9e6..cc10cba9 100644 --- a/Gemfile +++ b/Gemfile @@ -32,7 +32,9 @@ group :test do gem 'rspec-rails' gem 'factory_girl_rails' gem 'shoulda-matchers' + gem 'rspec-sidekiq' end gem 'react-rails' gem 'carrierwave' +gem 'sidekiq' diff --git a/Gemfile.lock b/Gemfile.lock index 09bdc98c..dde662ab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -95,6 +95,8 @@ GEM pry-rails (0.3.4) pry (>= 0.9.10) rack (1.6.4) + rack-protection (1.5.3) + rack rack-test (0.6.3) rack (>= 1.0) rails (4.2.7) @@ -131,6 +133,11 @@ GEM execjs railties (>= 3.2) tilt + redis (3.3.1) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) rspec-core (3.5.2) rspec-support (~> 3.5.0) rspec-expectations (3.5.0) @@ -147,12 +154,24 @@ GEM rspec-expectations (~> 3.5.0) rspec-mocks (~> 3.5.0) rspec-support (~> 3.5.0) + rspec-sidekiq (2.2.0) + rspec (~> 3.0, >= 3.0.0) + sidekiq (>= 2.4.0) rspec-support (3.5.0) sdoc (0.4.1) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) + sidekiq (4.1.4) + concurrent-ruby (~> 1.0) + connection_pool (~> 2.2, >= 2.2.0) + redis (~> 3.2, >= 3.2.1) + sinatra (>= 1.4.7) + sinatra (1.4.7) + rack (~> 1.5) + rack-protection (~> 1.4) + tilt (>= 1.3, < 3) slop (3.6.0) spring (1.7.2) sprockets (3.7.0) @@ -184,8 +203,10 @@ DEPENDENCIES rails (= 4.2.7) react-rails rspec-rails + rspec-sidekiq sdoc (~> 0.4.0) shoulda-matchers + sidekiq spring sqlite3 uglifier (>= 1.3.0) From b4b35c8adccc2684329d4d740d990949d1d624ef Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 20:56:15 -0300 Subject: [PATCH 03/27] [sidekiq]: Change readme to add sidekiq run Changed readme to add instructions about sidekiq startup --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 299f7f95..9c5f3768 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ We recommend you use one ruby version manager as [rbenv](http://rbenv.org/) | [r - 3. After run bundler you should you database config, one example file is in config/database.yml.sample, maybe you want use it with `cp config/database.yml.sample config/database.yml`. - 4. After configured database you go run `bundle exec rake db:migrate` to generate ou database schema. - 5. This project manage frontend dependencies with [bower](https://bower.io/), to build dependencies use `bower install` +- 6. Init sidekiq with `bundle exec sidkiq -C config/sidekiq.yml` To run tests you user `bundle exec rspec spec`, to run webserver use `bundle exec rails server`, you server should listen in http://localhost:3000/ From ba15de1029f94e22475298a7db73e654c6a9caa6 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 20:59:13 -0300 Subject: [PATCH 04/27] [sidekiq]: Change process sales to use sidekiq Now when user send sales batch file, the system process it assync background job with Sidekiq (instead synchronous process with concern module). Add sidekiq.yml config file and example. Also add routes to Sidekiq web admin (/sidekiq/) --- app/controllers/sales_batches_controller.rb | 8 +++- app/models/concerns/sales_from_file.rb | 37 ---------------- app/uploaders/sales_uploader.rb | 1 - app/workers/sales_batch_worker.rb | 49 +++++++++++++++++++++ config/routes.rb | 3 ++ config/sidekiq.yml | 23 ++++++++++ config/sidekiq.yml.example | 23 ++++++++++ 7 files changed, 105 insertions(+), 39 deletions(-) delete mode 100644 app/models/concerns/sales_from_file.rb create mode 100644 app/workers/sales_batch_worker.rb create mode 100644 config/sidekiq.yml create mode 100644 config/sidekiq.yml.example diff --git a/app/controllers/sales_batches_controller.rb b/app/controllers/sales_batches_controller.rb index 6ee37063..7c259def 100644 --- a/app/controllers/sales_batches_controller.rb +++ b/app/controllers/sales_batches_controller.rb @@ -9,7 +9,13 @@ def new def create @batch = SalesBatch.create(upload_params) - redirect_to sales_batch_path(@batch) + + if @batch.persisted? + SalesBatchWorker.perform_async(@batch.id) + redirect_to sales_batches_path + else + render json: { error: @batch.errors }, status: :unprocessable_entity + end end def show diff --git a/app/models/concerns/sales_from_file.rb b/app/models/concerns/sales_from_file.rb deleted file mode 100644 index a939d893..00000000 --- a/app/models/concerns/sales_from_file.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'csv' - -module Concerns - module SalesFromFile - extend ActiveSupport::Concern - - CSV_HEADERS = %w(customer description unit_price amount address supplier) - - private - - #TODO: Refactor this to use uploader filename - #TODO: Refactor this to move to Sidekiq - #TODO: Refactor this to reduce method lines - def process_data_file! - filename = self.attachment.file.file - data = CSV.read(filename, col_sep: "\t") - data.delete_at(0) - - sales_attrs = data.map do |row| - row.each_with_index.map do |value, index| - Hash[ CSV_HEADERS[index], value ] - end.reduce(&:merge) - end - - sales_attrs.each do |sale_attr| - self.sales.create(sale_attr) - end - - total_revenue = self.sales.map{|sale| sale.amount * sale.unit_price }.reduce(:+) - self.update_attributes({ - processed: true, - revenue: total_revenue, - batch_code: SecureRandom.uuid - }) - end - end -end diff --git a/app/uploaders/sales_uploader.rb b/app/uploaders/sales_uploader.rb index 7e4c00d7..aa065d64 100644 --- a/app/uploaders/sales_uploader.rb +++ b/app/uploaders/sales_uploader.rb @@ -47,5 +47,4 @@ def extension_white_list # def filename # "something.jpg" if original_filename # end - end diff --git a/app/workers/sales_batch_worker.rb b/app/workers/sales_batch_worker.rb new file mode 100644 index 00000000..0857f9ea --- /dev/null +++ b/app/workers/sales_batch_worker.rb @@ -0,0 +1,49 @@ +require 'csv' + +class SalesBatchWorker + include Sidekiq::Worker + + sidekiq_options queue: :sales + + CSV_HEADERS = %w(customer description unit_price amount address supplier) + + def perform(id) + batch = SalesBatch.find(id) + tsv = generate_tsv(batch.attachment.file.path) + + generate_sales_attrs(tsv).each do |sale_attr| + batch.sales.create(sale_attr) + end + + update_batch!(batch) + end + + private + + def update_batch!(batch) + total_revenue = calc_revenue(batch) + + batch.update_attributes({ + processed: true, + revenue: total_revenue + }) + end + + def calc_revenue(batch) + batch.sales.map{|sale| sale.amount * sale.unit_price }.reduce(:+) + end + + def generate_sales_attrs(tsv) + tsv.map do |row| + row.each_with_index.map do |value, index| + Hash[ CSV_HEADERS[index], value ] + end.reduce(&:merge) + end + end + + def generate_tsv(file_path) + data = CSV.read(file_path, col_sep: "\t") + data.delete_at(0) + data + end +end diff --git a/config/routes.rb b/config/routes.rb index 15a82e78..07544a95 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,4 +3,7 @@ resources :sales_batches, only: [:new, :create, :show, :index] resources :sales, only: [:show] + + require 'sidekiq/web' + mount Sidekiq::Web => '/sidekiq' end diff --git a/config/sidekiq.yml b/config/sidekiq.yml new file mode 100644 index 00000000..ad1cbaa7 --- /dev/null +++ b/config/sidekiq.yml @@ -0,0 +1,23 @@ +default: &default + :service: 'redis://localhost:6379' + :logfile: ./log/sidekiq.log + :queues: + - sales + +development: + <<: *default + +test: + <<: *default + +qa: + <<: *default + +production: + :service: 'redis://localhost:6379' + :user: 'admin' + :password: 'admin' + :logfile: ./log/sidekiq.log + :queues: + - sales + diff --git a/config/sidekiq.yml.example b/config/sidekiq.yml.example new file mode 100644 index 00000000..ad1cbaa7 --- /dev/null +++ b/config/sidekiq.yml.example @@ -0,0 +1,23 @@ +default: &default + :service: 'redis://localhost:6379' + :logfile: ./log/sidekiq.log + :queues: + - sales + +development: + <<: *default + +test: + <<: *default + +qa: + <<: *default + +production: + :service: 'redis://localhost:6379' + :user: 'admin' + :password: 'admin' + :logfile: ./log/sidekiq.log + :queues: + - sales + From 8f0e1fd643122102e48bab99343295fe89bdae36 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 22:21:31 -0300 Subject: [PATCH 05/27] [sidekiq]: add sidekiq test support --- spec/support/rspec_sidekiq_support.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 spec/support/rspec_sidekiq_support.rb diff --git a/spec/support/rspec_sidekiq_support.rb b/spec/support/rspec_sidekiq_support.rb new file mode 100644 index 00000000..a3c4c6e7 --- /dev/null +++ b/spec/support/rspec_sidekiq_support.rb @@ -0,0 +1,10 @@ +RSpec::Sidekiq.configure do |config| + # Clears all job queues before each example + config.clear_all_enqueued_jobs = true # default => true + + # Whether to use terminal colours when outputting messages + config.enable_terminal_colours = true # default => true + + # Warn when jobs are not enqueued to Redis but to a job array + config.warn_when_jobs_not_processed_by_sidekiq = true # default => true +end From ae81341961de0b1c3a785115580c85718eac5cd3 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 22:21:54 -0300 Subject: [PATCH 06/27] [sidekiq]: WIP: creating test controllers --- app/models/sales_batch.rb | 13 +++-- app/views/sales/show.html.erb | 24 +++++++- app/views/sales_batches/show.html.erb | 2 +- .../sales_batches_controller_spec.rb | 57 +++++++++++++++++++ spec/factories/sales_batches_factorie.rb | 1 + spec/models/sales_batch_spec.rb | 5 -- 6 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 spec/controllers/sales_batches_controller_spec.rb diff --git a/app/models/sales_batch.rb b/app/models/sales_batch.rb index 5ad186c6..ca3111c8 100644 --- a/app/models/sales_batch.rb +++ b/app/models/sales_batch.rb @@ -12,12 +12,15 @@ # class SalesBatch < ActiveRecord::Base - include Concerns::SalesFromFile - has_many :sales, dependent: :destroy - - validates :batch_code, uniqueness: true, presence: false + before_create :generate_batch_code + validates :batch_code, uniqueness: true mount_uploader :attachment, SalesUploader - after_create :process_data_file! + + private + + def generate_batch_code + self.batch_code = SecureRandom.uuid + end end diff --git a/app/views/sales/show.html.erb b/app/views/sales/show.html.erb index 1475b37d..2ad8915b 100644 --- a/app/views/sales/show.html.erb +++ b/app/views/sales/show.html.erb @@ -1 +1,23 @@ -

<%= @sale.customer %>

+ +

Venda efetuada

+ + + + + + + + + + + + + + + + + + +
CompradorDescriçãoPreço unitárioQuantidadeEndereçoFornecedor
<%= @sale.customer %><%= @sale.description %><%= number_to_currency(@sale.unit_price, :unit => "R$ ") %><%= @sale.amount %>
<%= @sale.address %>
<%= @sale.supplier %>
+ +<%= link_to "<< Voltar para listagem do lote", sales_batch_path(@sale.sales_batch_id) %> diff --git a/app/views/sales_batches/show.html.erb b/app/views/sales_batches/show.html.erb index 8572b0e5..51f419e6 100644 --- a/app/views/sales_batches/show.html.erb +++ b/app/views/sales_batches/show.html.erb @@ -1,4 +1,4 @@ -

Dados de venda

+

Dados do lote de venda

<% if @sales_batch.processed? %> diff --git a/spec/controllers/sales_batches_controller_spec.rb b/spec/controllers/sales_batches_controller_spec.rb new file mode 100644 index 00000000..0011942f --- /dev/null +++ b/spec/controllers/sales_batches_controller_spec.rb @@ -0,0 +1,57 @@ +require 'rails_helper' + +describe SalesBatchesController, type: :controller do + describe '#index' do + before do + get :index + end + + it 'returns with :success' do + expect(response).to be_success + end + + it 'render template :index' do + expect(response).to render_template :index + end + + context 'when does not have sales batches' do + it 'assigns :sales_batches empty' do + expect(assigns(:sales_batches)).to be_empty + end + end + + context 'when have any sales batches' do + let(:registers_no) { 3 } + before do + registers_no.times.each {|x| create(:sales_batch) } + get :index + end + + it 'assigns :sales_batches with all batches' do + expect(assigns(:sales_batches).count).to eq registers_no + end + end + end + + describe '#create' do + let(:sales_batches_params) do + { + attachment: Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec', 'fixtures', 'sales.txt')) + } + end + + + before do + allow(SalesBatchWorker).to receive(:perform_async) + post :create, sales_batch: sales_batches_params + end + + it 'batch persisted' do + expect(assigns(:batch)).to be_persisted + end + + it 'enqued job' do + expect(SalesBatchWorker).to have_received(:perform_async) + end + end +end diff --git a/spec/factories/sales_batches_factorie.rb b/spec/factories/sales_batches_factorie.rb index 87a60ad7..8f2dee83 100644 --- a/spec/factories/sales_batches_factorie.rb +++ b/spec/factories/sales_batches_factorie.rb @@ -1,5 +1,6 @@ FactoryGirl.define do factory :sales_batch do attachment { Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec', 'fixtures', 'sales.txt')) } + batch_code SecureRandom.uuid end end diff --git a/spec/models/sales_batch_spec.rb b/spec/models/sales_batch_spec.rb index 460d27d2..5a776899 100644 --- a/spec/models/sales_batch_spec.rb +++ b/spec/models/sales_batch_spec.rb @@ -18,7 +18,6 @@ is_expected.to have_many :sales end - context 'validates' do subject { build(:sales_batch) } @@ -26,8 +25,4 @@ is_expected.to validate_uniqueness_of :batch_code end end - - context 'callbacks' do - pending "Warn: Callbacks as anti pattern" - end end From 9a6be07f02ad9a7f9e00914eb6974a0dbbb757d2 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sat, 27 Aug 2016 11:45:12 -0300 Subject: [PATCH 07/27] [sidekiq]: Little views changes --- app/views/sales/show.html.erb | 7 ++++--- app/views/sales_batches/_form_new.html.erb | 5 +++-- app/views/sales_batches/show.html.erb | 13 ++++++++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/views/sales/show.html.erb b/app/views/sales/show.html.erb index 2ad8915b..2857ad7f 100644 --- a/app/views/sales/show.html.erb +++ b/app/views/sales/show.html.erb @@ -1,5 +1,4 @@ - -

Venda efetuada

+

Log de venda efetuada

@@ -9,14 +8,16 @@ + - + +
Quantidade Endereço FornecedorValor total da compra
<%= @sale.customer %> <%= @sale.description %><%= number_to_currency(@sale.unit_price, :unit => "R$ ") %><%= number_to_currency(@sale.unit_price, unit: "R$ ") %> <%= @sale.amount %>
<%= @sale.address %>
<%= @sale.supplier %><%= number_to_currency(@sale.amount * @sale.unit_price, unit: "BRL ") %>
diff --git a/app/views/sales_batches/_form_new.html.erb b/app/views/sales_batches/_form_new.html.erb index 123cc9d3..332d6d06 100644 --- a/app/views/sales_batches/_form_new.html.erb +++ b/app/views/sales_batches/_form_new.html.erb @@ -1,6 +1,6 @@ <%= form_for sales_batch, url: sales_batches_path, html: { class: 'form-inline' } do |f| %> <%= f.file_field :attachment, class: 'form-control' %> - <%= f.submit 'Enviar', class: 'btn btn-success' %> + <%= f.submit 'Enviar', class: 'glyphicon glyphicon-cloud-upload btn btn-success' %>

Instruções para novo lote

Para criar um novo lote de vendas, selecione um arquivo no formato '.txt' @@ -10,6 +10,7 @@

Comprador descrição Preço Unitário  Quantidade  Endereço  Fornecedor
- Você pode baixar um arquivo de <%= link_to "exemplo aqui", "/sales.txt" %>. + Você pode baixar um arquivo de exemplo aqui + <%= link_to "Exemplo", "/sales.txt", class: 'glyphicon glyphicon-cloud-download btn-success' %>.

<% end %> diff --git a/app/views/sales_batches/show.html.erb b/app/views/sales_batches/show.html.erb index 51f419e6..b9c3d4a4 100644 --- a/app/views/sales_batches/show.html.erb +++ b/app/views/sales_batches/show.html.erb @@ -22,11 +22,18 @@ <% end %> - Código do Lote: - <%= @sales_batch.batch_code %> +

+ + + Download do arquivo original + +
+ Código do Lote: + <%= @sales_batch.batch_code %> +

<% else %>

A processar

<%end%> -<%= link_to "Voltar para home", root_path %> +<%= link_to "Voltar para home", root_path, class: "btn btn-info glyphicon glyphicon-menu-left" %> From 4329c46b9f0b63371e1c4258e5f0c104a4841c93 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 28 Aug 2016 16:00:46 -0300 Subject: [PATCH 08/27] [sidekiq]: Tests with capybara and change BG Job. Init feature tests with Capybara and Poltergeist (add phantomjs as dependencie --updated README). Changed Sidekiq backgroud job to model #before_create callback (over controller). --- Gemfile | 2 ++ Gemfile.lock | 20 ++++++++++++++++++++ README.md | 1 + app/controllers/sales_batches_controller.rb | 1 - app/models/sales_batch.rb | 5 +++++ codereview.md | 0 spec/support/capybara_support.rb | 2 ++ spec/support/sidekiq_support.rb | 7 +++++++ 8 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 codereview.md create mode 100644 spec/support/capybara_support.rb create mode 100644 spec/support/sidekiq_support.rb diff --git a/Gemfile b/Gemfile index cc10cba9..763fcf87 100644 --- a/Gemfile +++ b/Gemfile @@ -33,6 +33,8 @@ group :test do gem 'factory_girl_rails' gem 'shoulda-matchers' gem 'rspec-sidekiq' + gem 'capybara' + gem 'poltergeist' end gem 'react-rails' diff --git a/Gemfile.lock b/Gemfile.lock index dde662ab..f901d40c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,6 +36,7 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) + addressable (2.4.0) annotate (2.7.1) activerecord (>= 3.2, < 6.0) rake (>= 10.4, < 12.0) @@ -45,12 +46,20 @@ GEM babel-source (>= 4.0, < 6) execjs (~> 2.0) builder (3.2.2) + capybara (2.8.1) + addressable + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) carrierwave (0.11.2) activemodel (>= 3.2.0) activesupport (>= 3.2.0) json (>= 1.7) mime-types (>= 1.16) mimemagic (>= 0.3.0) + cliver (0.3.2) coderay (1.1.1) coffee-script-source (1.10.0) concurrent-ruby (1.0.2) @@ -86,6 +95,10 @@ GEM mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) pkg-config (1.1.7) + poltergeist (1.10.0) + capybara (~> 2.1) + cliver (~> 0.3.1) + websocket-driver (>= 0.2.0) pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -189,15 +202,22 @@ GEM thread_safe (~> 0.1) uglifier (3.0.2) execjs (>= 0.3.0, < 3) + websocket-driver (0.6.4) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + xpath (2.0.0) + nokogiri (~> 1.3) PLATFORMS ruby DEPENDENCIES annotate + capybara carrierwave factory_girl_rails jbuilder (~> 2.0) + poltergeist pry-nav pry-rails rails (= 4.2.7) diff --git a/README.md b/README.md index 9c5f3768..3f4f1488 100644 --- a/README.md +++ b/README.md @@ -36,5 +36,6 @@ you server should listen in http://localhost:3000/ - Gem Bundler (`gem install bundler`) - NodeJS - Bower (`npm install bower -g`) +- PhantomJS (to run features specs) diff --git a/app/controllers/sales_batches_controller.rb b/app/controllers/sales_batches_controller.rb index 7c259def..cca3f507 100644 --- a/app/controllers/sales_batches_controller.rb +++ b/app/controllers/sales_batches_controller.rb @@ -11,7 +11,6 @@ def create @batch = SalesBatch.create(upload_params) if @batch.persisted? - SalesBatchWorker.perform_async(@batch.id) redirect_to sales_batches_path else render json: { error: @batch.errors }, status: :unprocessable_entity diff --git a/app/models/sales_batch.rb b/app/models/sales_batch.rb index ca3111c8..6029d779 100644 --- a/app/models/sales_batch.rb +++ b/app/models/sales_batch.rb @@ -14,6 +14,7 @@ class SalesBatch < ActiveRecord::Base has_many :sales, dependent: :destroy before_create :generate_batch_code + after_create :process_attachment validates :batch_code, uniqueness: true mount_uploader :attachment, SalesUploader @@ -23,4 +24,8 @@ class SalesBatch < ActiveRecord::Base def generate_batch_code self.batch_code = SecureRandom.uuid end + + def process_attachment + SalesBatchWorker.perform_async(self.id) + end end diff --git a/codereview.md b/codereview.md new file mode 100644 index 00000000..e69de29b diff --git a/spec/support/capybara_support.rb b/spec/support/capybara_support.rb new file mode 100644 index 00000000..bbcfd251 --- /dev/null +++ b/spec/support/capybara_support.rb @@ -0,0 +1,2 @@ +require 'capybara/poltergeist' +Capybara.javascript_driver = :poltergeist diff --git a/spec/support/sidekiq_support.rb b/spec/support/sidekiq_support.rb new file mode 100644 index 00000000..bba06318 --- /dev/null +++ b/spec/support/sidekiq_support.rb @@ -0,0 +1,7 @@ +require 'sidekiq/testing' + +RSpec.configure do |config| + config.before(:each) do + Sidekiq::Worker.clear_all + end +end From e6c492958330dcca3d4d9ffffea9ccf1b5fc7b0a Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 28 Aug 2016 18:52:06 -0300 Subject: [PATCH 09/27] [state_machine]: Add gem state_machine with AR Add gem state_machines with ActiveRecord compatible, to save state on database. --- Gemfile | 9 ++++++--- Gemfile.lock | 19 ++++++++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 763fcf87..d9148307 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,5 @@ source 'https://rubygems.org' - # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '4.2.7' @@ -21,11 +20,13 @@ group :development, :test do gem 'pry-rails' gem 'pry-nav' gem 'annotate' + gem 'thin' end group :development do - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' + # Spring speeds up development by keeping your application running in the background. + # Read more: https://github.com/rails/spring + # gem 'spring' end group :test do @@ -40,3 +41,5 @@ end gem 'react-rails' gem 'carrierwave' gem 'sidekiq' +gem 'state_machines-activerecord' + diff --git a/Gemfile.lock b/Gemfile.lock index f901d40c..63a3e7de 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -64,8 +64,10 @@ GEM coffee-script-source (1.10.0) concurrent-ruby (1.0.2) connection_pool (2.2.0) + daemons (1.2.4) diff-lcs (1.2.5) erubis (2.7.0) + eventmachine (1.2.0.1) execjs (2.7.0) factory_girl (4.7.0) activesupport (>= 3.0.0) @@ -159,7 +161,7 @@ GEM rspec-mocks (3.5.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.5.0) - rspec-rails (3.5.1) + rspec-rails (3.5.2) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) @@ -186,7 +188,6 @@ GEM rack-protection (~> 1.4) tilt (>= 1.3, < 3) slop (3.6.0) - spring (1.7.2) sprockets (3.7.0) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -195,6 +196,17 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.11) + state_machines (0.4.0) + state_machines-activemodel (0.4.0) + activemodel (>= 4.1, < 5.1) + state_machines (>= 0.4.0) + state_machines-activerecord (0.4.0) + activerecord (>= 4.1, < 5.1) + state_machines-activemodel (>= 0.3.0) + thin (1.7.0) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0, >= 1.0.4) + rack (>= 1, < 3) thor (0.19.1) thread_safe (0.3.5) tilt (2.0.5) @@ -227,8 +239,9 @@ DEPENDENCIES sdoc (~> 0.4.0) shoulda-matchers sidekiq - spring sqlite3 + state_machines-activerecord + thin uglifier (>= 1.3.0) BUNDLED WITH From a755a5c15db81e025a3a1b4e10b99f4d0b20012d Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 28 Aug 2016 18:54:56 -0300 Subject: [PATCH 10/27] [state_machine]: Use state machine to manage sales batch workflow. Enable state machine to manage sales batch workflow. - Remove column Boolen :processed from :sales_batches table - Add column String :state at :sales_batches table - Add sate_machine workflow on sales bacth model - Change sales batch worker wot use state machine --- app/models/sales_batch.rb | 26 ++++++++++++++++--- app/views/sales_batches/index.html.erb | 4 +-- app/workers/sales_batch_worker.rb | 23 ++++++++-------- ...191211_add_field_state_to_sales_batches.rb | 6 +++++ db/schema.rb | 8 +++--- .../uploading_new_sales_batch_spec.rb | 15 +++++++++++ spec/models/sales_batch_spec.rb | 2 +- 7 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 db/migrate/20160828191211_add_field_state_to_sales_batches.rb create mode 100644 spec/features/uploading_new_sales_batch_spec.rb diff --git a/app/models/sales_batch.rb b/app/models/sales_batch.rb index 6029d779..a785a10f 100644 --- a/app/models/sales_batch.rb +++ b/app/models/sales_batch.rb @@ -4,28 +4,48 @@ # # id :integer not null, primary key # attachment :string -# processed :boolean default(FALSE) # revenue :decimal(12, 2) default(0.0) # created_at :datetime not null # updated_at :datetime not null # batch_code :string +# state :string # class SalesBatch < ActiveRecord::Base has_many :sales, dependent: :destroy before_create :generate_batch_code - after_create :process_attachment + after_create :queue! validates :batch_code, uniqueness: true mount_uploader :attachment, SalesUploader + state_machine :state, :initial => :uploaded do + + after_transition on: :queue, do: :queue_on_sidekiq + event :queue do + transition :uploaded => :queued + end + + event :process do + transition [:queued, :processing] => :processing + end + + event :resolve do + transition :processing => :resolved + end + + event :reject do + transition :processing => :rejected + end + end + private def generate_batch_code self.batch_code = SecureRandom.uuid end - def process_attachment + def queue_on_sidekiq SalesBatchWorker.perform_async(self.id) end end diff --git a/app/views/sales_batches/index.html.erb b/app/views/sales_batches/index.html.erb index 532dbbdb..104ef376 100644 --- a/app/views/sales_batches/index.html.erb +++ b/app/views/sales_batches/index.html.erb @@ -23,8 +23,8 @@ <%= batch.sales.count %> <%= number_to_currency(batch.revenue, :unit => "R$ ") %> -

- <%= (batch.processed) ? "Processado" : "A processar" %> +

+ <%= batch.resolved? ? "Processado" : "A processar" %>

diff --git a/app/workers/sales_batch_worker.rb b/app/workers/sales_batch_worker.rb index 0857f9ea..cb28edc5 100644 --- a/app/workers/sales_batch_worker.rb +++ b/app/workers/sales_batch_worker.rb @@ -9,28 +9,29 @@ class SalesBatchWorker def perform(id) batch = SalesBatch.find(id) + + batch.process! + tsv = generate_tsv(batch.attachment.file.path) generate_sales_attrs(tsv).each do |sale_attr| batch.sales.create(sale_attr) end - update_batch!(batch) + calc_revenue(batch) + batch.resolve! + # rescue => e + # logger.error "Erro de execução de job no sidekiq #{e}" + # batch.reject! end private - def update_batch!(batch) - total_revenue = calc_revenue(batch) - - batch.update_attributes({ - processed: true, - revenue: total_revenue - }) - end - def calc_revenue(batch) - batch.sales.map{|sale| sale.amount * sale.unit_price }.reduce(:+) + total_revenue = batch.sales.map do |sale| + sale.amount * sale.unit_price + end.reduce(:+) + batch.update_attributes({ revenue: total_revenue }) end def generate_sales_attrs(tsv) diff --git a/db/migrate/20160828191211_add_field_state_to_sales_batches.rb b/db/migrate/20160828191211_add_field_state_to_sales_batches.rb new file mode 100644 index 00000000..1badf710 --- /dev/null +++ b/db/migrate/20160828191211_add_field_state_to_sales_batches.rb @@ -0,0 +1,6 @@ +class AddFieldStateToSalesBatches < ActiveRecord::Migration + def change + add_column :sales_batches, :state, :string + remove_column :sales_batches, :processed + end +end diff --git a/db/schema.rb b/db/schema.rb index 37a28f16..71d112df 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160826050946) do +ActiveRecord::Schema.define(version: 20160828191211) do create_table "sales", force: :cascade do |t| t.string "customer" @@ -29,11 +29,11 @@ create_table "sales_batches", force: :cascade do |t| t.string "attachment" - t.boolean "processed", default: false t.decimal "revenue", precision: 12, scale: 2, default: 0.0 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "batch_code" + t.string "state" end add_index "sales_batches", ["batch_code"], name: "index_sales_batches_on_batch_code" diff --git a/spec/features/uploading_new_sales_batch_spec.rb b/spec/features/uploading_new_sales_batch_spec.rb new file mode 100644 index 00000000..8095839c --- /dev/null +++ b/spec/features/uploading_new_sales_batch_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +feature 'Uploading and creating new Sales Batch', type: :feature do + let(:sales_batch_file_path) { 'spec/fixtures/sales.txt' } + + before do + visit root_path + attach_file 'sales_batch[attachment]', File.absolute_path(sales_batch_file_path) + click_on 'Enviar' + end + + it '' do + + end +end diff --git a/spec/models/sales_batch_spec.rb b/spec/models/sales_batch_spec.rb index 5a776899..c8a6808b 100644 --- a/spec/models/sales_batch_spec.rb +++ b/spec/models/sales_batch_spec.rb @@ -4,11 +4,11 @@ # # id :integer not null, primary key # attachment :string -# processed :boolean default(FALSE) # revenue :decimal(12, 2) default(0.0) # created_at :datetime not null # updated_at :datetime not null # batch_code :string +# state :string # require 'rails_helper' From 54225ecc24c5353f950f2fc71ac8cb3bef23cf28 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 28 Aug 2016 20:02:21 -0300 Subject: [PATCH 11/27] [development]: Update a readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3f4f1488..558df2cd 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ System sales analysis via log file (.txt) This system works with upload a log sales file (sales batch) and generate a total revenue about this batch. -> Warn: This is not a real system. It is just one example of use Ruby on Rails. +> Warn: This is not a real system. It is just one example of use Ruby on Rails and show my dev skill. ## How to deploy in production -> This project is not done to using in production. +> To write. ## How to build in Development Environment From 2caa1058486bdc7678d214725862356160ce3424 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 19:22:17 -0300 Subject: [PATCH 12/27] [react]: Install react on project Using gem react-rails and command: - rails g react:install Installed react on project (react on rails) --- app/assets/javascripts/application.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index f3f01c63..5b2880da 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,4 +12,7 @@ // //= require jquery/dist/jquery.min //= require bootstrap/dist/js/bootstrap.min +//= require react +//= require react_ujs +//= require components //= require_tree . From 8c0510db8f4bf1c5e76b425d6dd5fa926eb50305 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Fri, 26 Aug 2016 19:35:00 -0300 Subject: [PATCH 13/27] [react]: Add navbar --- app/views/layouts/application.html.erb | 2 ++ app/views/shareds/_navbar.html.erb | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 app/views/shareds/_navbar.html.erb diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 062a7776..6c478afd 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -8,6 +8,8 @@ + <%= render partial: 'shareds/navbar' %> +
<%= yield %>
diff --git a/app/views/shareds/_navbar.html.erb b/app/views/shareds/_navbar.html.erb new file mode 100644 index 00000000..f76077bb --- /dev/null +++ b/app/views/shareds/_navbar.html.erb @@ -0,0 +1,22 @@ + From d4e1a43b3cbcbf2a9a79dee5ace8b1461e25e56a Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 28 Aug 2016 19:58:06 -0300 Subject: [PATCH 14/27] [react]: Layout changes --- app/views/sales_batches/_form_new.html.erb | 26 +++++++++++++----- app/views/sales_batches/index.html.erb | 3 +-- app/views/sales_batches/show.html.erb | 7 +++-- app/views/shareds/_navbar.html.erb | 31 +++++++++++++++++++--- 4 files changed, 52 insertions(+), 15 deletions(-) diff --git a/app/views/sales_batches/_form_new.html.erb b/app/views/sales_batches/_form_new.html.erb index 332d6d06..fb99ee48 100644 --- a/app/views/sales_batches/_form_new.html.erb +++ b/app/views/sales_batches/_form_new.html.erb @@ -1,16 +1,28 @@ +
<%= form_for sales_batch, url: sales_batches_path, html: { class: 'form-inline' } do |f| %> - <%= f.file_field :attachment, class: 'form-control' %> - <%= f.submit 'Enviar', class: 'glyphicon glyphicon-cloud-upload btn btn-success' %> -

Instruções para novo lote

+

Instruções para novo lote

Para criar um novo lote de vendas, selecione um arquivo no formato '.txt' com dados separados por TAB.
A primeira linha do arquivo deve conter os nome das colunas obrigatóriamente: +

Comprador descrição Preço Unitário  Quantidade  Endereço  Fornecedor
+ Você pode baixar um arquivo de exemplo aqui. +
-
Comprador descrição Preço Unitário  Quantidade  Endereço  Fornecedor
- - Você pode baixar um arquivo de exemplo aqui - <%= link_to "Exemplo", "/sales.txt", class: 'glyphicon glyphicon-cloud-download btn-success' %>. + <%= link_to "/sales.txt", class: 'btn btn-success' do %> + + Download de modelo de Arquivo de lote + <% end %>

+
+ +
+ <%= f.file_field :attachment, class: 'form-control' %> + <%= f.button :send, class: 'btn btn-success' do %> + + Enviar novo arquivo de lote + <% end %> +
<% end %> +
diff --git a/app/views/sales_batches/index.html.erb b/app/views/sales_batches/index.html.erb index 104ef376..06ac7eee 100644 --- a/app/views/sales_batches/index.html.erb +++ b/app/views/sales_batches/index.html.erb @@ -1,8 +1,7 @@ -

Splunka

-
<%= render partial: 'form_new', locals: { sales_batch: SalesBatch.new } %>
+
<% #TODO: Move this to presenter %> diff --git a/app/views/sales_batches/show.html.erb b/app/views/sales_batches/show.html.erb index b9c3d4a4..ac0490b9 100644 --- a/app/views/sales_batches/show.html.erb +++ b/app/views/sales_batches/show.html.erb @@ -1,5 +1,5 @@

Dados do lote de venda

-<% if @sales_batch.processed? %> +<% if @sales_batch.resolved? %> @@ -36,4 +36,7 @@

A processar

<%end%> -<%= link_to "Voltar para home", root_path, class: "btn btn-info glyphicon glyphicon-menu-left" %> +<%= link_to root_path, class: "btn btn-info" do %> + + Voltar +<% end %> diff --git a/app/views/shareds/_navbar.html.erb b/app/views/shareds/_navbar.html.erb index f76077bb..b640aa3a 100644 --- a/app/views/shareds/_navbar.html.erb +++ b/app/views/shareds/_navbar.html.erb @@ -1,12 +1,35 @@ + + + + + + + + + ); + } +} + diff --git a/app/assets/javascripts/components/batch_list_table.es6.jsx b/app/assets/javascripts/components/batch_list_table.es6.jsx new file mode 100644 index 00000000..0777d9f3 --- /dev/null +++ b/app/assets/javascripts/components/batch_list_table.es6.jsx @@ -0,0 +1,25 @@ +class BatchListTable extends React.Component { + + + render () { + let createRow = (batch) => ; + + return ( +
#
+ + + + + {this.props.batch.total_sales} + + R$ {this.props.batch.revenue} + +

+ {this.props.batch.state == 'resolved' ? "Concluído" : "A processar"} +

+
+ + + + + + + + + + + {this.props.batches.map(createRow)} + +
Lote Total de vendas Receita Bruta Status
+ ); + } +} + From ee11d22173a683a64eb890f18805cd5ebbe0c869 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 28 Aug 2016 23:31:43 -0300 Subject: [PATCH 17/27] [react]: HACK: Add method to serialization Ok, maybe I should use gem 'active_model_serializers' to create custom serialization attributes to json, but I don't want add one more dependency. On this case I think more appropriate use 'ActiveModel::Serializers::JSON#as_json'. Maybe this change on future, but for now, this solution solve my needs. Read more in: - http://api.rubyonrails.org/classes/ActiveModel/Serialization.html - http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json - http://bit.ly/2bT1ZUN --- app/models/sales_batch.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/models/sales_batch.rb b/app/models/sales_batch.rb index a785a10f..c9fb896f 100644 --- a/app/models/sales_batch.rb +++ b/app/models/sales_batch.rb @@ -39,6 +39,16 @@ class SalesBatch < ActiveRecord::Base end end + def total_sales + self.sales.count + end + + #TODO: Comment this hack on codereview + def as_json(options={}) + options[:methods] = [:total_sales] + super + end + private def generate_batch_code From 7bdd09bebb7bb6c24cef75f3ea40a9266412991a Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 28 Aug 2016 23:42:22 -0300 Subject: [PATCH 18/27] [react]: Using react componetes on sales_batches#index. --- app/views/sales_batches/index.html.erb | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/app/views/sales_batches/index.html.erb b/app/views/sales_batches/index.html.erb index 06ac7eee..0491ac5c 100644 --- a/app/views/sales_batches/index.html.erb +++ b/app/views/sales_batches/index.html.erb @@ -8,26 +8,5 @@ <% if @sales_batches.empty? %> Sem dados <% else %> - - - - - - - - - <% @sales_batches.each do |batch| %> - - - - - - - <% end %> - -
# Batch Total de vendas Receita Bruta Status
<%= link_to "##{batch.id}", sales_batch_path(batch) %><%= batch.sales.count %><%= number_to_currency(batch.revenue, :unit => "R$ ") %> -

- <%= batch.resolved? ? "Processado" : "A processar" %> -

-
+ <%= react_component 'BatchListTable', { batches: @sales_batches } %> <% end %> From 724c5cef26cacef9798d02e0e50f8a7e50e07242 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 14:33:04 -0300 Subject: [PATCH 19/27] Bumps versions and update project * Bump ruby version to 2.4.1 (through .ruby-version file) * Bump Rails version to 4.2.9 * Update ignored files --- .gitignore | 2 ++ .ruby-version | 2 +- Gemfile | 19 +++++++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 7cc2c820..8c005480 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ vendor/assets/components/ public/uploads/ config/database.yml +package-lock.json +node_modules/ diff --git a/.ruby-version b/.ruby-version index ac2cdeba..005119ba 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.1.3 +2.4.1 diff --git a/Gemfile b/Gemfile index d9148307..3ac7be3d 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '4.2.7' +gem 'rails', '4.2.9' # Use sqlite3 as the database for Active Record gem 'sqlite3' @@ -15,18 +15,26 @@ gem 'jbuilder', '~> 2.0' # bundle exec rake doc:rails generates the API under doc/api. gem 'sdoc', '~> 0.4.0', group: :doc +# Webpacker +gem 'webpacker', git: 'https://github.com/rails/webpacker.git' + +gem 'react-rails' +gem 'carrierwave' +gem 'sidekiq' +gem 'state_machines-activerecord' + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'pry-rails' gem 'pry-nav' gem 'annotate' - gem 'thin' + gem 'puma' end group :development do # Spring speeds up development by keeping your application running in the background. # Read more: https://github.com/rails/spring - # gem 'spring' + gem 'spring' end group :test do @@ -38,8 +46,3 @@ group :test do gem 'poltergeist' end -gem 'react-rails' -gem 'carrierwave' -gem 'sidekiq' -gem 'state_machines-activerecord' - From 5724a01c4b8a0660723b367c94f93f00abba037f Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 14:35:28 -0300 Subject: [PATCH 20/27] Update dependency manager with npm Update to use package json to manage JS libs configs. Update README with new information. --- README.md | 8 +++----- bower.json | 4 +--- package.json | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 package.json diff --git a/README.md b/README.md index 558df2cd..fcc5b1ee 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ System sales analysis via log file (.txt) - ## Overview This system works with upload a log sales file (sales batch) and generate a total revenue about this batch. @@ -30,12 +29,11 @@ you server should listen in http://localhost:3000/ ### Requirements -- Ruby 2.1.3 -- Rails 4.2.7 +- Ruby 2.4.1 +- Rails 4.2.9 +- Redis (on ubuntu run `sudo apt install redis-server` - SQLite 3 (in ubuntu run `sudo apt-get install -y sqlite3 libsqlite3-dev`) - Gem Bundler (`gem install bundler`) - NodeJS - Bower (`npm install bower -g`) - PhantomJS (to run features specs) - - diff --git a/bower.json b/bower.json index 63931ebf..c22c2dd2 100644 --- a/bower.json +++ b/bower.json @@ -1,8 +1,6 @@ { "name": "Splunka", - "authors": [ - "Paulo Patto " - ], + "authors": [ "Paulo Patto " ], "description": "", "main": "", "license": "MIT", diff --git a/package.json b/package.json new file mode 100644 index 00000000..a35658bf --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "splunka", + "version": "0.0.1", + "description": "My description", + "main": "index.js", + "directories": { + "lib": "lib" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/paulopatto/Splunka.git" + }, + "keywords": [ + "rails", + "react" + ], + "author": "Paulo Patto ", + "license": "MIT", + "bugs": { + "url": "https://github.com/paulopatto/Splunka/issues" + }, + "homepage": "https://github.com/paulopatto/Splunka#readme", + "dependencies": { + "bower": "^1.8.0", + "phantomjs": "^2.1.7" + } +} From 7894e956e63162a5944cfa5819a21e3c2e3545db Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 14:40:31 -0300 Subject: [PATCH 21/27] Bump gem versions Bump gemfile.lock and remove some files. --- Gemfile.lock | 260 +++++++++++++++++++++++++------------------------- codereview.md | 0 task.md | 42 ++++---- 3 files changed, 150 insertions(+), 152 deletions(-) delete mode 100644 codereview.md diff --git a/Gemfile.lock b/Gemfile.lock index 63a3e7de..e4d57b55 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,103 +1,105 @@ +GIT + remote: https://github.com/rails/webpacker.git + revision: 3947386f8fc0dbec39d2315c6a336717b2a9e532 + specs: + webpacker (3.0.1) + activesupport (>= 4.2) + rack-proxy (>= 0.6.1) + railties (>= 4.2) + GEM remote: https://rubygems.org/ specs: - actionmailer (4.2.7) - actionpack (= 4.2.7) - actionview (= 4.2.7) - activejob (= 4.2.7) + actionmailer (4.2.9) + actionpack (= 4.2.9) + actionview (= 4.2.9) + activejob (= 4.2.9) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.7) - actionview (= 4.2.7) - activesupport (= 4.2.7) + actionpack (4.2.9) + actionview (= 4.2.9) + activesupport (= 4.2.9) rack (~> 1.6) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.7) - activesupport (= 4.2.7) + actionview (4.2.9) + activesupport (= 4.2.9) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (4.2.7) - activesupport (= 4.2.7) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (4.2.9) + activesupport (= 4.2.9) globalid (>= 0.3.0) - activemodel (4.2.7) - activesupport (= 4.2.7) + activemodel (4.2.9) + activesupport (= 4.2.9) builder (~> 3.1) - activerecord (4.2.7) - activemodel (= 4.2.7) - activesupport (= 4.2.7) + activerecord (4.2.9) + activemodel (= 4.2.9) + activesupport (= 4.2.9) arel (~> 6.0) - activesupport (4.2.7) + activesupport (4.2.9) i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.4.0) - annotate (2.7.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + annotate (2.7.2) activerecord (>= 3.2, < 6.0) - rake (>= 10.4, < 12.0) - arel (6.0.3) + rake (>= 10.4, < 13.0) + arel (6.0.4) babel-source (5.8.35) babel-transpiler (0.7.0) babel-source (>= 4.0, < 6) execjs (~> 2.0) - builder (3.2.2) - capybara (2.8.1) + builder (3.2.3) + capybara (2.15.1) addressable - mime-types (>= 1.16) + mini_mime (>= 0.1.3) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - carrierwave (0.11.2) - activemodel (>= 3.2.0) - activesupport (>= 3.2.0) - json (>= 1.7) + carrierwave (1.1.0) + activemodel (>= 4.0.0) + activesupport (>= 4.0.0) mime-types (>= 1.16) - mimemagic (>= 0.3.0) cliver (0.3.2) - coderay (1.1.1) - coffee-script-source (1.10.0) - concurrent-ruby (1.0.2) - connection_pool (2.2.0) - daemons (1.2.4) - diff-lcs (1.2.5) + coderay (1.1.2) + concurrent-ruby (1.0.5) + connection_pool (2.2.1) + diff-lcs (1.3) erubis (2.7.0) - eventmachine (1.2.0.1) execjs (2.7.0) - factory_girl (4.7.0) + factory_girl (4.8.0) activesupport (>= 3.0.0) - factory_girl_rails (4.7.0) - factory_girl (~> 4.7.0) + factory_girl_rails (4.8.0) + factory_girl (~> 4.8.0) railties (>= 3.0.0) - globalid (0.3.7) - activesupport (>= 4.1.0) - i18n (0.7.0) - jbuilder (2.6.0) - activesupport (>= 3.0.0, < 5.1) - multi_json (~> 1.2) - json (1.8.3) + globalid (0.4.0) + activesupport (>= 4.2.0) + i18n (0.8.6) + jbuilder (2.7.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + json (1.8.6) loofah (2.0.3) nokogiri (>= 1.5.9) - mail (2.6.4) + mail (2.6.6) mime-types (>= 1.16, < 4) method_source (0.8.2) mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) - mimemagic (0.3.2) - mini_portile2 (2.1.0) - minitest (5.9.0) + mini_mime (0.1.4) + mini_portile2 (2.2.0) + minitest (5.10.3) multi_json (1.12.1) - nokogiri (1.6.8) - mini_portile2 (~> 2.1.0) - pkg-config (~> 1.1.7) - pkg-config (1.1.7) - poltergeist (1.10.0) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) + poltergeist (1.16.0) capybara (~> 2.1) cliver (~> 0.3.1) websocket-driver (>= 0.2.0) @@ -107,117 +109,109 @@ GEM slop (~> 3.4) pry-nav (0.2.4) pry (>= 0.9.10, < 0.11.0) - pry-rails (0.3.4) - pry (>= 0.9.10) - rack (1.6.4) - rack-protection (1.5.3) + pry-rails (0.3.6) + pry (>= 0.10.4) + public_suffix (3.0.0) + puma (3.10.0) + rack (1.6.8) + rack-protection (2.0.0) + rack + rack-proxy (0.6.2) rack rack-test (0.6.3) rack (>= 1.0) - rails (4.2.7) - actionmailer (= 4.2.7) - actionpack (= 4.2.7) - actionview (= 4.2.7) - activejob (= 4.2.7) - activemodel (= 4.2.7) - activerecord (= 4.2.7) - activesupport (= 4.2.7) + rails (4.2.9) + actionmailer (= 4.2.9) + actionpack (= 4.2.9) + actionview (= 4.2.9) + activejob (= 4.2.9) + activemodel (= 4.2.9) + activerecord (= 4.2.9) + activesupport (= 4.2.9) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.7) + railties (= 4.2.9) sprockets-rails rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.7) + rails-dom-testing (1.0.8) activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) + nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.3) loofah (~> 2.0) - railties (4.2.7) - actionpack (= 4.2.7) - activesupport (= 4.2.7) + railties (4.2.9) + actionpack (= 4.2.9) + activesupport (= 4.2.9) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (11.2.2) - rdoc (4.2.2) - json (~> 1.4) - react-rails (1.8.2) + rake (12.0.0) + rdoc (4.3.0) + react-rails (2.2.1) babel-transpiler (>= 0.7.0) - coffee-script-source (~> 1.8) connection_pool execjs railties (>= 3.2) tilt - redis (3.3.1) - rspec (3.5.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-core (3.5.2) - rspec-support (~> 3.5.0) - rspec-expectations (3.5.0) + redis (3.3.3) + rspec-core (3.6.0) + rspec-support (~> 3.6.0) + rspec-expectations (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-mocks (3.5.0) + rspec-support (~> 3.6.0) + rspec-mocks (3.6.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-rails (3.5.2) + rspec-support (~> 3.6.0) + rspec-rails (3.6.1) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-support (~> 3.5.0) - rspec-sidekiq (2.2.0) - rspec (~> 3.0, >= 3.0.0) + rspec-core (~> 3.6.0) + rspec-expectations (~> 3.6.0) + rspec-mocks (~> 3.6.0) + rspec-support (~> 3.6.0) + rspec-sidekiq (3.0.3) + rspec-core (~> 3.0, >= 3.0.0) sidekiq (>= 2.4.0) - rspec-support (3.5.0) - sdoc (0.4.1) + rspec-support (3.6.0) + sdoc (0.4.2) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) - shoulda-matchers (3.1.1) + shoulda-matchers (3.1.2) activesupport (>= 4.0.0) - sidekiq (4.1.4) + sidekiq (5.0.4) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) - redis (~> 3.2, >= 3.2.1) - sinatra (>= 1.4.7) - sinatra (1.4.7) - rack (~> 1.5) - rack-protection (~> 1.4) - tilt (>= 1.3, < 3) + rack-protection (>= 1.5.0) + redis (~> 3.3, >= 3.3.3) slop (3.6.0) - sprockets (3.7.0) + spring (2.0.2) + activesupport (>= 4.2) + sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.1.1) + sprockets-rails (3.2.1) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sqlite3 (1.3.11) - state_machines (0.4.0) - state_machines-activemodel (0.4.0) - activemodel (>= 4.1, < 5.1) - state_machines (>= 0.4.0) - state_machines-activerecord (0.4.0) - activerecord (>= 4.1, < 5.1) - state_machines-activemodel (>= 0.3.0) - thin (1.7.0) - daemons (~> 1.0, >= 1.0.9) - eventmachine (~> 1.0, >= 1.0.4) - rack (>= 1, < 3) - thor (0.19.1) - thread_safe (0.3.5) - tilt (2.0.5) - tzinfo (1.2.2) + sqlite3 (1.3.13) + state_machines (0.5.0) + state_machines-activemodel (0.5.0) + activemodel (>= 4.1, < 5.2) + state_machines (>= 0.5.0) + state_machines-activerecord (0.5.0) + activerecord (>= 4.1, < 5.2) + state_machines-activemodel (>= 0.5.0) + thor (0.20.0) + thread_safe (0.3.6) + tilt (2.0.8) + tzinfo (1.2.3) thread_safe (~> 0.1) - uglifier (3.0.2) + uglifier (3.2.0) execjs (>= 0.3.0, < 3) - websocket-driver (0.6.4) + websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) - xpath (2.0.0) + xpath (2.1.0) nokogiri (~> 1.3) PLATFORMS @@ -232,17 +226,19 @@ DEPENDENCIES poltergeist pry-nav pry-rails - rails (= 4.2.7) + puma + rails (= 4.2.9) react-rails rspec-rails rspec-sidekiq sdoc (~> 0.4.0) shoulda-matchers sidekiq + spring sqlite3 state_machines-activerecord - thin uglifier (>= 1.3.0) + webpacker! BUNDLED WITH - 1.12.5 + 1.15.4 diff --git a/codereview.md b/codereview.md deleted file mode 100644 index e69de29b..00000000 diff --git a/task.md b/task.md index 5e5ee7a3..61a764b3 100644 --- a/task.md +++ b/task.md @@ -4,10 +4,10 @@ A idéia deste desafio é nos permitir avaliar melhor as habilidades de candidat Este desafio deve ser feito por você em sua casa. Gaste o tempo que você quiser, porém normalmente você não deve precisar de mais do que algumas horas. ## Instruções de entrega do desafio -1. Primeiro, faça um fork deste projeto para sua conta no Github (crie uma se você não possuir). -2. Em seguida, implemente o projeto tal qual descrito abaixo, em seu próprio fork. -3. Crie as instruções de instalação e execução do aplicativo em seu readme.md -4. Por fim, envie o link do seu repositorio para avaliarmos seu código +- 1. Primeiro, faça um fork deste projeto para sua conta no Github (crie uma se você não possuir). +- 2. Em seguida, implemente o projeto tal qual descrito abaixo, em seu próprio fork. +- 3. Crie as instruções de instalação e execução do aplicativo em seu readme.md +- 4. Por fim, envie o link do seu repositorio para avaliarmos seu código ## Descrição do projeto @@ -17,27 +17,29 @@ Sua tarefa é criar uma interface web que aceite upload de arquivos, normalize o Sua aplicação web DEVE: -1. Aceitar (via um formulário) o upload de arquivos text, com dados separados por TAB testar o aplicativo usando o arquivo fornecido. A primeira linha do arquivo tem o nome das colunas. Você pode assumir que as colunas estarão sempre nesta ordem, e que sempre haverá uma linha de cabeçalho. Um arquivo de exemplo chamado 'dados.txt' está incluído neste repositório. -2. Interpretar ("parsear") o arquivo recebido, normalizar os dados, e salvar corretamente a informação em um banco de dados relacional. -3. Exibir todos os registros importados, bem como a receita bruta total dos registros contidos no arquivo enviado após o upload + parser. -4. Se sua vaga é para Ruby e Ruby On Rails, ser escrita obrigatoriamente em: Ruby 2.1+ Rails 4 e SQLite -5. Se sua vaga é para .Net ser escrita obrigatoriamente em: VB# ou C#, última versão, SQL Server (pode ser express) -6. Ser simples de configurar e rodar a partir das instruções fornecidas, -7. funcionando em ambiente compatível com Unix (Linux ou Mac OS X) para Ruby On Rails e Windows para .Net. Ela deve utilizar apenas linguagens e bibliotecas livres ou gratuitas. -8. Ter um teste de model e controller automatizado para a funcionalidade pedida -9. Ter uma boa aparecia e ser fácil de usar +- 1. Aceitar (via um formulário) o upload de arquivos text, com dados separados por TAB testar o aplicativo usando o arquivo fornecido. A primeira linha do arquivo tem o nome das colunas. Você pode assumir que as colunas estarão sempre nesta ordem, e que sempre haverá uma linha de cabeçalho. Um arquivo de exemplo chamado 'dados.txt' está incluído neste repositório. +- 2. Interpretar ("parsear") o arquivo recebido, normalizar os dados, e salvar corretamente a informação em um banco de dados relacional. +- 3. Exibir todos os registros importados, bem como a receita bruta total dos registros contidos no arquivo enviado após o upload + parser. +- 4. Se sua vaga é para Ruby e Ruby On Rails, ser escrita obrigatoriamente em: Ruby 2.1+ Rails 4 e SQLite +- 5. Se sua vaga é para .Net ser escrita obrigatoriamente em: VB# ou C#, última versão, SQL Server (pode ser express) +- 6. Ser simples de configurar e rodar a partir das instruções fornecidas, +- 7. funcionando em ambiente compatível com Unix (Linux ou Mac OS X) para Ruby On Rails e Windows para .Net. Ela deve utilizar apenas linguagens e bibliotecas livres ou gratuitas. +- 8. Ter um teste de model e controller automatizado para a funcionalidade pedida +- 9. Ter uma boa aparecia e ser fácil de usar ## Avaliação Seu projeto será avaliado de acordo com os seguintes critérios. -1. Sua aplicação atende funcionalmente o que foi pedido -2. Você documentou a maneira de configurar o ambiente e rodar sua aplicação na maquina do avaliador -3. Você seguiu as instruções enviadas -4. Voce segue as boas práticas de programação e entrega para o Cliente -5. O código escrito é facil de entender e manter -6. Você se preocupa com o uso do aplicativo pelo Usuário +- 1. Sua aplicação atende funcionalmente o que foi pedido +- 2. Você documentou a maneira de configurar o ambiente e rodar sua aplicação na maquina do avaliador +- 3. Você seguiu as instruções enviadas +- 4. Voce segue as boas práticas de programação e entrega para o Cliente +- 5. O código escrito é facil de entender e manter +- 6. Você se preocupa com o uso do aplicativo pelo Usuário -Adicionalmente, tentaremos verificar a sua familiarização com as bibliotecas padrões (standard libs), bem como sua experiência com programação orientada a objetos a partir da estrutura de seu projeto, preucupação com o objetivo da aplicação e do seu uso pelo usuário, suporte e manutenção do código por outros desenvolvdores +Adicionalmente, tentaremos verificar a sua familiarização com as bibliotecas padrões (standard libs), +bem como sua experiência com programação orientada a objetos a partir da estrutura de seu projeto, +preucupação com o objetivo da aplicação e do seu uso pelo usuário, suporte e manutenção do código por outros desenvolvdores. ### Referência From bcc5c09e1d957bf17bfa441e6ec3ac55dd186132 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 15:30:18 -0300 Subject: [PATCH 22/27] Add yarn --- .gitignore | 3 +++ package.json | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8c005480..6ea052c7 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ public/uploads/ config/database.yml package-lock.json node_modules/ +/public/packs +/public/packs-test +/node_modules diff --git a/package.json b/package.json index a35658bf..72096f41 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,12 @@ }, "homepage": "https://github.com/paulopatto/Splunka#readme", "dependencies": { + "@rails/webpacker": "^3.0.1", "bower": "^1.8.0", - "phantomjs": "^2.1.7" + "phantomjs": "^2.1.7", + "yarn": "^0.27.5" + }, + "devDependencies": { + "webpack-dev-server": "^2.7.1" } } From 5495ee4fca42de0d76b6f5f6395c5b876ba87658 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 15:32:05 -0300 Subject: [PATCH 23/27] Add babel --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 72096f41..2d010ffa 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,12 @@ "homepage": "https://github.com/paulopatto/Splunka#readme", "dependencies": { "@rails/webpacker": "^3.0.1", + "babel-preset-react": "^6.24.1", "bower": "^1.8.0", "phantomjs": "^2.1.7", + "prop-types": "^15.5.10", + "react": "^15.6.1", + "react-dom": "^15.6.1", "yarn": "^0.27.5" }, "devDependencies": { From a5ed32cd0573e166a56cfd9a3e2b4daa099cdc90 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 15:33:01 -0300 Subject: [PATCH 24/27] Webpacker files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Arquivos gerados com a instalação do webpacker... ```sh $ bundle exec rake webpacker:install $ bundle exec rake webpacker:install:react $ bundle exec rails generate react:install # (not runned) ``` ---- See more in https://github.com/reactjs/react-rails --- .babelrc | 26 +++++++++++ .postcssrc.yml | 3 ++ app/javascript/packs/application.js | 10 ++++ app/javascript/packs/hello_react.jsx | 26 +++++++++++ bin/webpack | 27 +++++++++++ bin/webpack-dev-server | 68 ++++++++++++++++++++++++++++ config/webpack/development.js | 3 ++ config/webpack/environment.js | 3 ++ config/webpack/production.js | 3 ++ config/webpack/test.js | 3 ++ config/webpacker.yml | 56 +++++++++++++++++++++++ 11 files changed, 228 insertions(+) create mode 100644 .babelrc create mode 100644 .postcssrc.yml create mode 100644 app/javascript/packs/application.js create mode 100644 app/javascript/packs/hello_react.jsx create mode 100755 bin/webpack create mode 100755 bin/webpack-dev-server create mode 100644 config/webpack/development.js create mode 100644 config/webpack/environment.js create mode 100644 config/webpack/production.js create mode 100644 config/webpack/test.js create mode 100644 config/webpacker.yml diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..75e4c04e --- /dev/null +++ b/.babelrc @@ -0,0 +1,26 @@ +{ + "presets": [ + [ + "env", + { + "modules": false, + "targets": { + "browsers": "> 1%", + "uglify": true + }, + "useBuiltIns": true + } + ], + "react" + ], + "plugins": [ + "syntax-dynamic-import", + "transform-object-rest-spread", + [ + "transform-class-properties", + { + "spec": true + } + ] + ] +} diff --git a/.postcssrc.yml b/.postcssrc.yml new file mode 100644 index 00000000..a123d1fd --- /dev/null +++ b/.postcssrc.yml @@ -0,0 +1,3 @@ +plugins: + postcss-smart-import: {} + postcss-cssnext: {} diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js new file mode 100644 index 00000000..54b106ee --- /dev/null +++ b/app/javascript/packs/application.js @@ -0,0 +1,10 @@ +/* eslint no-console:0 */ +// This file is automatically compiled by Webpack, along with any other files +// present in this directory. You're encouraged to place your actual application logic in +// a relevant structure within app/javascript and only use these pack files to reference +// that code so it'll be compiled. +// +// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate +// layout file, like app/views/layouts/application.html.erb + +console.log('Hello World from Webpacker') diff --git a/app/javascript/packs/hello_react.jsx b/app/javascript/packs/hello_react.jsx new file mode 100644 index 00000000..772fc97e --- /dev/null +++ b/app/javascript/packs/hello_react.jsx @@ -0,0 +1,26 @@ +// Run this example by adding <%= javascript_pack_tag 'hello_react' %> to the head of your layout file, +// like app/views/layouts/application.html.erb. All it does is render
Hello React
at the bottom +// of the page. + +import React from 'react' +import ReactDOM from 'react-dom' +import PropTypes from 'prop-types' + +const Hello = props => ( +
Hello {props.name}!
+) + +Hello.defaultProps = { + name: 'David' +} + +Hello.propTypes = { + name: PropTypes.string +} + +document.addEventListener('DOMContentLoaded', () => { + ReactDOM.render( + , + document.body.appendChild(document.createElement('div')), + ) +}) diff --git a/bin/webpack b/bin/webpack new file mode 100755 index 00000000..528233a7 --- /dev/null +++ b/bin/webpack @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +$stdout.sync = true + +require "shellwords" + +ENV["RAILS_ENV"] ||= "development" +RAILS_ENV = ENV["RAILS_ENV"] + +ENV["NODE_ENV"] ||= RAILS_ENV +NODE_ENV = ENV["NODE_ENV"] + +APP_PATH = File.expand_path("../", __dir__) +NODE_MODULES_PATH = File.join(APP_PATH, "node_modules") +WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/#{NODE_ENV}.js") + +unless File.exist?(WEBPACK_CONFIG) + puts "Webpack configuration not found." + puts "Please run bundle exec rails webpacker:install to install webpacker" + exit! +end + +env = { "NODE_PATH" => NODE_MODULES_PATH.shellescape } +cmd = [ "#{NODE_MODULES_PATH}/.bin/webpack", "--config", WEBPACK_CONFIG ] + ARGV + +Dir.chdir(APP_PATH) do + exec env, *cmd +end diff --git a/bin/webpack-dev-server b/bin/webpack-dev-server new file mode 100755 index 00000000..c9672f66 --- /dev/null +++ b/bin/webpack-dev-server @@ -0,0 +1,68 @@ +#!/usr/bin/env ruby +$stdout.sync = true + +require "shellwords" +require "yaml" +require "socket" + +ENV["RAILS_ENV"] ||= "development" +RAILS_ENV = ENV["RAILS_ENV"] + +ENV["NODE_ENV"] ||= RAILS_ENV +NODE_ENV = ENV["NODE_ENV"] + +APP_PATH = File.expand_path("../", __dir__) +CONFIG_FILE = File.join(APP_PATH, "config/webpacker.yml") +NODE_MODULES_PATH = File.join(APP_PATH, "node_modules") +WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/#{NODE_ENV}.js") + +DEFAULT_LISTEN_HOST_ADDR = NODE_ENV == 'development' ? 'localhost' : '0.0.0.0' + +def args(key) + index = ARGV.index(key) + index ? ARGV[index + 1] : nil +end + +begin + dev_server = YAML.load_file(CONFIG_FILE)[RAILS_ENV]["dev_server"] + + HOSTNAME = args('--host') || dev_server["host"] + PORT = args('--port') || dev_server["port"] + HTTPS = ARGV.include?('--https') || dev_server["https"] + DEV_SERVER_ADDR = "http#{"s" if HTTPS}://#{HOSTNAME}:#{PORT}" + LISTEN_HOST_ADDR = args('--listen-host') || DEFAULT_LISTEN_HOST_ADDR + +rescue Errno::ENOENT, NoMethodError + $stdout.puts "Webpack dev_server configuration not found in #{CONFIG_FILE}." + $stdout.puts "Please run bundle exec rails webpacker:install to install webpacker" + exit! +end + +begin + server = TCPServer.new(LISTEN_HOST_ADDR, PORT) + server.close + +rescue Errno::EADDRINUSE + $stdout.puts "Another program is running on port #{PORT}. Set a new port in #{CONFIG_FILE} for dev_server" + exit! +end + +# Delete supplied host, port and listen-host CLI arguments +["--host", "--port", "--listen-host"].each do |arg| + ARGV.delete(args(arg)) + ARGV.delete(arg) +end + +env = { "NODE_PATH" => NODE_MODULES_PATH.shellescape } + +cmd = [ + "#{NODE_MODULES_PATH}/.bin/webpack-dev-server", "--progress", "--color", + "--config", WEBPACK_CONFIG, + "--host", LISTEN_HOST_ADDR, + "--public", "#{HOSTNAME}:#{PORT}", + "--port", PORT.to_s +] + ARGV + +Dir.chdir(APP_PATH) do + exec env, *cmd +end diff --git a/config/webpack/development.js b/config/webpack/development.js new file mode 100644 index 00000000..81269f65 --- /dev/null +++ b/config/webpack/development.js @@ -0,0 +1,3 @@ +const environment = require('./environment') + +module.exports = environment.toWebpackConfig() diff --git a/config/webpack/environment.js b/config/webpack/environment.js new file mode 100644 index 00000000..d16d9af7 --- /dev/null +++ b/config/webpack/environment.js @@ -0,0 +1,3 @@ +const { environment } = require('@rails/webpacker') + +module.exports = environment diff --git a/config/webpack/production.js b/config/webpack/production.js new file mode 100644 index 00000000..81269f65 --- /dev/null +++ b/config/webpack/production.js @@ -0,0 +1,3 @@ +const environment = require('./environment') + +module.exports = environment.toWebpackConfig() diff --git a/config/webpack/test.js b/config/webpack/test.js new file mode 100644 index 00000000..81269f65 --- /dev/null +++ b/config/webpack/test.js @@ -0,0 +1,3 @@ +const environment = require('./environment') + +module.exports = environment.toWebpackConfig() diff --git a/config/webpacker.yml b/config/webpacker.yml new file mode 100644 index 00000000..e62a7acd --- /dev/null +++ b/config/webpacker.yml @@ -0,0 +1,56 @@ +# Note: You must restart bin/webpack-dev-server for changes to take effect + +default: &default + source_path: app/javascript + source_entry_path: packs + public_output_path: packs + cache_path: tmp/cache/webpacker + + # Additional paths webpack should lookup modules + # ['app/assets', 'engine/foo/app/assets'] + resolved_paths: [] + + # Reload manifest.json on all requests so we reload latest compiled packs + cache_manifest: false + + extensions: + - .coffee + - .erb + - .js + - .jsx + - .ts + - .vue + - .sass + - .scss + - .css + - .png + - .svg + - .gif + - .jpeg + - .jpg + +development: + <<: *default + compile: true + + dev_server: + host: localhost + port: 3035 + hmr: false + https: false + +test: + <<: *default + compile: true + + # Compile test packs to a separate directory + public_output_path: packs-test + +production: + <<: *default + + # Production depends on precompilation of packs prior to booting for performance. + compile: false + + # Cache manifest.json for performance + cache_manifest: true From 17c30844b45e767373d1c28cdfd7dd257e803c25 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 15:35:16 -0300 Subject: [PATCH 25/27] update ignore files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6ea052c7..f3afbfeb 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ node_modules/ /public/packs /public/packs-test /node_modules +yarn.lock From 255f8a10af7ccb84d8e8d2e3fa3bdbd5b8fe9fa0 Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 15:35:39 -0300 Subject: [PATCH 26/27] WIP: Stated config docker --- docker-compose.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..2d7a97c9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,21 @@ +version: '2' +services: + db: + image: postgres + redis: + image: redis + # worker: + # build: . + # command: bundle exec sidkiq -C config/sidekiq.yml + # volumes: + # - .:/opt/splunka + web: + build: . + command: bundle exec rails server -p 3000 -b '0.0.0.0' + volumes: + - .:/opt/splunka + ports: + - '3000':'3000' + depends_on: + - db + - redis From 428e2bbce96d020a701ad840aa69721fc35c239f Mon Sep 17 00:00:00 2001 From: Paulo Patto Date: Sun, 3 Sep 2017 15:48:14 -0300 Subject: [PATCH 27/27] update compose --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 2d7a97c9..374de222 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,8 @@ services: image: postgres redis: image: redis + ports: + - "6379":"6379" # worker: # build: . # command: bundle exec sidkiq -C config/sidekiq.yml