问:
Issue deploying rails app on heroku
I am new to rails and I was to work on a code. The website works perfect on my local but when deploying remotely on heroku, the css files seem not found.

I am running the app with ruby 2.4, Rails 5.0 and gemfile

```<code>source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

gem 'bootstrap-sass', '~> 3.3', '>= 3.3.7'
gem 'autoprefixer-rails'
gem 'font-awesome-rails', '~> 4.6', '>= 4.6.3.1'
gem 'animate-rails', '~> 1.0', '>= 1.0.10'
gem 'owlcarousel-rails', '~> 1.1', '>= 1.1.3.3'
gem 'wow-rails', '~> 0.0.1'
gem 'magnific-popup-rails', '~> 1.1'
gem 'google-api-client', '~> 0.12.0'
gem 'figaro'
# cron task
gem 'whenever', require: false
# Authentication
gem 'devise'
gem 'cancancan', '~> 1.15'
# serach and autocompletion
gem 'pg_search'
# mailer dev
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.3'
# Use sqlite3 as the database for Active Record
gem 'pg'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Use jquery as the JavaScript library
gem 'jquery-rails'
gem 'jquery-ui-rails', '~> 5.0'
gem 'rails_admin', :git => 'git://github.com/sferik/rails_admin.git'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
#gem 'capistrano3-puma', github: "seuros/capistrano-puma"

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.0.5'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  # Use Capistrano for deployment
  gem 'capistrano'
  gem 'capistrano-rails'
  gem 'capistrano-rvm'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

ruby "2.4.1"
</code>```

Here's the log via the command heroku log --tail

```<code>2017-11-16T16:07:52.898937+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 6818 -e production`
2017-11-16T16:07:58.371812+00:00 app[web.1]: => Booting Puma
2017-11-16T16:07:58.371821+00:00 app[web.1]: => Rails 5.0.6 application starting in production on http://0.0.0.0:6818
2017-11-16T16:07:58.371822+00:00 app[web.1]: => Run `rails server -h` for more startup options
2017-11-16T16:07:58.371822+00:00 app[web.1]: Puma starting in single mode...
2017-11-16T16:07:58.371827+00:00 app[web.1]: * Version 3.10.0 (ruby 2.4.1-p111), codename: Russell's Teapot
2017-11-16T16:07:58.371828+00:00 app[web.1]: * Min threads: 5, max threads: 5
2017-11-16T16:07:58.371828+00:00 app[web.1]: * Environment: production
2017-11-16T16:07:58.371978+00:00 app[web.1]: * Listening on tcp://0.0.0.0:6818
2017-11-16T16:07:58.372379+00:00 app[web.1]: Use Ctrl-C to stop
2017-11-16T16:07:58.939021+00:00 heroku[web.1]: State changed from starting to up
2017-11-16T16:07:59.757157+00:00 app[web.1]: I, [2017-11-16T16:07:59.757044 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3] Started GET "/" for 80.12.27.252 at 2017-11-16 16:07:59 +0000
2017-11-16T16:07:59.766621+00:00 app[web.1]: I, [2017-11-16T16:07:59.766547 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendering pages/index.html.erb within layouts/application
2017-11-16T16:07:59.763739+00:00 app[web.1]: I, [2017-11-16T16:07:59.763642 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3] Processing by PagesController#index as HTML
2017-11-16T16:07:59.767481+00:00 app[web.1]: I, [2017-11-16T16:07:59.767416 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendered pages/index.html.erb within layouts/application (0.7ms)
2017-11-16T16:07:59.936841+00:00 app[web.1]: I, [2017-11-16T16:07:59.936713 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendered layouts/_nav.html.erb (0.4ms)
2017-11-16T16:07:59.941558+00:00 app[web.1]: I, [2017-11-16T16:07:59.941458 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendered layouts/_footer.html.erb (4.1ms)
2017-11-16T16:07:59.941919+00:00 app[web.1]: I, [2017-11-16T16:07:59.941858 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3] Completed 200 OK in 178ms (Views: 177.2ms)
2017-11-16T16:07:59.942814+00:00 heroku[router]: at=info method=GET path="/" host=mysterious-crag-68857.herokuapp.com request_id=b03307de-5170-474a-9f27-50cd05bf07a3 fwd="80.12.27.252" dyno=web.1 connect=0ms service=190ms status=200 bytes=14894 protocol=https
2017-11-16T16:08:00.224613+00:00 heroku[router]: at=info method=GET path="/assets/application-cbd352f84234371962220aac536e7439e570099d31857c088b4e6d82141e9206.css" host=mysterious-crag-68857.herokuapp.com request_id=d2c6dfd6-4660-4844-9d44-143e3d21b917 fwd="80.12.27.252" dyno=web.1 connect=5ms service=10ms status=200 bytes=290 protocol=https
2017-11-16T16:08:00.469689+00:00 heroku[router]: at=info method=GET path="/assets/fondation_pierre_fabre.png" host=mysterious-crag-68857.herokuapp.com request_id=c7adcbdd-8478-4916-9aff-0a90a52058bc fwd="80.12.27.252" dyno=web.1 connect=0ms service=8ms status=200 bytes=3889 protocol=https
2017-11-16T16:08:00.354457+00:00 heroku[router]: at=info method=GET path="/assets/logo2.png" host=mysterious-crag-68857.herokuapp.com request_id=720bf865-6dc4-401f-aac2-bf8eb96c5e90 fwd="80.12.27.252" dyno=web.1 connect=0ms service=5ms status=200 bytes=15746 protocol=https
2017-11-16T16:08:00.331984+00:00 heroku[router]: at=info method=GET path="/assets/application-7a19b05aebcc1264ba7bc75e8a9ab79af4669370f312952095c90b8160480841.js" host=mysterious-crag-68857.herokuapp.com request_id=c58820a6-ce78-43d8-b9da-f188ab36a9d4 fwd="80.12.27.252" dyno=web.1 connect=0ms service=3ms status=200 bytes=303 protocol=https
2017-11-16T16:08:00.351225+00:00 app[web.1]: I, [2017-11-16T16:08:00.351111 #4]  INFO -- : [720bf865-6dc4-401f-aac2-bf8eb96c5e90] Started GET "/assets/logo2.png" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.464437+00:00 app[web.1]: I, [2017-11-16T16:08:00.464337 #4]  INFO -- : [62f2a2a3-392b-446d-be9b-a32e38f68397] Started GET "/assets/single_folio/featured1.jpg" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.465587+00:00 app[web.1]: I, [2017-11-16T16:08:00.464658 #4]  INFO -- : [c7adcbdd-8478-4916-9aff-0a90a52058bc] Started GET "/assets/fondation_pierre_fabre.png" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.582164+00:00 app[web.1]: I, [2017-11-16T16:08:00.582059 #4]  INFO -- : [2c5ed467-5129-4e52-9794-c22a611efaec] Started GET "/assets/logo_altran.png" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.480539+00:00 heroku[router]: at=info method=GET path="/assets/single_folio/featured1.jpg" host=mysterious-crag-68857.herokuapp.com request_id=62f2a2a3-392b-446d-be9b-a32e38f68397 fwd="80.12.27.252" dyno=web.1 connect=1ms service=19ms status=200 bytes=230727 protocol=https
2017-11-16T16:08:00.628238+00:00 heroku[router]: at=info method=GET path="/assets/home/build.jpg" host=mysterious-crag-68857.herokuapp.com request_id=f9d88aa4-d176-4190-8ad7-08f15cffc6fd fwd="80.12.27.252" dyno=web.1 connect=0ms service=7ms status=200 bytes=19242 protocol=https
2017-11-16T16:08:00.584670+00:00 heroku[router]: at=info method=GET path="/assets/logo_altran.png" host=mysterious-crag-68857.herokuapp.com request_id=2c5ed467-5129-4e52-9794-c22a611efaec fwd="80.12.27.252" dyno=web.1 connect=0ms service=4ms status=200 bytes=8918 protocol=https
2017-11-16T16:08:00.623571+00:00 app[web.1]: I, [2017-11-16T16:08:00.623424 #4]  INFO -- : [f9d88aa4-d176-4190-8ad7-08f15cffc6fd] Started GET "/assets/home/build.jpg" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:01.911423+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=mysterious-crag-68857.herokuapp.com request_id=69791277-1eb3-4067-a23a-51987305595b fwd="80.12.27.252" dyno=web.1 connect=1ms service=1ms status=200 bytes=180 protocol=https
2017-11-16T16:08:04.306986+00:00 heroku[router]: at=info method=GET path="/assets/application-cbd352f84234371962220aac536e7439e570099d31857c088b4e6d82141e9206.css" host=mysterious-crag-68857.herokuapp.com request_id=9d090e84-2bfe-49d8-afe1-7a5769d84497 fwd="80.12.27.252" dyno=web.1 connect=1ms service=5ms status=304 bytes=48 protocol=https
2017-11-16T16:12:50.000000+00:00 app[api]: Build started by user benchoufi.mehdi@gmail.com
2017-11-16T16:13:08.103929+00:00 heroku[web.1]: Restarting
2017-11-16T16:13:08.116568+00:00 heroku[web.1]: State changed from up to starting
2017-11-16T16:13:07.390096+00:00 app[api]: Release v7 created by user benchoufi.mehdi@gmail.com
2017-11-16T16:13:07.390096+00:00 app[api]: Deploy 99038abe by user benchoufi.mehdi@gmail.com
2017-11-16T16:12:50.000000+00:00 app[api]: Build succeeded
2017-11-16T16:13:08.751218+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2017-11-16T16:13:08.761369+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2017-11-16T16:13:08.788899+00:00 app[web.1]: Exiting
2017-11-16T16:13:08.789433+00:00 app[web.1]: /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:395:in `close': stream closed (IOError)
2017-11-16T16:13:08.789487+00:00 app[web.1]:    from /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:398:in `handle_servers'
2017-11-16T16:13:08.789453+00:00 app[web.1]:    from /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:395:in `ensure in handle_servers'
2017-11-16T16:13:08.789489+00:00 app[web.1]:    from /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:327:in `block in run'
2017-11-16T16:13:08.907475+00:00 heroku[web.1]: Process exited with status 1
2017-11-16T16:13:13.745852+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 5997 -e production`
2017-11-16T16:13:22.652430+00:00 heroku[web.1]: State changed from starting to up
2017-11-16T16:13:22.424108+00:00 app[web.1]: => Booting Puma
2017-11-16T16:13:22.424142+00:00 app[web.1]: => Rails 5.0.6 application starting in production on http://0.0.0.0:5997
2017-11-16T16:13:22.424145+00:00 app[web.1]: => Run `rails server -h` for more startup options
2017-11-16T16:13:22.424195+00:00 app[web.1]: Puma starting in single mode...
2017-11-16T16:13:22.424286+00:00 app[web.1]: * Min threads: 5, max threads: 5
2017-11-16T16:13:22.424247+00:00 app[web.1]: * Version 3.10.0 (ruby 2.4.1-p111), codename: Russell's Teapot
2017-11-16T16:13:22.424352+00:00 app[web.1]: * Environment: production
2017-11-16T16:13:22.424528+00:00 app[web.1]: * Listening on tcp://0.0.0.0:5997
2017-11-16T16:13:22.425055+00:00 app[web.1]: Use Ctrl-C to stop
2017-11-16T16:13:57.966340+00:00 app[web.1]: I, [2017-11-16T16:13:57.966187 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936] Started GET "/" for 80.12.27.252 at 2017-11-16 16:13:57 +0000
2017-11-16T16:13:58.001708+00:00 app[web.1]: I, [2017-11-16T16:13:58.001639 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendered pages/index.html.erb within layouts/application (0.9ms)
2017-11-16T16:13:57.996269+00:00 app[web.1]: I, [2017-11-16T16:13:57.996152 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936] Processing by PagesController#index as HTML
2017-11-16T16:13:58.000897+00:00 app[web.1]: I, [2017-11-16T16:13:58.000568 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendering pages/index.html.erb within layouts/application
2017-11-16T16:13:58.296994+00:00 app[web.1]: I, [2017-11-16T16:13:58.296906 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936] Completed 200 OK in 301ms (Views: 299.3ms)
2017-11-16T16:13:58.286219+00:00 app[web.1]: I, [2017-11-16T16:13:58.286073 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendered layouts/_nav.html.erb (0.7ms)
2017-11-16T16:13:58.296500+00:00 app[web.1]: I, [2017-11-16T16:13:58.296376 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendered layouts/_footer.html.erb (9.3ms)
2017-11-16T16:13:58.290239+00:00 heroku[router]: at=info method=GET path="/" host=mysterious-crag-68857.herokuapp.com request_id=e8dd584a-d608-4421-ac81-44cd455ed936 fwd="80.12.27.252" dyno=web.1 connect=0ms service=348ms status=200 bytes=14894 protocol=https
2017-11-16T16:13:58.571091+00:00 heroku[router]: at=info method=GET path="/assets/application-cbd352f84234371962220aac536e7439e570099d31857c088b4e6d82141e9206.css" host=mysterious-crag-68857.herokuapp.com request_id=92a4edc0-7f6f-4317-b7b8-7ea7e202aff4 fwd="80.12.27.252" dyno=web.1 connect=0ms service=4ms status=200 bytes=290 protocol=https
2017-11-16T16:13:58.704480+00:00 heroku[router]: at=info method=GET path="/assets/application-7a19b05aebcc1264ba7bc75e8a9ab79af4669370f312952095c90b8160480841.js" host=mysterious-crag-68857.herokuapp.com request_id=db83d660-cedf-4642-972c-1d2b4e08d156 fwd="80.12.27.252" dyno=web.1 connect=0ms service=3ms status=200 bytes=303 protocol=https
2017-11-16T16:13:58.832979+00:00 heroku[router]: at=info method=GET path="/assets/logo2.png" host=mysterious-crag-68857.herokuapp.com request_id=16ea7daf-d704-43f0-a8ce-91243a15b8f3 fwd="80.12.27.252" dyno=web.1 connect=0ms service=26ms status=200 bytes=15746 protocol=https
2017-11-16T16:13:58.817763+00:00 app[web.1]: I, [2017-11-16T16:13:58.817635 #4]  INFO -- : [16ea7daf-d704-43f0-a8ce-91243a15b8f3] Started GET "/assets/logo2.png" for 80.12.27.252 at 2017-11-16 16:13:58 +0000
2017-11-16T16:13:59.035120+00:00 app[web.1]: I, [2017-11-16T16:13:59.035020 #4]  INFO -- : [7191af72-e7a6-4c9f-b34d-f866349e19fe] Started GET "/assets/single_folio/featured1.jpg" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.038959+00:00 heroku[router]: at=info method=GET path="/assets/single_folio/featured1.jpg" host=mysterious-crag-68857.herokuapp.com request_id=7191af72-e7a6-4c9f-b34d-f866349e19fe fwd="80.12.27.252" dyno=web.1 connect=0ms service=18ms status=200 bytes=230727 protocol=https
2017-11-16T16:13:59.146207+00:00 heroku[router]: at=info method=GET path="/assets/fondation_pierre_fabre.png" host=mysterious-crag-68857.herokuapp.com request_id=f54b3701-44ae-4d9c-b76a-200a5be5f4f7 fwd="80.12.27.252" dyno=web.1 connect=0ms service=18ms status=200 bytes=3889 protocol=https
2017-11-16T16:13:59.137862+00:00 app[web.1]: I, [2017-11-16T16:13:59.137756 #4]  INFO -- : [b5620bf1-cd26-430e-bdc4-4b18d283d602] Started GET "/assets/logo_altran.png" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.152893+00:00 app[web.1]: I, [2017-11-16T16:13:59.152788 #4]  INFO -- : [f54b3701-44ae-4d9c-b76a-200a5be5f4f7] Started GET "/assets/fondation_pierre_fabre.png" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.158096+00:00 app[web.1]: I, [2017-11-16T16:13:59.158011 #4]  INFO -- : [19624a74-80a0-4796-b349-47e1a359291a] Started GET "/assets/home/build.jpg" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.161169+00:00 heroku[router]: at=info method=GET path="/assets/logo_altran.png" host=mysterious-crag-68857.herokuapp.com request_id=b5620bf1-cd26-430e-bdc4-4b18d283d602 fwd="80.12.27.252" dyno=web.1 connect=0ms service=34ms status=200 bytes=8918 protocol=https
2017-11-16T16:13:59.176271+00:00 heroku[router]: at=info method=GET path="/assets/home/build.jpg" host=mysterious-crag-68857.herokuapp.com request_id=19624a74-80a0-4796-b349-47e1a359291a fwd="80.12.27.252" dyno=web.1 connect=0ms service=43ms status=200 bytes=19242 protocol=https
2017-11-16T16:14:00.250138+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=mysterious-crag-68857.herokuapp.com request_id=8f82cf74-f19c-4fd8-af88-aaa76fba7f60 fwd="80.12.27.252" dyno=web.1 connect=0ms service=4ms status=200 bytes=180 protocol=https
2017-11-16T16:38:30.000000+00:00 app[api]: Build started by user benchoufi.mehdi@gmail.com
2017-11-16T16:38:47.990291+00:00 app[api]: Deploy 504623ba by user benchoufi.mehdi@gmail.com
2017-11-16T16:38:47.990291+00:00 app[api]: Release v8 created by user benchoufi.mehdi@gmail.com
2017-11-16T16:38:30.000000+00:00 app[api]: Build succeeded
2017-11-16T16:38:49.057909+00:00 heroku[web.1]: State changed from up to starting
2017-11-16T16:38:49.057351+00:00 heroku[web.1]: Restarting
2017-11-16T16:38:50.018531+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2017-11-16T16:38:50.030701+00:00 app[web.1]: === puma shutdown: 2017-11-16 16:38:50 +0000 ===
2017-11-16T16:38:50.030736+00:00 app[web.1]: - Goodbye!
2017-11-16T16:38:50.030914+00:00 app[web.1]: Exiting
2017-11-16T16:38:50.172254+00:00 heroku[web.1]: Process exited with status 143
2017-11-16T16:38:50.003821+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2017-11-16T16:38:52.617190+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 3626 -e production`
2017-11-16T16:38:56.842223+00:00 app[web.1]: => Booting Puma
2017-11-16T16:38:56.842258+00:00 app[web.1]: => Rails 5.0.6 application starting in production on http://0.0.0.0:3626
2017-11-16T16:38:56.842260+00:00 app[web.1]: => Run `rails server -h` for more startup options
2017-11-16T16:38:56.842261+00:00 app[web.1]: Puma starting in single mode...
2017-11-16T16:38:56.842261+00:00 app[web.1]: * Version 3.10.0 (ruby 2.4.1-p111), codename: Russell's Teapot
2017-11-16T16:38:56.842267+00:00 app[web.1]: * Min threads: 5, max threads: 5
2017-11-16T16:38:56.842268+00:00 app[web.1]: * Environment: production
2017-11-16T16:38:56.842314+00:00 app[web.1]: * Listening on tcp://0.0.0.0:3626
2017-11-16T16:38:56.842706+00:00 app[web.1]: Use Ctrl-C to stop
2017-11-16T16:38:56.991984+00:00 heroku[web.1]: State changed from starting to up
</code>```

besides, here's the content of the application.css.scss

```<code>*= require animate
*= require jquery-ui
*= require owl.carousel
*= require owl.theme
*= require magnific-popup
*= require_self
*= require_tree .
*/
@import "bootstrap";
@import "bootstrap-sprockets";
@import "font-awesome";
</code>```

答:
You need to config Rails to serve static assets in production: config/environments/production.rb

config.assets.compile = true

Try this hope its help !

Title: Issue deploying rails app on heroku

Body:
I am new to rails and I was to work on a code. The website works perfect on my local but when deploying remotely on heroku, the css files seem not found.

I am running the app with ruby 2.4, Rails 5.0 and gemfile

source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

gem 'bootstrap-sass', '~> 3.3', '>= 3.3.7'
gem 'autoprefixer-rails'
gem 'font-awesome-rails', '~> 4.6', '>= 4.6.3.1'
gem 'animate-rails', '~> 1.0', '>= 1.0.10'
gem 'owlcarousel-rails', '~> 1.1', '>= 1.1.3.3'
gem 'wow-rails', '~> 0.0.1'
gem 'magnific-popup-rails', '~> 1.1'
gem 'google-api-client', '~> 0.12.0'
gem 'figaro'
# cron task
gem 'whenever', require: false
# Authentication
gem 'devise'
gem 'cancancan', '~> 1.15'
# serach and autocompletion
gem 'pg_search'
# mailer dev
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.3'
# Use sqlite3 as the database for Active Record
gem 'pg'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Use jquery as the JavaScript library
gem 'jquery-rails'
gem 'jquery-ui-rails', '~> 5.0'
gem 'rails_admin', :git => 'git://github.com/sferik/rails_admin.git'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
#gem 'capistrano3-puma', github: "seuros/capistrano-puma"

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri
end

group :development do
  # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '~> 3.0.5'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  # Use Capistrano for deployment
  gem 'capistrano'
  gem 'capistrano-rails'
  gem 'capistrano-rvm'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

ruby "2.4.1"

Here's the log via the command heroku log --tail

2017-11-16T16:07:52.898937+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 6818 -e production`
2017-11-16T16:07:58.371812+00:00 app[web.1]: => Booting Puma
2017-11-16T16:07:58.371821+00:00 app[web.1]: => Rails 5.0.6 application starting in production on http://0.0.0.0:6818
2017-11-16T16:07:58.371822+00:00 app[web.1]: => Run `rails server -h` for more startup options
2017-11-16T16:07:58.371822+00:00 app[web.1]: Puma starting in single mode...
2017-11-16T16:07:58.371827+00:00 app[web.1]: * Version 3.10.0 (ruby 2.4.1-p111), codename: Russell's Teapot
2017-11-16T16:07:58.371828+00:00 app[web.1]: * Min threads: 5, max threads: 5
2017-11-16T16:07:58.371828+00:00 app[web.1]: * Environment: production
2017-11-16T16:07:58.371978+00:00 app[web.1]: * Listening on tcp://0.0.0.0:6818
2017-11-16T16:07:58.372379+00:00 app[web.1]: Use Ctrl-C to stop
2017-11-16T16:07:58.939021+00:00 heroku[web.1]: State changed from starting to up
2017-11-16T16:07:59.757157+00:00 app[web.1]: I, [2017-11-16T16:07:59.757044 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3] Started GET "/" for 80.12.27.252 at 2017-11-16 16:07:59 +0000
2017-11-16T16:07:59.766621+00:00 app[web.1]: I, [2017-11-16T16:07:59.766547 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendering pages/index.html.erb within layouts/application
2017-11-16T16:07:59.763739+00:00 app[web.1]: I, [2017-11-16T16:07:59.763642 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3] Processing by PagesController#index as HTML
2017-11-16T16:07:59.767481+00:00 app[web.1]: I, [2017-11-16T16:07:59.767416 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendered pages/index.html.erb within layouts/application (0.7ms)
2017-11-16T16:07:59.936841+00:00 app[web.1]: I, [2017-11-16T16:07:59.936713 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendered layouts/_nav.html.erb (0.4ms)
2017-11-16T16:07:59.941558+00:00 app[web.1]: I, [2017-11-16T16:07:59.941458 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3]   Rendered layouts/_footer.html.erb (4.1ms)
2017-11-16T16:07:59.941919+00:00 app[web.1]: I, [2017-11-16T16:07:59.941858 #4]  INFO -- : [b03307de-5170-474a-9f27-50cd05bf07a3] Completed 200 OK in 178ms (Views: 177.2ms)
2017-11-16T16:07:59.942814+00:00 heroku[router]: at=info method=GET path="/" host=mysterious-crag-68857.herokuapp.com request_id=b03307de-5170-474a-9f27-50cd05bf07a3 fwd="80.12.27.252" dyno=web.1 connect=0ms service=190ms status=200 bytes=14894 protocol=https
2017-11-16T16:08:00.224613+00:00 heroku[router]: at=info method=GET path="/assets/application-cbd352f84234371962220aac536e7439e570099d31857c088b4e6d82141e9206.css" host=mysterious-crag-68857.herokuapp.com request_id=d2c6dfd6-4660-4844-9d44-143e3d21b917 fwd="80.12.27.252" dyno=web.1 connect=5ms service=10ms status=200 bytes=290 protocol=https
2017-11-16T16:08:00.469689+00:00 heroku[router]: at=info method=GET path="/assets/fondation_pierre_fabre.png" host=mysterious-crag-68857.herokuapp.com request_id=c7adcbdd-8478-4916-9aff-0a90a52058bc fwd="80.12.27.252" dyno=web.1 connect=0ms service=8ms status=200 bytes=3889 protocol=https
2017-11-16T16:08:00.354457+00:00 heroku[router]: at=info method=GET path="/assets/logo2.png" host=mysterious-crag-68857.herokuapp.com request_id=720bf865-6dc4-401f-aac2-bf8eb96c5e90 fwd="80.12.27.252" dyno=web.1 connect=0ms service=5ms status=200 bytes=15746 protocol=https
2017-11-16T16:08:00.331984+00:00 heroku[router]: at=info method=GET path="/assets/application-7a19b05aebcc1264ba7bc75e8a9ab79af4669370f312952095c90b8160480841.js" host=mysterious-crag-68857.herokuapp.com request_id=c58820a6-ce78-43d8-b9da-f188ab36a9d4 fwd="80.12.27.252" dyno=web.1 connect=0ms service=3ms status=200 bytes=303 protocol=https
2017-11-16T16:08:00.351225+00:00 app[web.1]: I, [2017-11-16T16:08:00.351111 #4]  INFO -- : [720bf865-6dc4-401f-aac2-bf8eb96c5e90] Started GET "/assets/logo2.png" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.464437+00:00 app[web.1]: I, [2017-11-16T16:08:00.464337 #4]  INFO -- : [62f2a2a3-392b-446d-be9b-a32e38f68397] Started GET "/assets/single_folio/featured1.jpg" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.465587+00:00 app[web.1]: I, [2017-11-16T16:08:00.464658 #4]  INFO -- : [c7adcbdd-8478-4916-9aff-0a90a52058bc] Started GET "/assets/fondation_pierre_fabre.png" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.582164+00:00 app[web.1]: I, [2017-11-16T16:08:00.582059 #4]  INFO -- : [2c5ed467-5129-4e52-9794-c22a611efaec] Started GET "/assets/logo_altran.png" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:00.480539+00:00 heroku[router]: at=info method=GET path="/assets/single_folio/featured1.jpg" host=mysterious-crag-68857.herokuapp.com request_id=62f2a2a3-392b-446d-be9b-a32e38f68397 fwd="80.12.27.252" dyno=web.1 connect=1ms service=19ms status=200 bytes=230727 protocol=https
2017-11-16T16:08:00.628238+00:00 heroku[router]: at=info method=GET path="/assets/home/build.jpg" host=mysterious-crag-68857.herokuapp.com request_id=f9d88aa4-d176-4190-8ad7-08f15cffc6fd fwd="80.12.27.252" dyno=web.1 connect=0ms service=7ms status=200 bytes=19242 protocol=https
2017-11-16T16:08:00.584670+00:00 heroku[router]: at=info method=GET path="/assets/logo_altran.png" host=mysterious-crag-68857.herokuapp.com request_id=2c5ed467-5129-4e52-9794-c22a611efaec fwd="80.12.27.252" dyno=web.1 connect=0ms service=4ms status=200 bytes=8918 protocol=https
2017-11-16T16:08:00.623571+00:00 app[web.1]: I, [2017-11-16T16:08:00.623424 #4]  INFO -- : [f9d88aa4-d176-4190-8ad7-08f15cffc6fd] Started GET "/assets/home/build.jpg" for 80.12.27.252 at 2017-11-16 16:08:00 +0000
2017-11-16T16:08:01.911423+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=mysterious-crag-68857.herokuapp.com request_id=69791277-1eb3-4067-a23a-51987305595b fwd="80.12.27.252" dyno=web.1 connect=1ms service=1ms status=200 bytes=180 protocol=https
2017-11-16T16:08:04.306986+00:00 heroku[router]: at=info method=GET path="/assets/application-cbd352f84234371962220aac536e7439e570099d31857c088b4e6d82141e9206.css" host=mysterious-crag-68857.herokuapp.com request_id=9d090e84-2bfe-49d8-afe1-7a5769d84497 fwd="80.12.27.252" dyno=web.1 connect=1ms service=5ms status=304 bytes=48 protocol=https
2017-11-16T16:12:50.000000+00:00 app[api]: Build started by user benchoufi.mehdi@gmail.com
2017-11-16T16:13:08.103929+00:00 heroku[web.1]: Restarting
2017-11-16T16:13:08.116568+00:00 heroku[web.1]: State changed from up to starting
2017-11-16T16:13:07.390096+00:00 app[api]: Release v7 created by user benchoufi.mehdi@gmail.com
2017-11-16T16:13:07.390096+00:00 app[api]: Deploy 99038abe by user benchoufi.mehdi@gmail.com
2017-11-16T16:12:50.000000+00:00 app[api]: Build succeeded
2017-11-16T16:13:08.751218+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2017-11-16T16:13:08.761369+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2017-11-16T16:13:08.788899+00:00 app[web.1]: Exiting
2017-11-16T16:13:08.789433+00:00 app[web.1]: /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:395:in `close': stream closed (IOError)
2017-11-16T16:13:08.789487+00:00 app[web.1]:    from /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:398:in `handle_servers'
2017-11-16T16:13:08.789453+00:00 app[web.1]:    from /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:395:in `ensure in handle_servers'
2017-11-16T16:13:08.789489+00:00 app[web.1]:    from /app/vendor/bundle/ruby/2.4.0/gems/puma-3.10.0/lib/puma/server.rb:327:in `block in run'
2017-11-16T16:13:08.907475+00:00 heroku[web.1]: Process exited with status 1
2017-11-16T16:13:13.745852+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 5997 -e production`
2017-11-16T16:13:22.652430+00:00 heroku[web.1]: State changed from starting to up
2017-11-16T16:13:22.424108+00:00 app[web.1]: => Booting Puma
2017-11-16T16:13:22.424142+00:00 app[web.1]: => Rails 5.0.6 application starting in production on http://0.0.0.0:5997
2017-11-16T16:13:22.424145+00:00 app[web.1]: => Run `rails server -h` for more startup options
2017-11-16T16:13:22.424195+00:00 app[web.1]: Puma starting in single mode...
2017-11-16T16:13:22.424286+00:00 app[web.1]: * Min threads: 5, max threads: 5
2017-11-16T16:13:22.424247+00:00 app[web.1]: * Version 3.10.0 (ruby 2.4.1-p111), codename: Russell's Teapot
2017-11-16T16:13:22.424352+00:00 app[web.1]: * Environment: production
2017-11-16T16:13:22.424528+00:00 app[web.1]: * Listening on tcp://0.0.0.0:5997
2017-11-16T16:13:22.425055+00:00 app[web.1]: Use Ctrl-C to stop
2017-11-16T16:13:57.966340+00:00 app[web.1]: I, [2017-11-16T16:13:57.966187 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936] Started GET "/" for 80.12.27.252 at 2017-11-16 16:13:57 +0000
2017-11-16T16:13:58.001708+00:00 app[web.1]: I, [2017-11-16T16:13:58.001639 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendered pages/index.html.erb within layouts/application (0.9ms)
2017-11-16T16:13:57.996269+00:00 app[web.1]: I, [2017-11-16T16:13:57.996152 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936] Processing by PagesController#index as HTML
2017-11-16T16:13:58.000897+00:00 app[web.1]: I, [2017-11-16T16:13:58.000568 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendering pages/index.html.erb within layouts/application
2017-11-16T16:13:58.296994+00:00 app[web.1]: I, [2017-11-16T16:13:58.296906 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936] Completed 200 OK in 301ms (Views: 299.3ms)
2017-11-16T16:13:58.286219+00:00 app[web.1]: I, [2017-11-16T16:13:58.286073 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendered layouts/_nav.html.erb (0.7ms)
2017-11-16T16:13:58.296500+00:00 app[web.1]: I, [2017-11-16T16:13:58.296376 #4]  INFO -- : [e8dd584a-d608-4421-ac81-44cd455ed936]   Rendered layouts/_footer.html.erb (9.3ms)
2017-11-16T16:13:58.290239+00:00 heroku[router]: at=info method=GET path="/" host=mysterious-crag-68857.herokuapp.com request_id=e8dd584a-d608-4421-ac81-44cd455ed936 fwd="80.12.27.252" dyno=web.1 connect=0ms service=348ms status=200 bytes=14894 protocol=https
2017-11-16T16:13:58.571091+00:00 heroku[router]: at=info method=GET path="/assets/application-cbd352f84234371962220aac536e7439e570099d31857c088b4e6d82141e9206.css" host=mysterious-crag-68857.herokuapp.com request_id=92a4edc0-7f6f-4317-b7b8-7ea7e202aff4 fwd="80.12.27.252" dyno=web.1 connect=0ms service=4ms status=200 bytes=290 protocol=https
2017-11-16T16:13:58.704480+00:00 heroku[router]: at=info method=GET path="/assets/application-7a19b05aebcc1264ba7bc75e8a9ab79af4669370f312952095c90b8160480841.js" host=mysterious-crag-68857.herokuapp.com request_id=db83d660-cedf-4642-972c-1d2b4e08d156 fwd="80.12.27.252" dyno=web.1 connect=0ms service=3ms status=200 bytes=303 protocol=https
2017-11-16T16:13:58.832979+00:00 heroku[router]: at=info method=GET path="/assets/logo2.png" host=mysterious-crag-68857.herokuapp.com request_id=16ea7daf-d704-43f0-a8ce-91243a15b8f3 fwd="80.12.27.252" dyno=web.1 connect=0ms service=26ms status=200 bytes=15746 protocol=https
2017-11-16T16:13:58.817763+00:00 app[web.1]: I, [2017-11-16T16:13:58.817635 #4]  INFO -- : [16ea7daf-d704-43f0-a8ce-91243a15b8f3] Started GET "/assets/logo2.png" for 80.12.27.252 at 2017-11-16 16:13:58 +0000
2017-11-16T16:13:59.035120+00:00 app[web.1]: I, [2017-11-16T16:13:59.035020 #4]  INFO -- : [7191af72-e7a6-4c9f-b34d-f866349e19fe] Started GET "/assets/single_folio/featured1.jpg" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.038959+00:00 heroku[router]: at=info method=GET path="/assets/single_folio/featured1.jpg" host=mysterious-crag-68857.herokuapp.com request_id=7191af72-e7a6-4c9f-b34d-f866349e19fe fwd="80.12.27.252" dyno=web.1 connect=0ms service=18ms status=200 bytes=230727 protocol=https
2017-11-16T16:13:59.146207+00:00 heroku[router]: at=info method=GET path="/assets/fondation_pierre_fabre.png" host=mysterious-crag-68857.herokuapp.com request_id=f54b3701-44ae-4d9c-b76a-200a5be5f4f7 fwd="80.12.27.252" dyno=web.1 connect=0ms service=18ms status=200 bytes=3889 protocol=https
2017-11-16T16:13:59.137862+00:00 app[web.1]: I, [2017-11-16T16:13:59.137756 #4]  INFO -- : [b5620bf1-cd26-430e-bdc4-4b18d283d602] Started GET "/assets/logo_altran.png" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.152893+00:00 app[web.1]: I, [2017-11-16T16:13:59.152788 #4]  INFO -- : [f54b3701-44ae-4d9c-b76a-200a5be5f4f7] Started GET "/assets/fondation_pierre_fabre.png" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.158096+00:00 app[web.1]: I, [2017-11-16T16:13:59.158011 #4]  INFO -- : [19624a74-80a0-4796-b349-47e1a359291a] Started GET "/assets/home/build.jpg" for 80.12.27.252 at 2017-11-16 16:13:59 +0000
2017-11-16T16:13:59.161169+00:00 heroku[router]: at=info method=GET path="/assets/logo_altran.png" host=mysterious-crag-68857.herokuapp.com request_id=b5620bf1-cd26-430e-bdc4-4b18d283d602 fwd="80.12.27.252" dyno=web.1 connect=0ms service=34ms status=200 bytes=8918 protocol=https
2017-11-16T16:13:59.176271+00:00 heroku[router]: at=info method=GET path="/assets/home/build.jpg" host=mysterious-crag-68857.herokuapp.com request_id=19624a74-80a0-4796-b349-47e1a359291a fwd="80.12.27.252" dyno=web.1 connect=0ms service=43ms status=200 bytes=19242 protocol=https
2017-11-16T16:14:00.250138+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=mysterious-crag-68857.herokuapp.com request_id=8f82cf74-f19c-4fd8-af88-aaa76fba7f60 fwd="80.12.27.252" dyno=web.1 connect=0ms service=4ms status=200 bytes=180 protocol=https
2017-11-16T16:38:30.000000+00:00 app[api]: Build started by user benchoufi.mehdi@gmail.com
2017-11-16T16:38:47.990291+00:00 app[api]: Deploy 504623ba by user benchoufi.mehdi@gmail.com
2017-11-16T16:38:47.990291+00:00 app[api]: Release v8 created by user benchoufi.mehdi@gmail.com
2017-11-16T16:38:30.000000+00:00 app[api]: Build succeeded
2017-11-16T16:38:49.057909+00:00 heroku[web.1]: State changed from up to starting
2017-11-16T16:38:49.057351+00:00 heroku[web.1]: Restarting
2017-11-16T16:38:50.018531+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2017-11-16T16:38:50.030701+00:00 app[web.1]: === puma shutdown: 2017-11-16 16:38:50 +0000 ===
2017-11-16T16:38:50.030736+00:00 app[web.1]: - Goodbye!
2017-11-16T16:38:50.030914+00:00 app[web.1]: Exiting
2017-11-16T16:38:50.172254+00:00 heroku[web.1]: Process exited with status 143
2017-11-16T16:38:50.003821+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2017-11-16T16:38:52.617190+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 3626 -e production`
2017-11-16T16:38:56.842223+00:00 app[web.1]: => Booting Puma
2017-11-16T16:38:56.842258+00:00 app[web.1]: => Rails 5.0.6 application starting in production on http://0.0.0.0:3626
2017-11-16T16:38:56.842260+00:00 app[web.1]: => Run `rails server -h` for more startup options
2017-11-16T16:38:56.842261+00:00 app[web.1]: Puma starting in single mode...
2017-11-16T16:38:56.842261+00:00 app[web.1]: * Version 3.10.0 (ruby 2.4.1-p111), codename: Russell's Teapot
2017-11-16T16:38:56.842267+00:00 app[web.1]: * Min threads: 5, max threads: 5
2017-11-16T16:38:56.842268+00:00 app[web.1]: * Environment: production
2017-11-16T16:38:56.842314+00:00 app[web.1]: * Listening on tcp://0.0.0.0:3626
2017-11-16T16:38:56.842706+00:00 app[web.1]: Use Ctrl-C to stop
2017-11-16T16:38:56.991984+00:00 heroku[web.1]: State changed from starting to up

besides, here's the content of the application.css.scss

*= require animate
*= require jquery-ui
*= require owl.carousel
*= require owl.theme
*= require magnific-popup
*= require_self
*= require_tree .
*/
@import "bootstrap";
@import "bootstrap-sprockets";
@import "font-awesome";


来源: stackexchange

问:
Wait until swift for loop with asynchronous network requests finishes executing
I would like a for in loop to send off a bunch of network requests to firebase, then pass the data to a new view controller once the the method finishes executing. Here is my code:

```<code>var datesArray = [String: AnyObject]()

for key in locationsArray {
    let ref = Firebase(url: "http://myfirebase.com/" + "\(key.0)")
    ref.observeSingleEventOfType(.Value, withBlock: { snapshot in

        datesArray["\(key.0)"] = snapshot.value
    })
}
// Segue to new view controller here and pass datesArray once it is complete
</code>```

I have a couple concerns. First, how do I wait until the for loop is finished and all the network requests are complete? I can't modify the observeSingleEventOfType function, it is part of the firebase SDK. Also, will I create some sort of race condition by trying to access the datesArray from different iterations of the for loop (hope that makes sense)? I've been reading about GCD and NSOperation but I'm a bit lost as this is the first app I've built.

Note: Locations array is an array containing the keys I need to access in firebase. Also, it's important that the network requests are fired off asynchronously. I just want to wait until ALL the asynchronous requests complete before I pass the datesArray to the next view controller.

答:
Details

Xcode 10.2.1 (10E1001), Swift 5

Solution

```<code>import Foundation

class SimultaneousOperationsQueue {
    typealias CompleteClosure = ()->()

    private let dispatchQueue: DispatchQueue
    private lazy var tasksCompletionQueue = DispatchQueue.main
    private let semaphore: DispatchSemaphore
    var whenCompleteAll: (()->())?
    private lazy var numberOfPendingActionsSemaphore = DispatchSemaphore(value: 1)
    private lazy var _numberOfPendingActions = 0

    var numberOfPendingTasks: Int {
        get {
            numberOfPendingActionsSemaphore.wait()
            defer { numberOfPendingActionsSemaphore.signal() }
            return _numberOfPendingActions
        }
        set(value) {
            numberOfPendingActionsSemaphore.wait()
            defer { numberOfPendingActionsSemaphore.signal() }
            _numberOfPendingActions = value
        }
    }

    init(numberOfSimultaneousActions: Int, dispatchQueueLabel: String) {
        dispatchQueue = DispatchQueue(label: dispatchQueueLabel)
        semaphore = DispatchSemaphore(value: numberOfSimultaneousActions)
    }

    func run(closure: ((@escaping CompleteClosure) -> Void)?) {
        numberOfPendingTasks += 1
        dispatchQueue.async { [weak self] in
            guard   let self = self,
                    let closure = closure else { return }
            self.semaphore.wait()
            closure {
                defer { self.semaphore.signal() }
                self.numberOfPendingTasks -= 1
                if self.numberOfPendingTasks == 0, let closure = self.whenCompleteAll {
                    self.tasksCompletionQueue.async { closure() }
                }
            }
        }
    }

    func run(closure: (() -> Void)?) {
        numberOfPendingTasks += 1
        dispatchQueue.async { [weak self] in
            guard   let self = self,
                    let closure = closure else { return }
            self.semaphore.wait(); defer { self.semaphore.signal() }
            closure()
            self.numberOfPendingTasks -= 1
            if self.numberOfPendingTasks == 0, let closure = self.whenCompleteAll {
                self.tasksCompletionQueue.async { closure() }
            }
        }
    }
}
</code>```

Usage

```<code>let queue = SimultaneousOperationsQueue(numberOfSimultaneousActions: 1, dispatchQueueLabel: "AnyString")
queue.whenCompleteAll = { print("All Done") }

 // add task with sync/async code
queue.run { completeClosure in
    // your code here...

    // Make signal that this closure finished
    completeClosure()
}

 // add task only with sync code
queue.run {
    // your code here...
}
</code>```

Full sample

```<code>import UIKit

class ViewController: UIViewController {

    private lazy var queue = { SimultaneousOperationsQueue(numberOfSimultaneousActions: 1,
                                                           dispatchQueueLabel: "AnyString") }()
    private weak var button: UIButton!
    private weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        let button = UIButton(frame: CGRect(x: 50, y: 80, width: 100, height: 100))
        button.setTitleColor(.blue, for: .normal)
        button.titleLabel?.numberOfLines = 0
        view.addSubview(button)
        self.button = button

        let label = UILabel(frame: CGRect(x: 180, y: 50, width: 100, height: 100))
        label.text = ""
        label.numberOfLines = 0
        label.textAlignment = .natural
        view.addSubview(label)
        self.label = label

        queue.whenCompleteAll = { [weak self] in self?.label.text = "All tasks completed" }

        //sample1()
        sample2()
    }

    func sample1() {
        button.setTitle("Run 2 task", for: .normal)
        button.addTarget(self, action: #selector(sample1Action), for: .touchUpInside)
    }

    func sample2() {
        button.setTitle("Run 10 tasks", for: .normal)
        button.addTarget(self, action: #selector(sample2Action), for: .touchUpInside)
    }

    private func add2Tasks() {
        queue.run { completeTask in
            DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + .seconds(1)) {
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    self.label.text = "pending tasks \(self.queue.numberOfPendingTasks)"
                }
                completeTask()
            }
        }
        queue.run {
            sleep(1)
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.label.text = "pending tasks \(self.queue.numberOfPendingTasks)"
            }
        }
    }

    @objc func sample1Action() {
        label.text = "pending tasks \(queue.numberOfPendingTasks)"
        add2Tasks()
    }

    @objc func sample2Action() {
        label.text = "pending tasks \(queue.numberOfPendingTasks)"
        for _ in 0..<5 { add2Tasks() }
    }
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I would like a for in loop to send off a bunch of network requests to firebase, then pass the data to a new view controller once the the method finishes executing. Here is my code:

var datesArray = [String: AnyObject]()

for key in locationsArray {
    let ref = Firebase(url: "http://myfirebase.com/" + "\(key.0)")
    ref.observeSingleEventOfType(.Value, withBlock: { snapshot in

        datesArray["\(key.0)"] = snapshot.value
    })
}
// Segue to new view controller here and pass datesArray once it is complete

I have a couple concerns. First, how do I wait until the for loop is finished and all the network requests are complete? I can't modify the observeSingleEventOfType function, it is part of the firebase SDK. Also, will I create some sort of race condition by trying to access the datesArray from different iterations of the for loop (hope that makes sense)? I've been reading about GCD and NSOperation but I'm a bit lost as this is the first app I've built.

Note: Locations array is an array containing the keys I need to access in firebase. Also, it's important that the network requests are fired off asynchronously. I just want to wait until ALL the asynchronous requests complete before I pass the datesArray to the next view controller.

Body:
Details

Xcode 10.2.1 (10E1001), Swift 5

Solution

import Foundation

class SimultaneousOperationsQueue {
    typealias CompleteClosure = ()->()

    private let dispatchQueue: DispatchQueue
    private lazy var tasksCompletionQueue = DispatchQueue.main
    private let semaphore: DispatchSemaphore
    var whenCompleteAll: (()->())?
    private lazy var numberOfPendingActionsSemaphore = DispatchSemaphore(value: 1)
    private lazy var _numberOfPendingActions = 0

    var numberOfPendingTasks: Int {
        get {
            numberOfPendingActionsSemaphore.wait()
            defer { numberOfPendingActionsSemaphore.signal() }
            return _numberOfPendingActions
        }
        set(value) {
            numberOfPendingActionsSemaphore.wait()
            defer { numberOfPendingActionsSemaphore.signal() }
            _numberOfPendingActions = value
        }
    }

    init(numberOfSimultaneousActions: Int, dispatchQueueLabel: String) {
        dispatchQueue = DispatchQueue(label: dispatchQueueLabel)
        semaphore = DispatchSemaphore(value: numberOfSimultaneousActions)
    }

    func run(closure: ((@escaping CompleteClosure) -> Void)?) {
        numberOfPendingTasks += 1
        dispatchQueue.async { [weak self] in
            guard   let self = self,
                    let closure = closure else { return }
            self.semaphore.wait()
            closure {
                defer { self.semaphore.signal() }
                self.numberOfPendingTasks -= 1
                if self.numberOfPendingTasks == 0, let closure = self.whenCompleteAll {
                    self.tasksCompletionQueue.async { closure() }
                }
            }
        }
    }

    func run(closure: (() -> Void)?) {
        numberOfPendingTasks += 1
        dispatchQueue.async { [weak self] in
            guard   let self = self,
                    let closure = closure else { return }
            self.semaphore.wait(); defer { self.semaphore.signal() }
            closure()
            self.numberOfPendingTasks -= 1
            if self.numberOfPendingTasks == 0, let closure = self.whenCompleteAll {
                self.tasksCompletionQueue.async { closure() }
            }
        }
    }
}

Usage

let queue = SimultaneousOperationsQueue(numberOfSimultaneousActions: 1, dispatchQueueLabel: "AnyString")
queue.whenCompleteAll = { print("All Done") }

 // add task with sync/async code
queue.run { completeClosure in
    // your code here...

    // Make signal that this closure finished
    completeClosure()
}

 // add task only with sync code
queue.run {
    // your code here...
}

Full sample

import UIKit

class ViewController: UIViewController {

    private lazy var queue = { SimultaneousOperationsQueue(numberOfSimultaneousActions: 1,
                                                           dispatchQueueLabel: "AnyString") }()
    private weak var button: UIButton!
    private weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        let button = UIButton(frame: CGRect(x: 50, y: 80, width: 100, height: 100))
        button.setTitleColor(.blue, for: .normal)
        button.titleLabel?.numberOfLines = 0
        view.addSubview(button)
        self.button = button

        let label = UILabel(frame: CGRect(x: 180, y: 50, width: 100, height: 100))
        label.text = ""
        label.numberOfLines = 0
        label.textAlignment = .natural
        view.addSubview(label)
        self.label = label

        queue.whenCompleteAll = { [weak self] in self?.label.text = "All tasks completed" }

        //sample1()
        sample2()
    }

    func sample1() {
        button.setTitle("Run 2 task", for: .normal)
        button.addTarget(self, action: #selector(sample1Action), for: .touchUpInside)
    }

    func sample2() {
        button.setTitle("Run 10 tasks", for: .normal)
        button.addTarget(self, action: #selector(sample2Action), for: .touchUpInside)
    }

    private func add2Tasks() {
        queue.run { completeTask in
            DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + .seconds(1)) {
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else { return }
                    self.label.text = "pending tasks \(self.queue.numberOfPendingTasks)"
                }
                completeTask()
            }
        }
        queue.run {
            sleep(1)
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.label.text = "pending tasks \(self.queue.numberOfPendingTasks)"
            }
        }
    }

    @objc func sample1Action() {
        label.text = "pending tasks \(queue.numberOfPendingTasks)"
        add2Tasks()
    }

    @objc func sample2Action() {
        label.text = "pending tasks \(queue.numberOfPendingTasks)"
        for _ in 0..<5 { add2Tasks() }
    }
}


问:
How to read values from property file in a JavaBean (domain class)?
I have a domain class and I want to read values from property file (autowiring messageSource wouldn't work here) so any ideas ?
I am using spring,hibernate
and here's a sample:</p>

```<code>package com.myapp.domain;

import java.io.Serializable;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name = "domain")
public class MyDomain implements Serializable {

    private long entityId;
    private String domain="some_hardcoded_value" // need to read it from a property file;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    @Basic(fetch = FetchType.EAGER)
    public long getEntityId() {
        return entityId;
    }

    public void setEntityId(long entityId) {
        this.entityId = entityId;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    @Column(name = "domain")
    public String getDomain() {
        return domain;
    }

}
</code>```

答:
Beside everything, you can always do,

```<code>Thread.currentThread.getContextClassLoader().getResourceAsStream("some.properties")
</code>```

But I am still curious what you want to read in your Entity, from a property file.

ContentLicense: CC BY-SA 3.0

Body:
I have a domain class and I want to read values from property file (autowiring messageSource wouldn't work here) so any ideas ?
I am using spring,hibernate
and here's a sample:

package com.myapp.domain;

import java.io.Serializable;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name = "domain")
public class MyDomain implements Serializable {

    private long entityId;
    private String domain="some_hardcoded_value" // need to read it from a property file;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    @Basic(fetch = FetchType.EAGER)
    public long getEntityId() {
        return entityId;
    }

    public void setEntityId(long entityId) {
        this.entityId = entityId;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    @Column(name = "domain")
    public String getDomain() {
        return domain;
    }

}

Body:
Beside everything, you can always do,

Thread.currentThread.getContextClassLoader().getResourceAsStream("some.properties")

But I am still curious what you want to read in your Entity, from a property file.

ContentLicense: CC BY-SA 2.5


问:
NullPointerException when I use sum function in hibernate 5
I'm using the following code:

```<code>CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<?> criteria = builder.createQuery();
Root<?> root = criteria.from(TblAgahi.class);
criteria.multiselect(builder.function("SUM", Object.class, root.get("id")));
List<?> resultList = entityManager.createQuery(criteria).getResultList();
</code>```

When i execute this code on hibernate 4.1.8.final it work fine but when i update my hibernate to 5.2.1.final I get NullPointerException.

```<code>the Exception is:
    java.lang.NullPointerException: null
    at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$SumFunction.determineJdbcTypeCode(StandardAnsiSqlAggregationFunctions.java:200)
    at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$SumFunction.getReturnType(StandardAnsiSqlAggregationFunctions.java:158)
    at org.hibernate.hql.internal.ast.tree.IdentNode.getDataType(IdentNode.java:327)
    at org.hibernate.hql.internal.ast.tree.MethodNode.getFirstArgumentType(MethodNode.java:59)
    at org.hibernate.hql.internal.ast.SqlGenerator.endFunctionTemplate(SqlGenerator.java:211)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.methodCall(SqlGeneratorBase.java:2538)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectExpr(SqlGeneratorBase.java:2102)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectColumn(SqlGeneratorBase.java:1914)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectClause(SqlGeneratorBase.java:544)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectStatement(SqlGeneratorBase.java:186)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.statement(SqlGeneratorBase.java:135)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.generate(QueryTranslatorImpl.java:244)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:210)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:152)
    at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:521)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:623)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3250)
    at org.hibernate.query.criteria.internal.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:318)
    at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3543)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:203)
    at com.advertisement.database.DbHelper.test(DbHelper.java:432)
    at com.advertisement.database.DbHelper.find(DbHelper.java:278)
    at com.advertisement.database.DbEntityRepository.find(DbEntityRepository.java:148)
    at com.advertisement.controller.Test.test(Test.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:247)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:149)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:813)
    at javax.faces.component.UICommand.broadcast(UICommand.java:300)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:78)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at com.advertisement.lifecycle.OverrideEncodingFilter.doFilter(OverrideEncodingFilter.java:22)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
</code>```

I know i can do above code by builder.sum(...) function but i want to do it by builder.function(...) method.

答: I have just fixed HHH-9931 and it will be released in Hibernate ORM 5.2.13.</p>

Body:
I'm using the following code:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<?> criteria = builder.createQuery();
Root<?> root = criteria.from(TblAgahi.class);
criteria.multiselect(builder.function("SUM", Object.class, root.get("id")));
List<?> resultList = entityManager.createQuery(criteria).getResultList();

When i execute this code on hibernate 4.1.8.final it work fine but when i update my hibernate to 5.2.1.final I get NullPointerException.

the Exception is:
    java.lang.NullPointerException: null
    at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$SumFunction.determineJdbcTypeCode(StandardAnsiSqlAggregationFunctions.java:200)
    at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$SumFunction.getReturnType(StandardAnsiSqlAggregationFunctions.java:158)
    at org.hibernate.hql.internal.ast.tree.IdentNode.getDataType(IdentNode.java:327)
    at org.hibernate.hql.internal.ast.tree.MethodNode.getFirstArgumentType(MethodNode.java:59)
    at org.hibernate.hql.internal.ast.SqlGenerator.endFunctionTemplate(SqlGenerator.java:211)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.methodCall(SqlGeneratorBase.java:2538)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectExpr(SqlGeneratorBase.java:2102)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectColumn(SqlGeneratorBase.java:1914)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectClause(SqlGeneratorBase.java:544)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.selectStatement(SqlGeneratorBase.java:186)
    at org.hibernate.hql.internal.antlr.SqlGeneratorBase.statement(SqlGeneratorBase.java:135)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.generate(QueryTranslatorImpl.java:244)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:210)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:152)
    at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:521)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:623)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3250)
    at org.hibernate.query.criteria.internal.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:318)
    at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3543)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:203)
    at com.advertisement.database.DbHelper.test(DbHelper.java:432)
    at com.advertisement.database.DbHelper.find(DbHelper.java:278)
    at com.advertisement.database.DbEntityRepository.find(DbEntityRepository.java:148)
    at com.advertisement.controller.Test.test(Test.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:247)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:149)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:813)
    at javax.faces.component.UICommand.broadcast(UICommand.java:300)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:78)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at com.advertisement.lifecycle.OverrideEncodingFilter.doFilter(OverrideEncodingFilter.java:22)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

I know i can do above code by builder.sum(...) function but i want to do it by builder.function(...) method.


问:
switch branches without checkout in GIT
Here are the steps that I have followed:

Created a repository

added a file to the master branch.

created a branch called test_branch.

added close to 30k files in the test_branch & committed.

now when I try to switch to master branch.
It says "checking out files:  83% (24967/30002)", and now I have all the files which I have committed in test_branch in my master branch as well.

Why I am getting this error, and how to overcome it ?

答:
created a branch called test_branch

How did you make it? Have you checked if you have checked it out? There are two commands to do it - git branch will NOT checkout it and git checkout -b will.

Title: switch branches without checkout in GIT


问:
Is there a way to serialize a sympy ufuncify-ied function?
Is there a way to serialize or save a function that has been binarized using the ufuncify tool from SymPy's autowrap module?

There is a solution here using dill: How to serialize sympy lambdified function?, but this only works for lambdified functions.

Here's a minimal working example to illustrate:

```<code>>>> import pickle
>>> import dill
>>> import numpy
>>> from sympy import *
>>> from sympy.utilities.autowrap import ufuncify

>>> x, y, z = symbols('x y z')
>>> fx = ufuncify([x], sin(x))

>>> dill.settings['recurse'] = True
>>> dill.detect.errors(fx)
pickle.PicklingError("Can't pickle <ufunc 'wrapper_module_0'>: it's not found as __main__.wrapper_module_0")
</code>```

Motivation: I have a few 50-million character-long SymPy expressions that I'd like to speed up; ufuncify works wonderfully (three-orders-of-magnitude improvement over lambidfy alone), but it takes 3 hr to ufuncify each expression. I would like to be able to take advantage of the ufuncify-ied expressions from time to time (without waiting a day to re-process them). Update: to illustrate, computer going to sleep killed my python kernel, and now I will need to wait ~10 hr to recover the binarized functions

答:
Got it. This is actually simpler than using dill/pickle, as the autowrap module produces and compiles C code (by default) that can be imported as a C-extension module [1] [2].

One way to save the generated code is to simply specify the temp directory for autowrap[3], e.g.:

Python environment 1:

```<code>import numpy
from sympy import *
from sympy.utilities.autowrap import ufuncify

x, y, z = symbols('x y z')
fx = ufuncify([x], sin(x), tempdir='tmp')
</code>```

Python environment 2 (same root directory):

```<code>import sys
sys.path.append('tmp')
import wrapper_module_0

wrapper_module_0.wrapped_8859643136(1)
</code>```

There's probably a better approach (e.g., is there an easy way to name the module and its embedded function?), but this will work for now.

[1] http://www.scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html

[2] https://docs.python.org/2/extending/extending.html

[3] http://docs.sympy.org/latest/modules/utilities/autowrap.html

Body:
Is there a way to serialize or save a function that has been binarized using the ufuncify tool from SymPy's autowrap module?

There is a solution here using dill: How to serialize sympy lambdified function?, but this only works for lambdified functions.

Here's a minimal working example to illustrate:

>>> import pickle
>>> import dill
>>> import numpy
>>> from sympy import *
>>> from sympy.utilities.autowrap import ufuncify

>>> x, y, z = symbols('x y z')
>>> fx = ufuncify([x], sin(x))

>>> dill.settings['recurse'] = True
>>> dill.detect.errors(fx)
pickle.PicklingError("Can't pickle <ufunc 'wrapper_module_0'>: it's not found as __main__.wrapper_module_0")

Motivation: I have a few 50-million character-long SymPy expressions that I'd like to speed up; ufuncify works wonderfully (three-orders-of-magnitude improvement over lambidfy alone), but it takes 3 hr to ufuncify each expression. I would like to be able to take advantage of the ufuncify-ied expressions from time to time (without waiting a day to re-process them). Update: to illustrate, computer going to sleep killed my python kernel, and now I will need to wait ~10 hr to recover the binarized functions

Body:
Got it. This is actually simpler than using dill/pickle, as the autowrap module produces and compiles C code (by default) that can be imported as a C-extension module [1] [2].

One way to save the generated code is to simply specify the temp directory for autowrap[3], e.g.:

Python environment 1:

import numpy
from sympy import *
from sympy.utilities.autowrap import ufuncify

x, y, z = symbols('x y z')
fx = ufuncify([x], sin(x), tempdir='tmp')

Python environment 2 (same root directory):

import sys
sys.path.append('tmp')
import wrapper_module_0

wrapper_module_0.wrapped_8859643136(1)

There's probably a better approach (e.g., is there an easy way to name the module and its embedded function?), but this will work for now.

[1] http://www.scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html

[2] https://docs.python.org/2/extending/extending.html

[3] http://docs.sympy.org/latest/modules/utilities/autowrap.html


问:
Azure AD B2C User Import: Can't Associate Email w/ Username
Hi hopefully someone can help.

I'm importing users into Azure B2C using the Azure AD Graph and have to use the username sign in approach.  We can import the users but we cannot set the mail field because we get an error:

read-only

When testing the self-service reset password functionality, we get:

AADB2C90161:+A+self-asserted+send+response+has+failed+with+reason+'Internal+Server+Error'

I believe this is because when resetting the password you have to supply an email address that you validate with a code.

How do we associate the email with the account when we cannot import the email because the mail field is read-only?  Has anyone else had this issue?  Any workarounds?

答:
One workaround is to use the Azure Portal and manually set it.  This will allow the Password Reset Policy to work.  This is obviously won't scale very well.

B2C Tenant -> Users and Groups -> All Users -> Open the User -> Set the authenticated email address


问:
Table just for grouping
Is it a common case to have a table with a single column for the purpose of grouping rows in another table?

I'm inserting data in batches and I want to have an autoincrement key for each batch to be able to group data based on generated id.

Concretely I want to get from this

```<code>A
id, x, y, b_id
id PRIMARY KEY
b_id FOREIGN KEY REFERENCES B.id

B
id, timestamp
id PRIMARY KEY

SELECT count(*) as number, B.timestamp FROM A inner join B on A.b_id=B.id
                     where A.x='value' and A.y='value'
                     group by B.id;
</code>```

to

```<code>A
id, x, y, timestamp, b_id
id PRIMARY KEY
b_id FOREIGN KEY REFERENCES B.id

B
id
id PRIMARY KEY

SELECT count(*) as number, A.timestamp FROM A
                         where A.x='value' and A.y='value'
                         group by A.b_id, A.timestamp;
</code>```

So basically move timestamp to B (denormalize) and use foreign key only for grouping. I want to avoid having join only for the timestamp placed in B. Tables are quite big (60M of rows) and join is very slow. If I still filter on A and have foreign key only for grouping then that would speed up things a lot.

Concretely, I'm using MySQL.

答: Denormalization can be acceptable for performance reasons. Just make sure that the performance improvement outweighs the cost of that denormalization. There will be costs not only in additional space requirements (which can cause their own performance issues), but also the cost of potential data errors. For example, when two rows end up in table "A" that have the same b_id, but different timestamp values.

Title: Table just for grouping

Body:
Is it a common case to have a table with a single column for the purpose of grouping rows in another table?

I'm inserting data in batches and I want to have an autoincrement key for each batch to be able to group data based on generated id.

Concretely I want to get from this

A
id, x, y, b_id
id PRIMARY KEY
b_id FOREIGN KEY REFERENCES B.id

B
id, timestamp
id PRIMARY KEY

SELECT count(*) as number, B.timestamp FROM A inner join B on A.b_id=B.id
                     where A.x='value' and A.y='value'
                     group by B.id;

to

A
id, x, y, timestamp, b_id
id PRIMARY KEY
b_id FOREIGN KEY REFERENCES B.id

B
id
id PRIMARY KEY

SELECT count(*) as number, A.timestamp FROM A
                         where A.x='value' and A.y='value'
                         group by A.b_id, A.timestamp;

So basically move timestamp to B (denormalize) and use foreign key only for grouping. I want to avoid having join only for the timestamp placed in B. Tables are quite big (60M of rows) and join is very slow. If I still filter on A and have foreign key only for grouping then that would speed up things a lot.

Concretely, I'm using MySQL.


问:
Error in implementing BFS to find the shortest transformation from one word to another(Word Ladder Challenge)
I am trying to implement the word ladder problem where I have to convert one word to another in shortest path possible.Obviously we can use the breadth first search (BFS) to solve it but before that we have to first draw the graph.I have implemented the concept of buckets where certain words fall under a bucket if they match the bucket type.But my graph is not implementing correctly.

The given word list is ["CAT", "BAT", "COT", "COG", "COW", "RAT", "BUT", "CUT", "DOG", "WED"]

So for each word I can create a bucket.For example for the word 'CAT', I can have three buckets _AT, C_T, CA_. Similarly I can create buckets for the rest of the words and which ever words match the bucket type will fall under those buckets.

My code for expressing the problem in graph works fine and I get a graph like this (theoritical)

Now I need to find the shortest no of operations to transform 'CAT' to 'DOG'.So I use a modified method of BFS to achieve it.It works fine when I make a sample graph of my own.For example

```<code>graph = {'COG': ['DOG', 'COW', 'COT'], 'CAT': ['COT', 'BAT', 'CAT', 'RAT'], 'BUT': ['CUT', 'BAT'], 'DOG': ['COG']}
</code>```

The code works fine and I get the correct result.But if I have a huge list of words say 1500, it's not feasible to type and create a dictionary that long.So I made a function which takes those words from the list, implements the technique I dicussed above and creates the graph for me which works just fine until here.But when I try to get the shortest distance between two words, I get the following error

```<code>for neighbour in neighbours:
TypeError: 'Vertex' object is not iterable
</code>```

Here is my code below

```<code>class Vertex:
    def __init__(self,key):
        self.id = key
        self.connectedTo = {}

    # add neighbouring vertices to the current vertex along with the edge weight
    def addNeighbour(self,nbr,weight=0):
        self.connectedTo[nbr] = weight

    #string representation of the object
    def __str__(self):
        return str(self.id) + " is connected to " + str([x.id for x in self.connectedTo])

    def getConnections(self):
        return self.connectedTo.keys()

    def getId(self):
        return self.id

    def getWeight(self,nbr):
        return self.connectedTo[nbr]

class Graph:
    def __init__(self):
        self.vertList = {}
        self.numVertices = 0

    def addVertex(self,key):
        self.numVertices += 1
        newVertex = Vertex(key)
        self.vertList[key] = newVertex
        return newVertex

    def getVertex(self,n):
        if n in self.vertList:
            return self.vertList[n]
        else:
            return None

    def addEdge(self,f,t,cost=0):
        if f not in self.vertList:
            nv = self.addVertex(f)

        if t not in self.vertList:
            nv = self.addVertex(t)

        self.vertList[f].addNeighbour(self.vertList[t],cost)

    def getVertices(self):
        return self.vertList.keys()

    def __iter__(self):
        return iter(self.vertList.values())

# I have only included few words in the list to focus on the implementation
wordList = ["CAT", "BAT", "COT", "COG", "COW", "RAT", "BUT", "CUT", "DOG", "WED"]

def buildGraph(wordList):
    d = {} #in this dictionary the buckets will be the keys and the words will be their values
    g = Graph()
    for i in wordList:
        for j in range(len(i)):
            bucket = i[:j] + "_" + i[j+1:]
            if bucket in d:
                #we are storing the words that fall under the same bucket in a list
                d[bucket].append(i)
            else:
                d[bucket] = [i]

    # create vertices for the words under the buckets and join them
    #print("Dictionary",d)
    for bucket in d.keys():
        for word1 in d[bucket]:
            for word2 in d[bucket]:
                #we ensure same words are not treated as two different vertices
                if word1 != word2:
                    g.addEdge(word1,word2)
    return g

def bfs_shortest_path(graph, start, goal):
    explored = []
    queue = [[start]]
    if start == goal:
        return "The starting node and the destination node is same"
    while queue:
        path = queue.pop(0)
        node = path[-1]
        if node not in explored:
            neighbours = graph[node] # it shows the error here
            for neighbour in neighbours:
                new_path = list(path)
                new_path.append(neighbour)
                queue.append(new_path)
                if neighbour == goal:
                    return new_path

            explored.append(node)

    return "No connecting path between the two nodes"

# get the graph object
gobj = buildGraph(wordList)
# just to check if I am able to fetch the data properly as mentioned above where I get the error (neighbours = graph[node])
print(gobj["CAT"]) # ['COT', 'BAT', 'CUT', 'RAT']
print(bfs_shortest_path(gobj, "CAT", "DOG"))
</code>```

To check neighbouring vertices of each vertex, we can do

```<code>for v in gobj:
    print(v)
</code>```

The output is obtained as below which correctly depicts the graph above.

```<code>CAT is connected to ['COT', 'BAT', 'CUT', 'RAT']
RAT is connected to ['BAT', 'CAT']
COT is connected to ['CUT', 'CAT', 'COG', 'COW']
CUT is connected to ['COT', 'BUT', 'CAT']
COG is connected to ['COT', 'DOG', 'COW']
DOG is connected to ['COG']
BUT is connected to ['BAT', 'CUT']
BAT is connected to ['BUT', 'CAT', 'RAT']
COW is connected to ['COT', 'COG']
CAT is connected to ['COT', 'BAT', 'CUT', 'RAT']
</code>```

What could be going wrong then?

答:
Ok so I figured out the issue.The problem was in this line of code

```<code>neighbours = graph[node]
</code>```

Basically it is trying the fetch the neigbours for the particular node.So it needs to access the vertList dictionary declared as an attribute for the Graph class.So for an object to access the dictonary value, one has to implement a __getitem__ special method.So I declare this under the Graph class as follows

```<code># returns the value for the key which will be an object
def __getitem__(self, key):
    return self.vertList[key]
</code>```

Now graph[node] will be able to fetch the object representation of the node since the value of vertList dictionary is a vertex object (vertList stores vertex name as key and vertex object as value) .So I have to explicitly tell it to fetch the object's neighbours and not the object itself.So I can call the getConnections() method under the Vertex class which further calls the connectedTo attribute to get the neighbour objects for the particular vertex object. (connectedTo dictionary has the vertex object as the key and edge weight as the value.)

So now those neighbour objects will have their own ids which I can access and use it for the BFS operation.The below line is the modified code (under the bfs_shortest_path method) which does the above work.

```<code>if node not in explored:
    neighbours = [x.id for x in graph[node].getConnections()]
</code>```

Now I get the list of the neigbours for the particular node and use it.The rest of the code stays the same.

Body:
I am trying to implement the word ladder problem where I have to convert one word to another in shortest path possible.Obviously we can use the breadth first search (BFS) to solve it but before that we have to first draw the graph.I have implemented the concept of buckets where certain words fall under a bucket if they match the bucket type.But my graph is not implementing correctly.

The given word list is ["CAT", "BAT", "COT", "COG", "COW", "RAT", "BUT", "CUT", "DOG", "WED"]

So for each word I can create a bucket.For example for the word 'CAT', I can have three buckets _AT, C_T, CA_. Similarly I can create buckets for the rest of the words and which ever words match the bucket type will fall under those buckets.

My code for expressing the problem in graph works fine and I get a graph like this (theoritical)

Now I need to find the shortest no of operations to transform 'CAT' to 'DOG'.So I use a modified method of BFS to achieve it.It works fine when I make a sample graph of my own.For example

graph = {'COG': ['DOG', 'COW', 'COT'], 'CAT': ['COT', 'BAT', 'CAT', 'RAT'], 'BUT': ['CUT', 'BAT'], 'DOG': ['COG']}

The code works fine and I get the correct result.But if I have a huge list of words say 1500, it's not feasible to type and create a dictionary that long.So I made a function which takes those words from the list, implements the technique I dicussed above and creates the graph for me which works just fine until here.But when I try to get the shortest distance between two words, I get the following error

for neighbour in neighbours:
TypeError: 'Vertex' object is not iterable

Here is my code below

class Vertex:
    def __init__(self,key):
        self.id = key
        self.connectedTo = {}

    # add neighbouring vertices to the current vertex along with the edge weight
    def addNeighbour(self,nbr,weight=0):
        self.connectedTo[nbr] = weight

    #string representation of the object
    def __str__(self):
        return str(self.id) + " is connected to " + str([x.id for x in self.connectedTo])

    def getConnections(self):
        return self.connectedTo.keys()

    def getId(self):
        return self.id

    def getWeight(self,nbr):
        return self.connectedTo[nbr]

class Graph:
    def __init__(self):
        self.vertList = {}
        self.numVertices = 0

    def addVertex(self,key):
        self.numVertices += 1
        newVertex = Vertex(key)
        self.vertList[key] = newVertex
        return newVertex

    def getVertex(self,n):
        if n in self.vertList:
            return self.vertList[n]
        else:
            return None

    def addEdge(self,f,t,cost=0):
        if f not in self.vertList:
            nv = self.addVertex(f)

        if t not in self.vertList:
            nv = self.addVertex(t)

        self.vertList[f].addNeighbour(self.vertList[t],cost)

    def getVertices(self):
        return self.vertList.keys()

    def __iter__(self):
        return iter(self.vertList.values())

# I have only included few words in the list to focus on the implementation
wordList = ["CAT", "BAT", "COT", "COG", "COW", "RAT", "BUT", "CUT", "DOG", "WED"]

def buildGraph(wordList):
    d = {} #in this dictionary the buckets will be the keys and the words will be their values
    g = Graph()
    for i in wordList:
        for j in range(len(i)):
            bucket = i[:j] + "_" + i[j+1:]
            if bucket in d:
                #we are storing the words that fall under the same bucket in a list
                d[bucket].append(i)
            else:
                d[bucket] = [i]

    # create vertices for the words under the buckets and join them
    #print("Dictionary",d)
    for bucket in d.keys():
        for word1 in d[bucket]:
            for word2 in d[bucket]:
                #we ensure same words are not treated as two different vertices
                if word1 != word2:
                    g.addEdge(word1,word2)
    return g

def bfs_shortest_path(graph, start, goal):
    explored = []
    queue = [[start]]
    if start == goal:
        return "The starting node and the destination node is same"
    while queue:
        path = queue.pop(0)
        node = path[-1]
        if node not in explored:
            neighbours = graph[node] # it shows the error here
            for neighbour in neighbours:
                new_path = list(path)
                new_path.append(neighbour)
                queue.append(new_path)
                if neighbour == goal:
                    return new_path

            explored.append(node)

    return "No connecting path between the two nodes"

# get the graph object
gobj = buildGraph(wordList)
# just to check if I am able to fetch the data properly as mentioned above where I get the error (neighbours = graph[node])
print(gobj["CAT"]) # ['COT', 'BAT', 'CUT', 'RAT']
print(bfs_shortest_path(gobj, "CAT", "DOG"))

To check neighbouring vertices of each vertex, we can do

for v in gobj:
    print(v)

The output is obtained as below which correctly depicts the graph above.

CAT is connected to ['COT', 'BAT', 'CUT', 'RAT']
RAT is connected to ['BAT', 'CAT']
COT is connected to ['CUT', 'CAT', 'COG', 'COW']
CUT is connected to ['COT', 'BUT', 'CAT']
COG is connected to ['COT', 'DOG', 'COW']
DOG is connected to ['COG']
BUT is connected to ['BAT', 'CUT']
BAT is connected to ['BUT', 'CAT', 'RAT']
COW is connected to ['COT', 'COG']
CAT is connected to ['COT', 'BAT', 'CUT', 'RAT']

What could be going wrong then?

Body:
Ok so I figured out the issue.The problem was in this line of code

neighbours = graph[node]

Basically it is trying the fetch the neigbours for the particular node.So it needs to access the vertList dictionary declared as an attribute for the Graph class.So for an object to access the dictonary value, one has to implement a __getitem__ special method.So I declare this under the Graph class as follows

# returns the value for the key which will be an object
def __getitem__(self, key):
    return self.vertList[key]

Now graph[node] will be able to fetch the object representation of the node since the value of vertList dictionary is a vertex object (vertList stores vertex name as key and vertex object as value) .So I have to explicitly tell it to fetch the object's neighbours and not the object itself.So I can call the getConnections() method under the Vertex class which further calls the connectedTo attribute to get the neighbour objects for the particular vertex object. (connectedTo dictionary has the vertex object as the key and edge weight as the value.)

So now those neighbour objects will have their own ids which I can access and use it for the BFS operation.The below line is the modified code (under the bfs_shortest_path method) which does the above work.

if node not in explored:
    neighbours = [x.id for x in graph[node].getConnections()]

Now I get the list of the neigbours for the particular node and use it.The rest of the code stays the same.


问:
php custom exception handling
I am wanting to handle exceptions in my PHP application myself.

When I throw an exception I am wanting to pass along a title to be used in the error page.

Can someone please link me to a good tutorial, or write a clear explanation of how the exception handling actually works (eg how to know what sort of exception you are dealing with, etc.

答:
Try this as the first thing on your php page(s).

It captures php errors and exceptions.

```<code>function php_error($input, $msg = '', $file = '', $line = '', $context = '') {
    if (error_reporting() == 0) return;

    if (is_object($input)) {
        echo "<strong>PHP EXCEPTION: </strong>";
        h_print($input);
        $title  = 'PHP Exception';
        $error  = 'Exception';
        $code   = null;
    } else {
        if ($input == E_STRICT) return;
        if ($input != E_ERROR) return;
        $title  = 'PHP Error';
        $error  = $msg.' in <strong>'.$file.'</strong> on <strong>line '.$line.'</strong>.';
        $code   = null;
    }

    debug($title, $error, $code);

}

set_error_handler('php_error');
set_exception_handler('php_error');
</code>```

Title: php custom exception handling

Body:
Try this as the first thing on your php page(s).

It captures php errors and exceptions.

function php_error($input, $msg = '', $file = '', $line = '', $context = '') {
    if (error_reporting() == 0) return;

    if (is_object($input)) {
        echo "<strong>PHP EXCEPTION: </strong>";
        h_print($input);
        $title  = 'PHP Exception';
        $error  = 'Exception';
        $code   = null;
    } else {
        if ($input == E_STRICT) return;
        if ($input != E_ERROR) return;
        $title  = 'PHP Error';
        $error  = $msg.' in <strong>'.$file.'</strong> on <strong>line '.$line.'</strong>.';
        $code   = null;
    }

    debug($title, $error, $code);

}

set_error_handler('php_error');
set_exception_handler('php_error');