From a1deec427131c9e82153a6a1b8e7400ece631ca6 Mon Sep 17 00:00:00 2001 From: manoelosouza Date: Thu, 4 Feb 2021 11:47:36 -0300 Subject: [PATCH 01/33] Update README.md Update readme --- .env.example | 3 + .gitattributes | 7 + .gitignore | 34 +++ .ruby-version | 1 + Dockerfile | 16 ++ Gemfile | 73 ++++++ Gemfile.lock | 237 ++++++++++++++++++ README.example.md | 24 ++ README.md | 1 + Rakefile | 6 + app/assets/config/manifest.js | 2 + app/assets/images/.keep | 0 app/assets/stylesheets/application.css | 15 ++ app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/controllers/application_controller.rb | 2 + app/controllers/concerns/.keep | 0 app/helpers/application_helper.rb | 2 + app/jobs/application_job.rb | 7 + app/mailers/application_mailer.rb | 4 + app/models/application_record.rb | 3 + app/models/concerns/.keep | 0 app/views/layouts/application.html.erb | 15 ++ app/views/layouts/mailer.html.erb | 13 + app/views/layouts/mailer.text.erb | 1 + bin/rails | 4 + bin/rake | 4 + bin/setup | 33 +++ config.ru | 6 + config/application.rb | 22 ++ config/boot.rb | 4 + config/cable.yml | 10 + config/credentials.yml.enc | 1 + config/database.yml | 19 ++ config/environment.rb | 5 + config/environments/development.rb | 70 ++++++ config/environments/production.rb | 93 +++++++ config/environments/test.rb | 60 +++++ config/initializers/assets.rb | 12 + .../initializers/content_security_policy.rb | 25 ++ .../initializers/filter_parameter_logging.rb | 8 + config/initializers/inflections.rb | 16 ++ config/initializers/permissions_policy.rb | 11 + config/locales/en.yml | 33 +++ config/puma.rb | 43 ++++ config/routes.rb | 6 + config/storage.yml | 34 +++ db/seeds.rb | 7 + docker-compose.yml | 17 ++ entrypoint.sh | 8 + lib/assets/.keep | 0 lib/tasks/.keep | 0 log/.keep | 0 public/404.html | 67 +++++ public/422.html | 67 +++++ public/500.html | 66 +++++ public/apple-touch-icon-precomposed.png | 0 public/apple-touch-icon.png | 0 public/favicon.ico | 0 public/robots.txt | 1 + storage/.keep | 0 test/application_system_test_case.rb | 5 + .../application_cable/connection_test.rb | 11 + test/controllers/.keep | 0 test/fixtures/files/.keep | 0 test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/system/.keep | 0 test/test_helper.rb | 13 + tmp/.keep | 0 tmp/pids/.keep | 0 tmp/storage/.keep | 0 vendor/.keep | 0 75 files changed, 1255 insertions(+) create mode 100644 .env.example create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .ruby-version create mode 100644 Dockerfile create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 README.example.md create mode 100644 Rakefile create mode 100644 app/assets/config/manifest.js create mode 100644 app/assets/images/.keep create mode 100644 app/assets/stylesheets/application.css create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/concerns/.keep create mode 100644 app/helpers/application_helper.rb create mode 100644 app/jobs/application_job.rb create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/models/application_record.rb create mode 100644 app/models/concerns/.keep create mode 100644 app/views/layouts/application.html.erb create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.erb create mode 100755 bin/rails create mode 100755 bin/rake create mode 100755 bin/setup create mode 100644 config.ru create mode 100644 config/application.rb create mode 100644 config/boot.rb create mode 100644 config/cable.yml create mode 100644 config/credentials.yml.enc create mode 100644 config/database.yml create mode 100644 config/environment.rb create mode 100644 config/environments/development.rb create mode 100644 config/environments/production.rb create mode 100644 config/environments/test.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/initializers/inflections.rb create mode 100644 config/initializers/permissions_policy.rb create mode 100644 config/locales/en.yml create mode 100644 config/puma.rb create mode 100644 config/routes.rb create mode 100644 config/storage.yml create mode 100644 db/seeds.rb create mode 100644 docker-compose.yml create mode 100644 entrypoint.sh create mode 100644 lib/assets/.keep create mode 100644 lib/tasks/.keep create mode 100644 log/.keep create mode 100644 public/404.html create mode 100644 public/422.html create mode 100644 public/500.html create mode 100644 public/apple-touch-icon-precomposed.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon.ico create mode 100644 public/robots.txt create mode 100644 storage/.keep create mode 100644 test/application_system_test_case.rb create mode 100644 test/channels/application_cable/connection_test.rb create mode 100644 test/controllers/.keep create mode 100644 test/fixtures/files/.keep create mode 100644 test/helpers/.keep create mode 100644 test/integration/.keep create mode 100644 test/mailers/.keep create mode 100644 test/models/.keep create mode 100644 test/system/.keep create mode 100644 test/test_helper.rb create mode 100644 tmp/.keep create mode 100644 tmp/pids/.keep create mode 100644 tmp/storage/.keep create mode 100644 vendor/.keep diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..ce1440ef74 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +DATABASE_USERNAME=username +DATABASE_PASSWORD=password +DATABASE_HOST=host diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..31eeee0b6a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# See https://git-scm.com/docs/gitattributes for more about git attribute files. + +# Mark the database schema as having been generated. +db/schema.rb linguist-generated + +# Mark any vendored files as having been vendored. +vendor/* linguist-vendored diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..2f4b643a82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore pidfiles, but keep the directory. +/tmp/pids/* +!/tmp/pids/ +!/tmp/pids/.keep + +# Ignore uploaded files in development. +/storage/* +!/storage/.keep +/tmp/storage/* +!/tmp/storage/ +!/tmp/storage/.keep + +/public/assets + +# Ignore master key for decrypting credentials and more. +/config/master.key + +# Ignore .env file +.env diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000000..7bde84d06c --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +ruby-3.1.2 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..424e139c0f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM ruby:3.1.2 + +RUN apt-get update -qq && apt-get install -y nodejs postgresql-client +WORKDIR /github-search +COPY Gemfile /github-search/Gemfile +COPY Gemfile.lock /github-search/Gemfile.lock +RUN bundle install + +# Add a script to be executed every time the container starts. +COPY entrypoint.sh /usr/bin/ +RUN chmod +x /usr/bin/entrypoint.sh +ENTRYPOINT ["entrypoint.sh"] +EXPOSE 3000 + +# Configure the main process to run when running the image +CMD ["rails", "server", "-b", "0.0.0.0"] diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..4e19311185 --- /dev/null +++ b/Gemfile @@ -0,0 +1,73 @@ +source "https://rubygems.org" +git_source(:github) { |repo| "https://github.com/#{repo}.git" } + +ruby "3.1.2" + +# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" +gem "rails", "~> 7.0.4" + +# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] +gem "sprockets-rails" + +# Use postgresql as the database for Active Record +gem "pg", "~> 1.1" + +# Use the Puma web server [https://github.com/puma/puma] +gem "puma", "~> 5.0" + +# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails] +gem "importmap-rails" + +# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] +gem "turbo-rails" + +# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] +gem "stimulus-rails" + +# Build JSON APIs with ease [https://github.com/rails/jbuilder] +gem "jbuilder" + +# Use Redis adapter to run Action Cable in production +# gem "redis", "~> 4.0" + +# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] +# gem "kredis" + +# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] +# gem "bcrypt", "~> 3.1.7" + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] + +# Reduces boot times through caching; required in config/boot.rb +gem "bootsnap", require: false + +# Use Sass to process CSS +# gem "sassc-rails" + +# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] +# gem "image_processing", "~> 1.2" + +group :development, :test do + # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem + gem "debug", platforms: %i[ mri mingw x64_mingw ] + gem "dotenv-rails" +end + +group :development do + # Use console on exceptions pages [https://github.com/rails/web-console] + gem "web-console" + + # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] + # gem "rack-mini-profiler" + + # Speed up commands on slow machines / big apps [https://github.com/rails/spring] + # gem "spring" +end + +group :test do + # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] + gem "capybara" + gem "selenium-webdriver" + gem "webdrivers" +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..f53ac98f84 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,237 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.0.4) + actionpack (= 7.0.4) + activesupport (= 7.0.4) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (7.0.4) + actionpack (= 7.0.4) + activejob (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.4) + actionpack (= 7.0.4) + actionview (= 7.0.4) + activejob (= 7.0.4) + activesupport (= 7.0.4) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.0) + actionpack (7.0.4) + actionview (= 7.0.4) + activesupport (= 7.0.4) + rack (~> 2.0, >= 2.2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (7.0.4) + actionpack (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.0.4) + activesupport (= 7.0.4) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.4) + activesupport (= 7.0.4) + globalid (>= 0.3.6) + activemodel (7.0.4) + activesupport (= 7.0.4) + activerecord (7.0.4) + activemodel (= 7.0.4) + activesupport (= 7.0.4) + activestorage (7.0.4) + actionpack (= 7.0.4) + activejob (= 7.0.4) + activerecord (= 7.0.4) + activesupport (= 7.0.4) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (7.0.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + bindex (0.8.1) + bootsnap (1.15.0) + msgpack (~> 1.2) + builder (3.2.4) + capybara (3.38.0) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + concurrent-ruby (1.1.10) + crass (1.0.6) + date (3.3.3) + debug (1.7.1) + irb (>= 1.5.0) + reline (>= 0.3.1) + dotenv (2.8.1) + dotenv-rails (2.8.1) + dotenv (= 2.8.1) + railties (>= 3.2) + erubi (1.12.0) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.12.0) + concurrent-ruby (~> 1.0) + importmap-rails (1.1.5) + actionpack (>= 6.0.0) + railties (>= 6.0.0) + io-console (0.6.0) + irb (1.6.2) + reline (>= 0.3.0) + jbuilder (2.11.5) + actionview (>= 5.0.0) + activesupport (>= 5.0.0) + loofah (2.19.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.8.0) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) + method_source (1.0.0) + mini_mime (1.1.2) + minitest (5.17.0) + msgpack (1.6.0) + net-imap (0.3.4) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.3.3) + net-protocol + nio4r (2.5.8) + nokogiri (1.13.10-x86_64-linux) + racc (~> 1.4) + pg (1.4.5) + public_suffix (5.0.1) + puma (5.6.5) + nio4r (~> 2.0) + racc (1.6.2) + rack (2.2.5) + rack-test (2.0.2) + rack (>= 1.3) + rails (7.0.4) + actioncable (= 7.0.4) + actionmailbox (= 7.0.4) + actionmailer (= 7.0.4) + actionpack (= 7.0.4) + actiontext (= 7.0.4) + actionview (= 7.0.4) + activejob (= 7.0.4) + activemodel (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + bundler (>= 1.15.0) + railties (= 7.0.4) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.4.4) + loofah (~> 2.19, >= 2.19.1) + railties (7.0.4) + actionpack (= 7.0.4) + activesupport (= 7.0.4) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rake (13.0.6) + regexp_parser (2.6.1) + reline (0.3.2) + io-console (~> 0.5) + rexml (3.2.5) + rubyzip (2.3.2) + selenium-webdriver (4.7.1) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + sprockets (4.2.0) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) + sprockets (>= 3.0.0) + stimulus-rails (1.2.1) + railties (>= 6.0.0) + thor (1.2.1) + timeout (0.3.1) + turbo-rails (1.3.2) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (2.0.5) + concurrent-ruby (~> 1.0) + web-console (4.2.0) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) + bindex (>= 0.4.0) + railties (>= 6.0.0) + webdrivers (5.2.0) + nokogiri (~> 1.6) + rubyzip (>= 1.3.0) + selenium-webdriver (~> 4.0) + websocket (1.2.9) + websocket-driver (0.7.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.6) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + bootsnap + capybara + debug + dotenv-rails + importmap-rails + jbuilder + pg (~> 1.1) + puma (~> 5.0) + rails (~> 7.0.4) + selenium-webdriver + sprockets-rails + stimulus-rails + turbo-rails + tzinfo-data + web-console + webdrivers + +RUBY VERSION + ruby 3.1.2p20 + +BUNDLED WITH + 2.3.7 diff --git a/README.example.md b/README.example.md new file mode 100644 index 0000000000..28feefee53 --- /dev/null +++ b/README.example.md @@ -0,0 +1,24 @@ +# README + +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +- Ruby version + +- System dependencies + +- Configuration + +- Database creation + +- Database initialization + +- How to run the test suite + +- Services (job queues, cache servers, search engines, etc.) + +- Deployment instructions + +- ... diff --git a/README.md b/README.md index a3fb960f88..3f1e493650 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Alguns requisitos: - O deploy deve ser realizado, preferencialmente, no Heroku, AWS ou no Azure; - A aplicação precisa ter testes automatizados; - Preferenciamente dockerizar a aplicação; +- Por favor atualizar o readme da aplicação com passo a passo com instrução para subir o ambiente. Quando terminar, faça um Pull Request neste repo e avise-nos por email. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000000..9a5ea7383a --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative "config/application" + +Rails.application.load_tasks diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 0000000000..591819335f --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,2 @@ +//= link_tree ../images +//= link_directory ../stylesheets .css diff --git a/app/assets/images/.keep b/app/assets/images/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..288b9ab718 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's + * vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 0000000000..d672697283 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 0000000000..0ff5442f47 --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000000..09705d12ab --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::Base +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000000..de6be7945c --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 0000000000..d394c3d106 --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,7 @@ +class ApplicationJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked + + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError +end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 0000000000..3c34c8148f --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: "from@example.com" + layout "mailer" +end diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 0000000000..b63caeb8a5 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + primary_abstract_class +end diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000000..55e16a8038 --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,15 @@ + + + + GithubSearch + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000000..cbd34d2e9d --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000000..37f0bddbd7 --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000000..efc0377492 --- /dev/null +++ b/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path("../config/application", __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000000..4fbf10b960 --- /dev/null +++ b/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "rake" +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000000..ec47b79b3b --- /dev/null +++ b/bin/setup @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +require "fileutils" + +# path to your application root. +APP_ROOT = File.expand_path("..", __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. + # Add necessary setup steps to this file. + + puts "== Installing dependencies ==" + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" + # end + + puts "\n== Preparing database ==" + system! "bin/rails db:prepare" + + puts "\n== Removing old logs and tempfiles ==" + system! "bin/rails log:clear tmp:clear" + + puts "\n== Restarting application server ==" + system! "bin/rails restart" +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000000..4a3c09a688 --- /dev/null +++ b/config.ru @@ -0,0 +1,6 @@ +# This file is used by Rack-based servers to start the application. + +require_relative "config/environment" + +run Rails.application +Rails.application.load_server diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 0000000000..b078d80ea8 --- /dev/null +++ b/config/application.rb @@ -0,0 +1,22 @@ +require_relative "boot" + +require "rails/all" + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module GithubSearch + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 7.0 + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000000..988a5ddc46 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,4 @@ +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "bundler/setup" # Set up gems listed in the Gemfile. +require "bootsnap/setup" # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 0000000000..0e4a164d3c --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: test + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: github_search_production diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc new file mode 100644 index 0000000000..2b84853b6c --- /dev/null +++ b/config/credentials.yml.enc @@ -0,0 +1 @@ +31qGfKNJTfDMHvpy0RTIYgQa1PVTjth70Z+TzSxpr4nq5LqYOL6M2VPwHcbJEguS1JhXAvgVRN5Cv7gbat3QnMI+lLrNnuXrRDNVDi9eBAcqfxDTOfCFuRZ6EujVUqoXioBMbtHwRp4rFchaLqm3CJEJPoYEdeMp/E7rq7cMM05xFV8HXWA+yGQ4kWgDbM16Dx9jcSEdyEYxN4Zv7LBVSPo3cPRRC90DkWiyYpT0L8hv2jw+1UALk7UytIFMonGG0M1GUSZ69Re3d8aDi1GZxUOL+E1ifAePx4QzaGtotcYqQ4d1SJIcoKCddiEBvWKfvM/GuEl8ys6UxBYw5quO0EP8dBkKzzK3g+7HeBpGrgAfQ7x+rQzN6n+FsLdgkFy1+sTuq6SmS2UfkfPXU8LYENLSBbHn3UNZx3t8--zrVwtxf26Kchm5xm--teYkz+CeRSWefdhExuwHcA== \ No newline at end of file diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000000..d236abd048 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,19 @@ +default: &default + adapter: postgresql + encoding: unicode + host: <%= ENV['DATABASE_HOST'] %> + username: <%= ENV['DATABASE_USERNAME'] %> + password: <%= ENV['DATABASE_PASSWORD'] %> + pool: 5 + +development: + <<: *default + database: github-search_development + +test: + <<: *default + database: github-search_test + +production: + <<: *default + database: github-search_production diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000000..cac5315775 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative "application" + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000000..8500f459a8 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,70 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded any time + # it changes. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable server timing + config.server_timing = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join("tmp/caching-dev.txt").exist? + config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000000..b8b0862e05 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,93 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? + + # Compress CSS using a preprocessor. + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache + # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain. + # config.action_cable.mount_path = nil + # config.action_cable.url = "wss://example.com/cable" + # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Include generic and useful information about system operation, but avoid logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). + config.log_level = :info + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment). + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "github_search_production" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Don't log any deprecations. + config.active_support.report_deprecations = false + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require "syslog/logger" + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000000..6ea4d1e706 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,60 @@ +require "active_support/core_ext/integer/time" + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Turn false under Spring and add config.action_view.cache_template_loading = true. + config.cache_classes = true + + # Eager loading loads your whole application. When running a single test locally, + # this probably isn't necessary. It's a good idea to do in a continuous integration + # system, or in some way before deploying your code. + config.eager_load = ENV["CI"].present? + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + config.cache_store = :null_store + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory. + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true +end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000000..2eeef966fe --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,12 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = "1.0" + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 0000000000..54f47cf15f --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy. +# See the Securing Rails Applications Guide for more information: +# https://guides.rubyonrails.org/security.html#content-security-policy-header + +# Rails.application.configure do +# config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end +# +# # Generate session nonces for permitted importmap and inline scripts +# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } +# config.content_security_policy_nonce_directives = %w(script-src) +# +# # Report violations without enforcing the policy. +# # config.content_security_policy_report_only = true +# end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000000..adc6568ce8 --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# Configure parameters to be filtered from the log file. Use this to limit dissemination of +# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported +# notations and behaviors. +Rails.application.config.filter_parameters += [ + :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 0000000000..3860f659ea --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "RESTful" +# end diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb new file mode 100644 index 0000000000..00f64d71b0 --- /dev/null +++ b/config/initializers/permissions_policy.rb @@ -0,0 +1,11 @@ +# Define an application-wide HTTP permissions policy. For further +# information see https://developers.google.com/web/updates/2018/06/feature-policy +# +# Rails.application.config.permissions_policy do |f| +# f.camera :none +# f.gyroscope :none +# f.microphone :none +# f.usb :none +# f.fullscreen :self +# f.payment :self, "https://secure.example.com" +# end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000000..8ca56fc74f --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,33 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t "hello" +# +# In views, this is aliased to just `t`: +# +# <%= t("hello") %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# "true": "foo" +# +# To learn more, please read the Rails Internationalization guide +# available at https://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 0000000000..daaf036999 --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,43 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count + +# Specifies the `worker_timeout` threshold that Puma will use to wait before +# terminating a worker in development environments. +# +worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked web server processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `bin/rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000000..262ffd5472 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,6 @@ +Rails.application.routes.draw do + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + + # Defines the root path route ("/") + # root "articles#index" +end diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 0000000000..4942ab6694 --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket-<%= Rails.env %> + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket-<%= Rails.env %> + +# Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name-<%= Rails.env %> + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000000..bc25fce306 --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). +# +# Examples: +# +# movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }]) +# Character.create(name: "Luke", movie: movies.first) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..ce5f06ed6e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3" +services: + db: + image: postgres + volumes: + - ./tmp/db:/var/lib/postgresql/data + environment: + POSTGRES_PASSWORD: password + web: + build: . + command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" + volumes: + - .:/github-search + ports: + - "3000:3000" + depends_on: + - db diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000000..a8a58fd667 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +# Remove a potentially pre-existing server.pid for Rails. +rm -f /github-search/tmp/pids/server.pid + +# Then exec the container's main process (what's set as CMD in the Dockerfile). +exec "$@" diff --git a/lib/assets/.keep b/lib/assets/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/tasks/.keep b/lib/tasks/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/log/.keep b/log/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000000..2be3af26fc --- /dev/null +++ b/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/422.html b/public/422.html new file mode 100644 index 0000000000..c08eac0d1d --- /dev/null +++ b/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/500.html b/public/500.html new file mode 100644 index 0000000000..78a030af22 --- /dev/null +++ b/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000000..c19f78ab68 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1 @@ +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/storage/.keep b/storage/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb new file mode 100644 index 0000000000..d19212abd5 --- /dev/null +++ b/test/application_system_test_case.rb @@ -0,0 +1,5 @@ +require "test_helper" + +class ApplicationSystemTestCase < ActionDispatch::SystemTestCase + driven_by :selenium, using: :chrome, screen_size: [1400, 1400] +end diff --git a/test/channels/application_cable/connection_test.rb b/test/channels/application_cable/connection_test.rb new file mode 100644 index 0000000000..800405f15e --- /dev/null +++ b/test/channels/application_cable/connection_test.rb @@ -0,0 +1,11 @@ +require "test_helper" + +class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase + # test "connects with cookies" do + # cookies.signed[:user_id] = 42 + # + # connect + # + # assert_equal connection.user_id, "42" + # end +end diff --git a/test/controllers/.keep b/test/controllers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/helpers/.keep b/test/helpers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/integration/.keep b/test/integration/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/mailers/.keep b/test/mailers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/models/.keep b/test/models/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/system/.keep b/test/system/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000000..d713e377c9 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,13 @@ +ENV["RAILS_ENV"] ||= "test" +require_relative "../config/environment" +require "rails/test_help" + +class ActiveSupport::TestCase + # Run tests in parallel with specified workers + parallelize(workers: :number_of_processors) + + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + + # Add more helper methods to be used by all tests here... +end diff --git a/tmp/.keep b/tmp/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tmp/pids/.keep b/tmp/pids/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tmp/storage/.keep b/tmp/storage/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/.keep b/vendor/.keep new file mode 100644 index 0000000000..e69de29bb2 From 43f3ec5fe18977036bb2661b446d188979d9b786 Mon Sep 17 00:00:00 2001 From: bielzin Date: Wed, 11 Jan 2023 22:24:01 -0300 Subject: [PATCH 02/33] scaffold language --- app/controllers/languages_controller.rb | 70 +++++++++++++++++++ app/helpers/languages_helper.rb | 2 + app/models/language.rb | 11 +++ app/views/languages/_form.html.erb | 22 ++++++ app/views/languages/_language.html.erb | 7 ++ app/views/languages/_language.json.jbuilder | 2 + app/views/languages/edit.html.erb | 10 +++ app/views/languages/index.html.erb | 14 ++++ app/views/languages/index.json.jbuilder | 1 + app/views/languages/new.html.erb | 9 +++ app/views/languages/show.html.erb | 10 +++ app/views/languages/show.json.jbuilder | 1 + config/routes.rb | 1 + db/migrate/20230111221511_create_languages.rb | 9 +++ .../20230111222750_add_slug_to_languages.rb | 5 ++ db/schema.rb | 24 +++++++ db/seeds.rb | 6 ++ test/controllers/languages_controller_test.rb | 48 +++++++++++++ test/fixtures/languages.yml | 7 ++ test/models/language_test.rb | 7 ++ test/system/languages_test.rb | 41 +++++++++++ 21 files changed, 307 insertions(+) create mode 100644 app/controllers/languages_controller.rb create mode 100644 app/helpers/languages_helper.rb create mode 100644 app/models/language.rb create mode 100644 app/views/languages/_form.html.erb create mode 100644 app/views/languages/_language.html.erb create mode 100644 app/views/languages/_language.json.jbuilder create mode 100644 app/views/languages/edit.html.erb create mode 100644 app/views/languages/index.html.erb create mode 100644 app/views/languages/index.json.jbuilder create mode 100644 app/views/languages/new.html.erb create mode 100644 app/views/languages/show.html.erb create mode 100644 app/views/languages/show.json.jbuilder create mode 100644 db/migrate/20230111221511_create_languages.rb create mode 100644 db/migrate/20230111222750_add_slug_to_languages.rb create mode 100644 db/schema.rb create mode 100644 test/controllers/languages_controller_test.rb create mode 100644 test/fixtures/languages.yml create mode 100644 test/models/language_test.rb create mode 100644 test/system/languages_test.rb diff --git a/app/controllers/languages_controller.rb b/app/controllers/languages_controller.rb new file mode 100644 index 0000000000..a42fb17e6d --- /dev/null +++ b/app/controllers/languages_controller.rb @@ -0,0 +1,70 @@ +class LanguagesController < ApplicationController + before_action :set_language, only: %i[ show edit update destroy ] + + # GET /languages or /languages.json + def index + @languages = Language.all + end + + # GET /languages/1 or /languages/1.json + def show + end + + # GET /languages/new + def new + @language = Language.new + end + + # GET /languages/1/edit + def edit + end + + # POST /languages or /languages.json + def create + @language = Language.new(language_params) + + respond_to do |format| + if @language.save + format.html { redirect_to language_url(@language), notice: "Language was successfully created." } + format.json { render :show, status: :created, location: @language } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @language.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /languages/1 or /languages/1.json + def update + respond_to do |format| + if @language.update(language_params) + format.html { redirect_to language_url(@language), notice: "Language was successfully updated." } + format.json { render :show, status: :ok, location: @language } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @language.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /languages/1 or /languages/1.json + def destroy + @language.destroy + + respond_to do |format| + format.html { redirect_to languages_url, notice: "Language was successfully destroyed." } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_language + @language = Language.find_by slug: params[:slug] + end + + # Only allow a list of trusted parameters through. + def language_params + params.require(:language).permit(:name) + end +end diff --git a/app/helpers/languages_helper.rb b/app/helpers/languages_helper.rb new file mode 100644 index 0000000000..24686681a6 --- /dev/null +++ b/app/helpers/languages_helper.rb @@ -0,0 +1,2 @@ +module LanguagesHelper +end diff --git a/app/models/language.rb b/app/models/language.rb new file mode 100644 index 0000000000..f03e25a96e --- /dev/null +++ b/app/models/language.rb @@ -0,0 +1,11 @@ +class Language < ApplicationRecord + before_validation :add_slug + + def add_slug + self.slug = name.parameterize + end + + def to_param + slug + end +end diff --git a/app/views/languages/_form.html.erb b/app/views/languages/_form.html.erb new file mode 100644 index 0000000000..c69ac33bf5 --- /dev/null +++ b/app/views/languages/_form.html.erb @@ -0,0 +1,22 @@ +<%= form_with(model: language) do |form| %> + <% if language.errors.any? %> +
+

<%= pluralize(language.errors.count, "error") %> prohibited this language from being saved:

+ +
    + <% language.errors.each do |error| %> +
  • <%= error.full_message %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= form.label :name, style: "display: block" %> + <%= form.text_field :name %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/languages/_language.html.erb b/app/views/languages/_language.html.erb new file mode 100644 index 0000000000..e6e047b26d --- /dev/null +++ b/app/views/languages/_language.html.erb @@ -0,0 +1,7 @@ +
+

+ Name: + <%= language.name %> +

+ +
diff --git a/app/views/languages/_language.json.jbuilder b/app/views/languages/_language.json.jbuilder new file mode 100644 index 0000000000..34f5b0e357 --- /dev/null +++ b/app/views/languages/_language.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! language, :id, :name, :created_at, :updated_at +json.url language_url(language, format: :json) diff --git a/app/views/languages/edit.html.erb b/app/views/languages/edit.html.erb new file mode 100644 index 0000000000..1c5c9900bf --- /dev/null +++ b/app/views/languages/edit.html.erb @@ -0,0 +1,10 @@ +

Editing language

+ +<%= render "form", language: @language %> + +
+ +
+ <%= link_to "Show this language", @language %> | + <%= link_to "Back to languages", languages_path %> +
diff --git a/app/views/languages/index.html.erb b/app/views/languages/index.html.erb new file mode 100644 index 0000000000..c8383c6fde --- /dev/null +++ b/app/views/languages/index.html.erb @@ -0,0 +1,14 @@ +

<%= notice %>

+ +

Languages

+ +
+ <% @languages.each do |language| %> + <%= render language %> +

+ <%= link_to "Show this language", language %> +

+ <% end %> +
+ +<%= link_to "New language", new_language_path %> diff --git a/app/views/languages/index.json.jbuilder b/app/views/languages/index.json.jbuilder new file mode 100644 index 0000000000..7b14dc271c --- /dev/null +++ b/app/views/languages/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @languages, partial: "languages/language", as: :language diff --git a/app/views/languages/new.html.erb b/app/views/languages/new.html.erb new file mode 100644 index 0000000000..bebcc3df0d --- /dev/null +++ b/app/views/languages/new.html.erb @@ -0,0 +1,9 @@ +

New language

+ +<%= render "form", language: @language %> + +
+ +
+ <%= link_to "Back to languages", languages_path %> +
diff --git a/app/views/languages/show.html.erb b/app/views/languages/show.html.erb new file mode 100644 index 0000000000..a7cf28ab13 --- /dev/null +++ b/app/views/languages/show.html.erb @@ -0,0 +1,10 @@ +

<%= notice %>

+ +<%= render @language %> + +
+ <%= link_to "Edit this language", edit_language_path(@language) %> | + <%= link_to "Back to languages", languages_path %> + + <%= button_to "Destroy this language", @language, method: :delete %> +
diff --git a/app/views/languages/show.json.jbuilder b/app/views/languages/show.json.jbuilder new file mode 100644 index 0000000000..db596e5101 --- /dev/null +++ b/app/views/languages/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "languages/language", language: @language diff --git a/config/routes.rb b/config/routes.rb index 262ffd5472..cc3ce617ff 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + resources :languages, param: :slug # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Defines the root path route ("/") diff --git a/db/migrate/20230111221511_create_languages.rb b/db/migrate/20230111221511_create_languages.rb new file mode 100644 index 0000000000..792ba5137e --- /dev/null +++ b/db/migrate/20230111221511_create_languages.rb @@ -0,0 +1,9 @@ +class CreateLanguages < ActiveRecord::Migration[7.0] + def change + create_table :languages do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20230111222750_add_slug_to_languages.rb b/db/migrate/20230111222750_add_slug_to_languages.rb new file mode 100644 index 0000000000..d8dcad5119 --- /dev/null +++ b/db/migrate/20230111222750_add_slug_to_languages.rb @@ -0,0 +1,5 @@ +class AddSlugToLanguages < ActiveRecord::Migration[7.0] + def change + add_column :languages, :slug, :string, null: false, default: '' + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..024cc13da4 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,24 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.0].define(version: 2023_01_11_222750) do + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "languages", force: :cascade do |t| + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "slug", default: "", null: false + end + +end diff --git a/db/seeds.rb b/db/seeds.rb index bc25fce306..c0de16ac5a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,3 +5,9 @@ # # movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }]) # Character.create(name: "Luke", movie: movies.first) + +Language.create(name: 'javascript') +Language.create(name: 'ruby') +Language.create(name: 'elixir') +Language.create(name: 'typescript') +Language.create(name: 'python') diff --git a/test/controllers/languages_controller_test.rb b/test/controllers/languages_controller_test.rb new file mode 100644 index 0000000000..af9287784b --- /dev/null +++ b/test/controllers/languages_controller_test.rb @@ -0,0 +1,48 @@ +require "test_helper" + +class LanguagesControllerTest < ActionDispatch::IntegrationTest + setup do + @language = languages(:one) + end + + test "should get index" do + get languages_url + assert_response :success + end + + test "should get new" do + get new_language_url + assert_response :success + end + + test "should create language" do + assert_difference("Language.count") do + post languages_url, params: { language: { name: @language.name } } + end + + assert_redirected_to language_url(Language.last) + end + + test "should show language" do + get language_url(@language) + assert_response :success + end + + test "should get edit" do + get edit_language_url(@language) + assert_response :success + end + + test "should update language" do + patch language_url(@language), params: { language: { name: @language.name } } + assert_redirected_to language_url(@language) + end + + test "should destroy language" do + assert_difference("Language.count", -1) do + delete language_url(@language) + end + + assert_redirected_to languages_url + end +end diff --git a/test/fixtures/languages.yml b/test/fixtures/languages.yml new file mode 100644 index 0000000000..7d4122404c --- /dev/null +++ b/test/fixtures/languages.yml @@ -0,0 +1,7 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + +two: + name: MyString diff --git a/test/models/language_test.rb b/test/models/language_test.rb new file mode 100644 index 0000000000..90c9cd0995 --- /dev/null +++ b/test/models/language_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class LanguageTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/system/languages_test.rb b/test/system/languages_test.rb new file mode 100644 index 0000000000..022ad83cad --- /dev/null +++ b/test/system/languages_test.rb @@ -0,0 +1,41 @@ +require "application_system_test_case" + +class LanguagesTest < ApplicationSystemTestCase + setup do + @language = languages(:one) + end + + test "visiting the index" do + visit languages_url + assert_selector "h1", text: "Languages" + end + + test "should create language" do + visit languages_url + click_on "New language" + + fill_in "Name", with: @language.name + click_on "Create Language" + + assert_text "Language was successfully created" + click_on "Back" + end + + test "should update Language" do + visit language_url(@language) + click_on "Edit this language", match: :first + + fill_in "Name", with: @language.name + click_on "Update Language" + + assert_text "Language was successfully updated" + click_on "Back" + end + + test "should destroy Language" do + visit language_url(@language) + click_on "Destroy this language", match: :first + + assert_text "Language was successfully destroyed" + end +end From 07a621f050c547f242ec166f43746778ad4d4b38 Mon Sep 17 00:00:00 2001 From: bielzin Date: Wed, 11 Jan 2023 22:27:10 -0300 Subject: [PATCH 03/33] scaffold repository --- app/controllers/repositories_controller.rb | 70 ++++++++++++++++ app/helpers/repositories_helper.rb | 2 + app/models/repository.rb | 3 + app/views/repositories/_form.html.erb | 82 +++++++++++++++++++ app/views/repositories/_repository.html.erb | 67 +++++++++++++++ .../repositories/_repository.json.jbuilder | 2 + app/views/repositories/edit.html.erb | 10 +++ app/views/repositories/index.html.erb | 14 ++++ app/views/repositories/index.json.jbuilder | 1 + app/views/repositories/new.html.erb | 9 ++ app/views/repositories/show.html.erb | 10 +++ app/views/repositories/show.json.jbuilder | 1 + config/routes.rb | 1 + .../20230112012548_create_repositories.rb | 22 +++++ db/schema.rb | 23 +++++- .../repositories_controller_test.rb | 48 +++++++++++ test/fixtures/repositories.yml | 31 +++++++ test/models/repository_test.rb | 7 ++ test/system/repositories_test.rb | 65 +++++++++++++++ 19 files changed, 467 insertions(+), 1 deletion(-) create mode 100644 app/controllers/repositories_controller.rb create mode 100644 app/helpers/repositories_helper.rb create mode 100644 app/models/repository.rb create mode 100644 app/views/repositories/_form.html.erb create mode 100644 app/views/repositories/_repository.html.erb create mode 100644 app/views/repositories/_repository.json.jbuilder create mode 100644 app/views/repositories/edit.html.erb create mode 100644 app/views/repositories/index.html.erb create mode 100644 app/views/repositories/index.json.jbuilder create mode 100644 app/views/repositories/new.html.erb create mode 100644 app/views/repositories/show.html.erb create mode 100644 app/views/repositories/show.json.jbuilder create mode 100644 db/migrate/20230112012548_create_repositories.rb create mode 100644 test/controllers/repositories_controller_test.rb create mode 100644 test/fixtures/repositories.yml create mode 100644 test/models/repository_test.rb create mode 100644 test/system/repositories_test.rb diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb new file mode 100644 index 0000000000..d9f1072fcc --- /dev/null +++ b/app/controllers/repositories_controller.rb @@ -0,0 +1,70 @@ +class RepositoriesController < ApplicationController + before_action :set_repository, only: %i[ show edit update destroy ] + + # GET /repositories or /repositories.json + def index + @repositories = Repository.all + end + + # GET /repositories/1 or /repositories/1.json + def show + end + + # GET /repositories/new + def new + @repository = Repository.new + end + + # GET /repositories/1/edit + def edit + end + + # POST /repositories or /repositories.json + def create + @repository = Repository.new(repository_params) + + respond_to do |format| + if @repository.save + format.html { redirect_to repository_url(@repository), notice: "Repository was successfully created." } + format.json { render :show, status: :created, location: @repository } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @repository.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /repositories/1 or /repositories/1.json + def update + respond_to do |format| + if @repository.update(repository_params) + format.html { redirect_to repository_url(@repository), notice: "Repository was successfully updated." } + format.json { render :show, status: :ok, location: @repository } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @repository.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /repositories/1 or /repositories/1.json + def destroy + @repository.destroy + + respond_to do |format| + format.html { redirect_to repositories_url, notice: "Repository was successfully destroyed." } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_repository + @repository = Repository.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def repository_params + params.require(:repository).permit(:name, :node_id, :github_id, :full_name, :stars, :url, :forks, :open_issues, :license, :origin_created_at, :origin_updated, :topics, :language_id) + end +end diff --git a/app/helpers/repositories_helper.rb b/app/helpers/repositories_helper.rb new file mode 100644 index 0000000000..2860b5a916 --- /dev/null +++ b/app/helpers/repositories_helper.rb @@ -0,0 +1,2 @@ +module RepositoriesHelper +end diff --git a/app/models/repository.rb b/app/models/repository.rb new file mode 100644 index 0000000000..c6743c9eb5 --- /dev/null +++ b/app/models/repository.rb @@ -0,0 +1,3 @@ +class Repository < ApplicationRecord + belongs_to :language +end diff --git a/app/views/repositories/_form.html.erb b/app/views/repositories/_form.html.erb new file mode 100644 index 0000000000..2f7f8d8ec8 --- /dev/null +++ b/app/views/repositories/_form.html.erb @@ -0,0 +1,82 @@ +<%= form_with(model: repository) do |form| %> + <% if repository.errors.any? %> +
+

<%= pluralize(repository.errors.count, "error") %> prohibited this repository from being saved:

+ +
    + <% repository.errors.each do |error| %> +
  • <%= error.full_message %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= form.label :name, style: "display: block" %> + <%= form.text_field :name %> +
+ +
+ <%= form.label :node_id, style: "display: block" %> + <%= form.text_field :node_id %> +
+ +
+ <%= form.label :github_id, style: "display: block" %> + <%= form.number_field :github_id %> +
+ +
+ <%= form.label :full_name, style: "display: block" %> + <%= form.text_field :full_name %> +
+ +
+ <%= form.label :stars, style: "display: block" %> + <%= form.number_field :stars %> +
+ +
+ <%= form.label :url, style: "display: block" %> + <%= form.text_field :url %> +
+ +
+ <%= form.label :forks, style: "display: block" %> + <%= form.number_field :forks %> +
+ +
+ <%= form.label :open_issues, style: "display: block" %> + <%= form.number_field :open_issues %> +
+ +
+ <%= form.label :license, style: "display: block" %> + <%= form.text_field :license %> +
+ +
+ <%= form.label :origin_created_at, style: "display: block" %> + <%= form.datetime_field :origin_created_at %> +
+ +
+ <%= form.label :origin_updated, style: "display: block" %> + <%= form.text_field :origin_updated %> +
+ +
+ <%= form.label :topics, style: "display: block" %> + <%= form.text_area :topics %> +
+ +
+ <%= form.label :language_id, style: "display: block" %> + <%= form.text_field :language_id %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/repositories/_repository.html.erb b/app/views/repositories/_repository.html.erb new file mode 100644 index 0000000000..1c66dc92e9 --- /dev/null +++ b/app/views/repositories/_repository.html.erb @@ -0,0 +1,67 @@ +
+

+ Name: + <%= repository.name %> +

+ +

+ Node: + <%= repository.node_id %> +

+ +

+ Github: + <%= repository.github_id %> +

+ +

+ Full name: + <%= repository.full_name %> +

+ +

+ Stars: + <%= repository.stars %> +

+ +

+ Url: + <%= repository.url %> +

+ +

+ Forks: + <%= repository.forks %> +

+ +

+ Open issues: + <%= repository.open_issues %> +

+ +

+ License: + <%= repository.license %> +

+ +

+ Origin created at: + <%= repository.origin_created_at %> +

+ +

+ Origin updated: + <%= repository.origin_updated %> +

+ +

+ Topics: + <%= repository.topics %> +

+ +

+ Language: + <%= repository.language_id %> +

+ +
diff --git a/app/views/repositories/_repository.json.jbuilder b/app/views/repositories/_repository.json.jbuilder new file mode 100644 index 0000000000..b5490d4d29 --- /dev/null +++ b/app/views/repositories/_repository.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! repository, :id, :name, :node_id, :github_id, :full_name, :stars, :url, :forks, :open_issues, :license, :origin_created_at, :origin_updated, :topics, :language_id, :created_at, :updated_at +json.url repository_url(repository, format: :json) diff --git a/app/views/repositories/edit.html.erb b/app/views/repositories/edit.html.erb new file mode 100644 index 0000000000..c85cbbf66b --- /dev/null +++ b/app/views/repositories/edit.html.erb @@ -0,0 +1,10 @@ +

Editing repository

+ +<%= render "form", repository: @repository %> + +
+ +
+ <%= link_to "Show this repository", @repository %> | + <%= link_to "Back to repositories", repositories_path %> +
diff --git a/app/views/repositories/index.html.erb b/app/views/repositories/index.html.erb new file mode 100644 index 0000000000..5d7ad9ddaa --- /dev/null +++ b/app/views/repositories/index.html.erb @@ -0,0 +1,14 @@ +

<%= notice %>

+ +

Repositories

+ +
+ <% @repositories.each do |repository| %> + <%= render repository %> +

+ <%= link_to "Show this repository", repository %> +

+ <% end %> +
+ +<%= link_to "New repository", new_repository_path %> diff --git a/app/views/repositories/index.json.jbuilder b/app/views/repositories/index.json.jbuilder new file mode 100644 index 0000000000..1dca2fe40d --- /dev/null +++ b/app/views/repositories/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @repositories, partial: "repositories/repository", as: :repository diff --git a/app/views/repositories/new.html.erb b/app/views/repositories/new.html.erb new file mode 100644 index 0000000000..4d3442e8f2 --- /dev/null +++ b/app/views/repositories/new.html.erb @@ -0,0 +1,9 @@ +

New repository

+ +<%= render "form", repository: @repository %> + +
+ +
+ <%= link_to "Back to repositories", repositories_path %> +
diff --git a/app/views/repositories/show.html.erb b/app/views/repositories/show.html.erb new file mode 100644 index 0000000000..248abb1e42 --- /dev/null +++ b/app/views/repositories/show.html.erb @@ -0,0 +1,10 @@ +

<%= notice %>

+ +<%= render @repository %> + +
+ <%= link_to "Edit this repository", edit_repository_path(@repository) %> | + <%= link_to "Back to repositories", repositories_path %> + + <%= button_to "Destroy this repository", @repository, method: :delete %> +
diff --git a/app/views/repositories/show.json.jbuilder b/app/views/repositories/show.json.jbuilder new file mode 100644 index 0000000000..bf3991441e --- /dev/null +++ b/app/views/repositories/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "repositories/repository", repository: @repository diff --git a/config/routes.rb b/config/routes.rb index cc3ce617ff..152f551317 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + resources :repositories resources :languages, param: :slug # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html diff --git a/db/migrate/20230112012548_create_repositories.rb b/db/migrate/20230112012548_create_repositories.rb new file mode 100644 index 0000000000..f55cc25904 --- /dev/null +++ b/db/migrate/20230112012548_create_repositories.rb @@ -0,0 +1,22 @@ +class CreateRepositories < ActiveRecord::Migration[7.0] + def change + create_table :repositories do |t| + t.string :name + t.text :description + t.string :node_id + t.integer :github_id + t.string :full_name + t.integer :stars + t.string :url + t.integer :forks + t.integer :open_issues + t.string :license + t.datetime :origin_created_at + t.string :origin_updated_at + t.string :topics, array: true, default: [] + t.references :language, null: false, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 024cc13da4..0e39152d74 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_01_11_222750) do +ActiveRecord::Schema[7.0].define(version: 2023_01_12_012548) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -21,4 +21,25 @@ t.string "slug", default: "", null: false end + create_table "repositories", force: :cascade do |t| + t.string "name" + t.text "description" + t.string "node_id" + t.integer "github_id" + t.string "full_name" + t.integer "stars" + t.string "url" + t.integer "forks" + t.integer "open_issues" + t.string "license" + t.datetime "origin_created_at" + t.string "origin_updated_at" + t.string "topics", default: [], array: true + t.bigint "language_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["language_id"], name: "index_repositories_on_language_id" + end + + add_foreign_key "repositories", "languages" end diff --git a/test/controllers/repositories_controller_test.rb b/test/controllers/repositories_controller_test.rb new file mode 100644 index 0000000000..285eb6ed11 --- /dev/null +++ b/test/controllers/repositories_controller_test.rb @@ -0,0 +1,48 @@ +require "test_helper" + +class RepositoriesControllerTest < ActionDispatch::IntegrationTest + setup do + @repository = repositories(:one) + end + + test "should get index" do + get repositories_url + assert_response :success + end + + test "should get new" do + get new_repository_url + assert_response :success + end + + test "should create repository" do + assert_difference("Repository.count") do + post repositories_url, params: { repository: { forks: @repository.forks, full_name: @repository.full_name, github_id: @repository.github_id, language_id: @repository.language_id, license: @repository.license, name: @repository.name, node_id: @repository.node_id, open_issues: @repository.open_issues, origin_created_at: @repository.origin_created_at, origin_updated: @repository.origin_updated, stars: @repository.stars, topics: @repository.topics, url: @repository.url } } + end + + assert_redirected_to repository_url(Repository.last) + end + + test "should show repository" do + get repository_url(@repository) + assert_response :success + end + + test "should get edit" do + get edit_repository_url(@repository) + assert_response :success + end + + test "should update repository" do + patch repository_url(@repository), params: { repository: { forks: @repository.forks, full_name: @repository.full_name, github_id: @repository.github_id, language_id: @repository.language_id, license: @repository.license, name: @repository.name, node_id: @repository.node_id, open_issues: @repository.open_issues, origin_created_at: @repository.origin_created_at, origin_updated: @repository.origin_updated, stars: @repository.stars, topics: @repository.topics, url: @repository.url } } + assert_redirected_to repository_url(@repository) + end + + test "should destroy repository" do + assert_difference("Repository.count", -1) do + delete repository_url(@repository) + end + + assert_redirected_to repositories_url + end +end diff --git a/test/fixtures/repositories.yml b/test/fixtures/repositories.yml new file mode 100644 index 0000000000..2fe139520b --- /dev/null +++ b/test/fixtures/repositories.yml @@ -0,0 +1,31 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + node_id: MyString + github_id: 1 + full_name: MyString + stars: 1 + url: MyString + forks: 1 + open_issues: 1 + license: MyString + origin_created_at: 2023-01-12 01:25:48 + origin_updated: MyString + topics: MyText + language: one + +two: + name: MyString + node_id: MyString + github_id: 1 + full_name: MyString + stars: 1 + url: MyString + forks: 1 + open_issues: 1 + license: MyString + origin_created_at: 2023-01-12 01:25:48 + origin_updated: MyString + topics: MyText + language: two diff --git a/test/models/repository_test.rb b/test/models/repository_test.rb new file mode 100644 index 0000000000..5c44b00ea5 --- /dev/null +++ b/test/models/repository_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class RepositoryTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/system/repositories_test.rb b/test/system/repositories_test.rb new file mode 100644 index 0000000000..344144371e --- /dev/null +++ b/test/system/repositories_test.rb @@ -0,0 +1,65 @@ +require "application_system_test_case" + +class RepositoriesTest < ApplicationSystemTestCase + setup do + @repository = repositories(:one) + end + + test "visiting the index" do + visit repositories_url + assert_selector "h1", text: "Repositories" + end + + test "should create repository" do + visit repositories_url + click_on "New repository" + + fill_in "Forks", with: @repository.forks + fill_in "Full name", with: @repository.full_name + fill_in "Github", with: @repository.github_id + fill_in "Language", with: @repository.language_id + fill_in "License", with: @repository.license + fill_in "Name", with: @repository.name + fill_in "Node", with: @repository.node_id + fill_in "Open issues", with: @repository.open_issues + fill_in "Origin created at", with: @repository.origin_created_at + fill_in "Origin updated", with: @repository.origin_updated + fill_in "Stars", with: @repository.stars + fill_in "Topics", with: @repository.topics + fill_in "Url", with: @repository.url + click_on "Create Repository" + + assert_text "Repository was successfully created" + click_on "Back" + end + + test "should update Repository" do + visit repository_url(@repository) + click_on "Edit this repository", match: :first + + fill_in "Forks", with: @repository.forks + fill_in "Full name", with: @repository.full_name + fill_in "Github", with: @repository.github_id + fill_in "Language", with: @repository.language_id + fill_in "License", with: @repository.license + fill_in "Name", with: @repository.name + fill_in "Node", with: @repository.node_id + fill_in "Open issues", with: @repository.open_issues + fill_in "Origin created at", with: @repository.origin_created_at + fill_in "Origin updated", with: @repository.origin_updated + fill_in "Stars", with: @repository.stars + fill_in "Topics", with: @repository.topics + fill_in "Url", with: @repository.url + click_on "Update Repository" + + assert_text "Repository was successfully updated" + click_on "Back" + end + + test "should destroy Repository" do + visit repository_url(@repository) + click_on "Destroy this repository", match: :first + + assert_text "Repository was successfully destroyed" + end +end From a0caeac1bd470075b3a4551b13196b6693012579 Mon Sep 17 00:00:00 2001 From: bielzin Date: Wed, 11 Jan 2023 23:11:44 -0300 Subject: [PATCH 04/33] adds association to language --- app/models/language.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/language.rb b/app/models/language.rb index f03e25a96e..d1c3394899 100644 --- a/app/models/language.rb +++ b/app/models/language.rb @@ -1,5 +1,6 @@ class Language < ApplicationRecord before_validation :add_slug + has_many :repositories def add_slug self.slug = name.parameterize From 77c0bbc49d47616b3879258cce0e2dc8fb836fea Mon Sep 17 00:00:00 2001 From: bielzin Date: Wed, 11 Jan 2023 23:12:25 -0300 Subject: [PATCH 05/33] fix mistyped attribute --- app/views/repositories/_form.html.erb | 4 ++-- app/views/repositories/_repository.html.erb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/repositories/_form.html.erb b/app/views/repositories/_form.html.erb index 2f7f8d8ec8..c6b38f09a2 100644 --- a/app/views/repositories/_form.html.erb +++ b/app/views/repositories/_form.html.erb @@ -62,8 +62,8 @@
- <%= form.label :origin_updated, style: "display: block" %> - <%= form.text_field :origin_updated %> + <%= form.label :origin_updated_at, style: "display: block" %> + <%= form.text_field :origin_updated_at %>
diff --git a/app/views/repositories/_repository.html.erb b/app/views/repositories/_repository.html.erb index 1c66dc92e9..e4c23008e9 100644 --- a/app/views/repositories/_repository.html.erb +++ b/app/views/repositories/_repository.html.erb @@ -51,7 +51,7 @@

Origin updated: - <%= repository.origin_updated %> + <%= repository.origin_updated_at %>

@@ -61,7 +61,7 @@

Language: - <%= repository.language_id %> + <%= repository.language.name %>

From 38cf8c96a5619173a84b9c21f7d7d6971d795c4d Mon Sep 17 00:00:00 2001 From: bielzin Date: Thu, 12 Jan 2023 23:22:04 -0300 Subject: [PATCH 06/33] gets data from github api and save in database --- Gemfile | 2 + Gemfile.lock | 5 +++ app/controllers/results_controller.rb | 40 +++++++++++++++++++ app/views/languages/show.html.erb | 1 + app/views/results/index.html.erb | 5 +++ config/routes.rb | 1 + ...0230113021006_add_index_to_repositories.rb | 5 +++ db/schema.rb | 3 +- 8 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 app/controllers/results_controller.rb create mode 100644 app/views/results/index.html.erb create mode 100644 db/migrate/20230113021006_add_index_to_repositories.rb diff --git a/Gemfile b/Gemfile index 4e19311185..6a50698704 100644 --- a/Gemfile +++ b/Gemfile @@ -48,6 +48,8 @@ gem "bootsnap", require: false # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] # gem "image_processing", "~> 1.2" +gem "httparty" + group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem "debug", platforms: %i[ mri mingw x64_mingw ] diff --git a/Gemfile.lock b/Gemfile.lock index f53ac98f84..7ca8d7b25b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,6 +94,9 @@ GEM erubi (1.12.0) globalid (1.0.0) activesupport (>= 5.0) + httparty (0.21.0) + mini_mime (>= 1.0.0) + multi_xml (>= 0.5.2) i18n (1.12.0) concurrent-ruby (~> 1.0) importmap-rails (1.1.5) @@ -119,6 +122,7 @@ GEM mini_mime (1.1.2) minitest (5.17.0) msgpack (1.6.0) + multi_xml (0.6.0) net-imap (0.3.4) date net-protocol @@ -217,6 +221,7 @@ DEPENDENCIES capybara debug dotenv-rails + httparty importmap-rails jbuilder pg (~> 1.1) diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb new file mode 100644 index 0000000000..bf88d8c343 --- /dev/null +++ b/app/controllers/results_controller.rb @@ -0,0 +1,40 @@ +require 'uri' +require 'httparty' + +class ResultsController < ApplicationController + def index + @languages = Language.all + @result = @languages.map do |language| + uri = URI.parse("https://api.github.com/search/repositories?q=#{language.name}&per_page=1") + res = HTTParty.get(uri, { + headers: { + "User-Agent" => "Httparty", + "Authorization" => ENV['GITHUB_TOKEN'] + } + }) + res_body_json = ActiveSupport::JSON.decode(res.body) + repository = res_body_json['items'][0] + begin + new_repository = Repository.new( + name: repository['name'], + description: repository['description'], + node_id: repository['node_id'], + github_id: repository['id'], + full_name: repository['full_name'], + stars: repository['stargazers_count'], + url: repository['html_url'], + forks: repository['forks_count'], + open_issues: repository['open_issues'], + license: repository['license']['name'], + origin_created_at: DateTime.parse(repository['created_at']), + origin_updated_at: DateTime.parse(repository['updated_at']), + topics: repository['topics'], + language: language + ) + new_repository.save! + rescue => exception + Repository.find_by(github_id: repository['id']) + end + end + end +end diff --git a/app/views/languages/show.html.erb b/app/views/languages/show.html.erb index a7cf28ab13..f901bff3e0 100644 --- a/app/views/languages/show.html.erb +++ b/app/views/languages/show.html.erb @@ -1,6 +1,7 @@

<%= notice %>

<%= render @language %> +<%= render @language.repositories %>
<%= link_to "Edit this language", edit_language_path(@language) %> | diff --git a/app/views/results/index.html.erb b/app/views/results/index.html.erb new file mode 100644 index 0000000000..3ebac6e51b --- /dev/null +++ b/app/views/results/index.html.erb @@ -0,0 +1,5 @@ +

funcionou

+<% @result.each do |repo| %> + Name: <%= repo['name'] %>
+ Name: <%= repo['full_name'] %>
+<% end %> diff --git a/config/routes.rb b/config/routes.rb index 152f551317..be20602e8b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ Rails.application.routes.draw do resources :repositories resources :languages, param: :slug + get 'results', to: 'results#index' # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Defines the root path route ("/") diff --git a/db/migrate/20230113021006_add_index_to_repositories.rb b/db/migrate/20230113021006_add_index_to_repositories.rb new file mode 100644 index 0000000000..be247e46fb --- /dev/null +++ b/db/migrate/20230113021006_add_index_to_repositories.rb @@ -0,0 +1,5 @@ +class AddIndexToRepositories < ActiveRecord::Migration[7.0] + def change + add_index :repositories, :github_id, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 0e39152d74..a4832d027b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_01_12_012548) do +ActiveRecord::Schema[7.0].define(version: 2023_01_13_021006) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -38,6 +38,7 @@ t.bigint "language_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["github_id"], name: "index_repositories_on_github_id", unique: true t.index ["language_id"], name: "index_repositories_on_language_id" end From d74ae541775ba6db41c53f97459b4317a3affbe3 Mon Sep 17 00:00:00 2001 From: bielzin Date: Thu, 12 Jan 2023 23:29:44 -0300 Subject: [PATCH 07/33] adds more data to results page --- app/controllers/results_controller.rb | 3 +-- app/views/results/index.html.erb | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index bf88d8c343..b1f53b7b38 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -15,7 +15,7 @@ def index res_body_json = ActiveSupport::JSON.decode(res.body) repository = res_body_json['items'][0] begin - new_repository = Repository.new( + new_repository = Repository.create!( name: repository['name'], description: repository['description'], node_id: repository['node_id'], @@ -31,7 +31,6 @@ def index topics: repository['topics'], language: language ) - new_repository.save! rescue => exception Repository.find_by(github_id: repository['id']) end diff --git a/app/views/results/index.html.erb b/app/views/results/index.html.erb index 3ebac6e51b..2ba83974df 100644 --- a/app/views/results/index.html.erb +++ b/app/views/results/index.html.erb @@ -1,5 +1,8 @@ -

funcionou

<% @result.each do |repo| %> Name: <%= repo['name'] %>
- Name: <%= repo['full_name'] %>
+ Full name: <%= repo['full_name'] %>
+ Stars: <%= repo['stars'] %>
+ Forks: <%= repo['forks'] %>
+ Url: <%= link_to "repo url", repo['url'] %>
+
<% end %> From 101946523fb1c4509c1c4940a1c0c044601e2129 Mon Sep 17 00:00:00 2001 From: bielzin Date: Thu, 12 Jan 2023 23:55:59 -0300 Subject: [PATCH 08/33] removes bracket notation and change api url --- app/controllers/results_controller.rb | 4 ++-- app/views/results/index.html.erb | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index b1f53b7b38..3db3b924ea 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -4,8 +4,8 @@ class ResultsController < ApplicationController def index @languages = Language.all - @result = @languages.map do |language| - uri = URI.parse("https://api.github.com/search/repositories?q=#{language.name}&per_page=1") + @results = @languages.map do |language| + uri = URI.parse("https://api.github.com/search/repositories?q=language:#{language.name}&per_page=1") res = HTTParty.get(uri, { headers: { "User-Agent" => "Httparty", diff --git a/app/views/results/index.html.erb b/app/views/results/index.html.erb index 2ba83974df..b7a32400ad 100644 --- a/app/views/results/index.html.erb +++ b/app/views/results/index.html.erb @@ -1,8 +1,9 @@ -<% @result.each do |repo| %> - Name: <%= repo['name'] %>
- Full name: <%= repo['full_name'] %>
- Stars: <%= repo['stars'] %>
- Forks: <%= repo['forks'] %>
- Url: <%= link_to "repo url", repo['url'] %>
+<% @results.each do |repo| %> + Name: <%= repo.name %>
+ Full name: <%= repo.full_name %>
+ Stars: <%= repo.stars %>
+ Forks: <%= repo.forks %>
+ Url: <%= link_to "repo url", repo.url, target: :_blank %>
+ Language: <%= link_to "#{repo.language.name}", language_path(repo.language) %>

<% end %> From b04a5a745d88dae7c328791931475629e5f0685d Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 14:00:14 -0300 Subject: [PATCH 09/33] removes unecessary code and files --- app/controllers/languages_controller.rb | 27 ------------- app/controllers/repositories_controller.rb | 47 ---------------------- app/views/languages/_form.html.erb | 22 ---------- app/views/languages/edit.html.erb | 10 ----- app/views/repositories/edit.html.erb | 10 ----- app/views/repositories/new.html.erb | 9 ----- 6 files changed, 125 deletions(-) delete mode 100644 app/views/languages/_form.html.erb delete mode 100644 app/views/languages/edit.html.erb delete mode 100644 app/views/repositories/edit.html.erb delete mode 100644 app/views/repositories/new.html.erb diff --git a/app/controllers/languages_controller.rb b/app/controllers/languages_controller.rb index a42fb17e6d..92bd2f5747 100644 --- a/app/controllers/languages_controller.rb +++ b/app/controllers/languages_controller.rb @@ -15,10 +15,6 @@ def new @language = Language.new end - # GET /languages/1/edit - def edit - end - # POST /languages or /languages.json def create @language = Language.new(language_params) @@ -34,29 +30,6 @@ def create end end - # PATCH/PUT /languages/1 or /languages/1.json - def update - respond_to do |format| - if @language.update(language_params) - format.html { redirect_to language_url(@language), notice: "Language was successfully updated." } - format.json { render :show, status: :ok, location: @language } - else - format.html { render :edit, status: :unprocessable_entity } - format.json { render json: @language.errors, status: :unprocessable_entity } - end - end - end - - # DELETE /languages/1 or /languages/1.json - def destroy - @language.destroy - - respond_to do |format| - format.html { redirect_to languages_url, notice: "Language was successfully destroyed." } - format.json { head :no_content } - end - end - private # Use callbacks to share common setup or constraints between actions. def set_language diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index d9f1072fcc..73de2aa550 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -10,53 +10,6 @@ def index def show end - # GET /repositories/new - def new - @repository = Repository.new - end - - # GET /repositories/1/edit - def edit - end - - # POST /repositories or /repositories.json - def create - @repository = Repository.new(repository_params) - - respond_to do |format| - if @repository.save - format.html { redirect_to repository_url(@repository), notice: "Repository was successfully created." } - format.json { render :show, status: :created, location: @repository } - else - format.html { render :new, status: :unprocessable_entity } - format.json { render json: @repository.errors, status: :unprocessable_entity } - end - end - end - - # PATCH/PUT /repositories/1 or /repositories/1.json - def update - respond_to do |format| - if @repository.update(repository_params) - format.html { redirect_to repository_url(@repository), notice: "Repository was successfully updated." } - format.json { render :show, status: :ok, location: @repository } - else - format.html { render :edit, status: :unprocessable_entity } - format.json { render json: @repository.errors, status: :unprocessable_entity } - end - end - end - - # DELETE /repositories/1 or /repositories/1.json - def destroy - @repository.destroy - - respond_to do |format| - format.html { redirect_to repositories_url, notice: "Repository was successfully destroyed." } - format.json { head :no_content } - end - end - private # Use callbacks to share common setup or constraints between actions. def set_repository diff --git a/app/views/languages/_form.html.erb b/app/views/languages/_form.html.erb deleted file mode 100644 index c69ac33bf5..0000000000 --- a/app/views/languages/_form.html.erb +++ /dev/null @@ -1,22 +0,0 @@ -<%= form_with(model: language) do |form| %> - <% if language.errors.any? %> -
-

<%= pluralize(language.errors.count, "error") %> prohibited this language from being saved:

- -
    - <% language.errors.each do |error| %> -
  • <%= error.full_message %>
  • - <% end %> -
-
- <% end %> - -
- <%= form.label :name, style: "display: block" %> - <%= form.text_field :name %> -
- -
- <%= form.submit %> -
-<% end %> diff --git a/app/views/languages/edit.html.erb b/app/views/languages/edit.html.erb deleted file mode 100644 index 1c5c9900bf..0000000000 --- a/app/views/languages/edit.html.erb +++ /dev/null @@ -1,10 +0,0 @@ -

Editing language

- -<%= render "form", language: @language %> - -
- -
- <%= link_to "Show this language", @language %> | - <%= link_to "Back to languages", languages_path %> -
diff --git a/app/views/repositories/edit.html.erb b/app/views/repositories/edit.html.erb deleted file mode 100644 index c85cbbf66b..0000000000 --- a/app/views/repositories/edit.html.erb +++ /dev/null @@ -1,10 +0,0 @@ -

Editing repository

- -<%= render "form", repository: @repository %> - -
- -
- <%= link_to "Show this repository", @repository %> | - <%= link_to "Back to repositories", repositories_path %> -
diff --git a/app/views/repositories/new.html.erb b/app/views/repositories/new.html.erb deleted file mode 100644 index 4d3442e8f2..0000000000 --- a/app/views/repositories/new.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -

New repository

- -<%= render "form", repository: @repository %> - -
- -
- <%= link_to "Back to repositories", repositories_path %> -
From b14b56b27cf045a633d6330cdf891c3ae478a23e Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 14:01:01 -0300 Subject: [PATCH 10/33] adds tailwindcss --- .gitignore | 3 +++ Gemfile | 3 +++ Procfile.dev | 2 ++ app/assets/builds/.keep | 0 app/assets/config/manifest.js | 1 + .../stylesheets/application.tailwind.css | 13 ++++++++++ app/views/layouts/application.html.erb | 5 +++- bin/dev | 8 ++++++ config/tailwind.config.js | 25 +++++++++++++++++++ 9 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 Procfile.dev create mode 100644 app/assets/builds/.keep create mode 100644 app/assets/stylesheets/application.tailwind.css create mode 100755 bin/dev create mode 100644 config/tailwind.config.js diff --git a/.gitignore b/.gitignore index 2f4b643a82..17c7b0da77 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ # Ignore .env file .env + +/app/assets/builds/* +!/app/assets/builds/.keep diff --git a/Gemfile b/Gemfile index 6a50698704..bac6b80d7e 100644 --- a/Gemfile +++ b/Gemfile @@ -54,6 +54,7 @@ group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem "debug", platforms: %i[ mri mingw x64_mingw ] gem "dotenv-rails" + gem 'rspec-rails', '~> 6.0.0' end group :development do @@ -73,3 +74,5 @@ group :test do gem "selenium-webdriver" gem "webdrivers" end + +gem "tailwindcss-rails", "~> 2.0" diff --git a/Procfile.dev b/Procfile.dev new file mode 100644 index 0000000000..023e98a019 --- /dev/null +++ b/Procfile.dev @@ -0,0 +1,2 @@ +web: bin/rails server -p 3000 +css: bin/rails tailwindcss:watch diff --git a/app/assets/builds/.keep b/app/assets/builds/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index 591819335f..338a0e8266 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -1,2 +1,3 @@ //= link_tree ../images //= link_directory ../stylesheets .css +//= link_tree ../builds diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css new file mode 100644 index 0000000000..8666d2f3c6 --- /dev/null +++ b/app/assets/stylesheets/application.tailwind.css @@ -0,0 +1,13 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* + +@layer components { + .btn-primary { + @apply py-2 px-4 bg-blue-200; + } +} + +*/ diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 55e16a8038..b486953d03 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -5,11 +5,14 @@ <%= csrf_meta_tags %> <%= csp_meta_tag %> + <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> - <%= yield %> +
+ <%= yield %> +
diff --git a/bin/dev b/bin/dev new file mode 100755 index 0000000000..74ade16641 --- /dev/null +++ b/bin/dev @@ -0,0 +1,8 @@ +#!/usr/bin/env sh + +if ! gem list foreman -i --silent; then + echo "Installing foreman..." + gem install foreman +fi + +exec foreman start -f Procfile.dev "$@" diff --git a/config/tailwind.config.js b/config/tailwind.config.js new file mode 100644 index 0000000000..e411d20a8f --- /dev/null +++ b/config/tailwind.config.js @@ -0,0 +1,25 @@ +const defaultTheme = require("tailwindcss/defaultTheme"); + +module.exports = { + content: [ + "./public/*.html", + "./app/helpers/**/*.rb", + "./app/javascript/**/*.js", + "./app/views/**/*.{erb,haml,html,slim}", + "./app/helpers/**/*.rb", + "./app/javascript/**/*.js", + "./app/views/**/*", + ], + theme: { + extend: { + fontFamily: { + sans: ["Inter var", ...defaultTheme.fontFamily.sans], + }, + }, + }, + plugins: [ + require("@tailwindcss/forms"), + require("@tailwindcss/aspect-ratio"), + require("@tailwindcss/typography"), + ], +}; From 7c59638264aac0af2908be8db7a6b5c22b2aee4a Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 14:02:12 -0300 Subject: [PATCH 11/33] set app root route --- config/routes.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index be20602e8b..ddbcf11902 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,6 @@ Rails.application.routes.draw do + root "languages#index" resources :repositories resources :languages, param: :slug get 'results', to: 'results#index' - # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html - - # Defines the root path route ("/") - # root "articles#index" end From ae162d5d33d68020f36e5b1c4e49258017f9cfb9 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 14:02:40 -0300 Subject: [PATCH 12/33] adds not null constraint to language name column --- app/models/language.rb | 1 + ...0230114162107_add_not_null_constraint_to_language_name.rb | 5 +++++ db/schema.rb | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20230114162107_add_not_null_constraint_to_language_name.rb diff --git a/app/models/language.rb b/app/models/language.rb index d1c3394899..c59de52d52 100644 --- a/app/models/language.rb +++ b/app/models/language.rb @@ -1,6 +1,7 @@ class Language < ApplicationRecord before_validation :add_slug has_many :repositories + validates :name, :slug, presence: true def add_slug self.slug = name.parameterize diff --git a/db/migrate/20230114162107_add_not_null_constraint_to_language_name.rb b/db/migrate/20230114162107_add_not_null_constraint_to_language_name.rb new file mode 100644 index 0000000000..7b5d319eec --- /dev/null +++ b/db/migrate/20230114162107_add_not_null_constraint_to_language_name.rb @@ -0,0 +1,5 @@ +class AddNotNullConstraintToLanguageName < ActiveRecord::Migration[7.0] + def change + change_column_null :languages, :name, false + end +end diff --git a/db/schema.rb b/db/schema.rb index a4832d027b..133c58c7b9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,12 +10,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_01_13_021006) do +ActiveRecord::Schema[7.0].define(version: 2023_01_14_162107) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" create_table "languages", force: :cascade do |t| - t.string "name" + t.string "name", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "slug", default: "", null: false From 1e4276d375568f2203e3e92524cc200698e5f9cd Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 14:03:40 -0300 Subject: [PATCH 13/33] adds rspec and language model test --- .rspec | 1 + Gemfile.lock | 22 +++++++++ spec/models/language_spec.rb | 31 ++++++++++++ spec/rails_helper.rb | 63 ++++++++++++++++++++++++ spec/spec_helper.rb | 94 ++++++++++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+) create mode 100644 .rspec create mode 100644 spec/models/language_spec.rb create mode 100644 spec/rails_helper.rb create mode 100644 spec/spec_helper.rb diff --git a/.rspec b/.rspec new file mode 100644 index 0000000000..c99d2e7396 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/Gemfile.lock b/Gemfile.lock index 7ca8d7b25b..fa7ac221de 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -87,6 +87,7 @@ GEM debug (1.7.1) irb (>= 1.5.0) reline (>= 0.3.1) + diff-lcs (1.5.0) dotenv (2.8.1) dotenv-rails (2.8.1) dotenv (= 2.8.1) @@ -174,6 +175,23 @@ GEM reline (0.3.2) io-console (~> 0.5) rexml (3.2.5) + rspec-core (3.12.0) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-rails (6.0.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.11) + rspec-expectations (~> 3.11) + rspec-mocks (~> 3.11) + rspec-support (~> 3.11) + rspec-support (3.12.0) rubyzip (2.3.2) selenium-webdriver (4.7.1) rexml (~> 3.2, >= 3.2.5) @@ -188,6 +206,8 @@ GEM sprockets (>= 3.0.0) stimulus-rails (1.2.1) railties (>= 6.0.0) + tailwindcss-rails (2.0.21-x86_64-linux) + railties (>= 6.0.0) thor (1.2.1) timeout (0.3.1) turbo-rails (1.3.2) @@ -227,9 +247,11 @@ DEPENDENCIES pg (~> 1.1) puma (~> 5.0) rails (~> 7.0.4) + rspec-rails (~> 6.0.0) selenium-webdriver sprockets-rails stimulus-rails + tailwindcss-rails (~> 2.0) turbo-rails tzinfo-data web-console diff --git a/spec/models/language_spec.rb b/spec/models/language_spec.rb new file mode 100644 index 0000000000..8467898f24 --- /dev/null +++ b/spec/models/language_spec.rb @@ -0,0 +1,31 @@ +require 'rails_helper' + +RSpec.describe Language, type: :model do + context 'with blank name on creation' do + it 'raises RecordInvalid' do + expect { Language.create!(name: '') }.to raise_error(ActiveRecord::RecordInvalid) + end + end + + context 'with no parameters on creation' do + it 'raises NoMethodError' do + expect { Language.create!() }.to raise_error(NoMethodError) + end + end + + context 'when name is not null or empty' do + it 'creates language properly' do + language = Language.create!(name: 'javascript') + expect(language.name).to eq('javascript') + expect(language.slug).to eq('javascript') + end + end + + context 'when the language name has more than 1 word' do + it 'creates language properly and slug separate words with hyphen' do + language = Language.create!(name: 'language name') + expect(language.name).to eq('language name') + expect(language.slug).to eq('language-name') + end + end +end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 0000000000..a53bdba2a5 --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,63 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +require 'spec_helper' +ENV['RAILS_ENV'] ||= 'test' +require_relative '../config/environment' +# Prevent database truncation if the environment is production +abort("The Rails environment is running in production mode!") if Rails.env.production? +require 'rspec/rails' +# Add additional requires below this line. Rails is not loaded until this point! + +# Requires supporting ruby files with custom matchers and macros, etc, in +# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are +# run as spec files by default. This means that files in spec/support that end +# in _spec.rb will both be required and run as specs, causing the specs to be +# run twice. It is recommended that you do not name files matching this glob to +# end with _spec.rb. You can configure this pattern with the --pattern +# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. +# +# The following line is provided for convenience purposes. It has the downside +# of increasing the boot-up time by auto-requiring all files in the support +# directory. Alternatively, in the individual `*_spec.rb` files, manually +# require only the support files necessary. +# +# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } + +# Checks for pending migrations and applies them before tests are run. +# If you are not using ActiveRecord, you can remove these lines. +begin + ActiveRecord::Migration.maintain_test_schema! +rescue ActiveRecord::PendingMigrationError => e + abort e.to_s.strip +end +RSpec.configure do |config| + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # You can uncomment this line to turn off ActiveRecord support entirely. + # config.use_active_record = false + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, type: :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! + + # Filter lines from Rails gems in backtraces. + config.filter_rails_from_backtrace! + # arbitrary gems may also be filtered via: + # config.filter_gems_from_backtrace("gem name") +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000000..a0d4080592 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,94 @@ +# This file was generated by the `rails generate rspec:install` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode + config.disable_monkey_patching! + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end From 141d71a87a7001eb77ba6c00e155aaa5ce899997 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 14:04:11 -0300 Subject: [PATCH 14/33] adds style to languages index and link to repo details --- app/views/languages/index.html.erb | 26 +++++++++++++------------- app/views/results/index.html.erb | 1 + 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/app/views/languages/index.html.erb b/app/views/languages/index.html.erb index c8383c6fde..c577275771 100644 --- a/app/views/languages/index.html.erb +++ b/app/views/languages/index.html.erb @@ -1,14 +1,14 @@ -

<%= notice %>

- -

Languages

- -
- <% @languages.each do |language| %> - <%= render language %> -

- <%= link_to "Show this language", language %> -

- <% end %> +
+

+ Languages +

+
+ <% @languages.each do |language| %> +
+
<%= language.name.capitalize %>
+ <%= link_to 'Repositories saved '.html_safe, language, { :class => "inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300"} %> +
+ <% end %> +
+ <%= link_to "Find new repos", results_path, {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300"} %>
- -<%= link_to "New language", new_language_path %> diff --git a/app/views/results/index.html.erb b/app/views/results/index.html.erb index b7a32400ad..d7c3483eb3 100644 --- a/app/views/results/index.html.erb +++ b/app/views/results/index.html.erb @@ -5,5 +5,6 @@ Forks: <%= repo.forks %>
Url: <%= link_to "repo url", repo.url, target: :_blank %>
Language: <%= link_to "#{repo.language.name}", language_path(repo.language) %>
+ <%= link_to "Check all details of the repo", repository_path(repo) %>

<% end %> From 5bbccc593f819c7b74a81a425bdfef761d974c6d Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 17:59:57 -0300 Subject: [PATCH 15/33] finish styling application --- app/views/languages/index.html.erb | 2 +- app/views/languages/show.html.erb | 35 +++++++++++++++++--------- app/views/repositories/show.html.erb | 30 +++++++++++++++------- app/views/results/index.html.erb | 37 ++++++++++++++++++++-------- 4 files changed, 73 insertions(+), 31 deletions(-) diff --git a/app/views/languages/index.html.erb b/app/views/languages/index.html.erb index c577275771..331c4af526 100644 --- a/app/views/languages/index.html.erb +++ b/app/views/languages/index.html.erb @@ -10,5 +10,5 @@
<% end %>
- <%= link_to "Find new repos", results_path, {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300"} %> + <%= link_to "Search repos", results_path, {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300"} %> diff --git a/app/views/languages/show.html.erb b/app/views/languages/show.html.erb index f901bff3e0..13e80b462d 100644 --- a/app/views/languages/show.html.erb +++ b/app/views/languages/show.html.erb @@ -1,11 +1,24 @@ -

<%= notice %>

- -<%= render @language %> -<%= render @language.repositories %> - -
- <%= link_to "Edit this language", edit_language_path(@language) %> | - <%= link_to "Back to languages", languages_path %> - - <%= button_to "Destroy this language", @language, method: :delete %> -
+
+

<%= @language.name.capitalize %>

+
+ <% @language.repositories.each do |repo| %> +
+

<%= repo.name %>

+

+ Full name: <%= repo.full_name.truncate(45) %> +

+

+ Stars: <%= repo.stars %> +

+

+ Forks: <%= repo.forks %> +

+

+ <%= link_to "Github Repository", repo.url, target: :_blank %> +

+ <%= link_to "Check all repository's details", repository_path(repo), {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300 absolute left-0 right-0 w-[260px] bottom-4 mx-auto"} %> +
+ <% end %> +
+ <%= link_to "Back to Home", languages_path, {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300"} %> +
diff --git a/app/views/repositories/show.html.erb b/app/views/repositories/show.html.erb index 248abb1e42..965ebbf8ac 100644 --- a/app/views/repositories/show.html.erb +++ b/app/views/repositories/show.html.erb @@ -1,10 +1,22 @@ -

<%= notice %>

- -<%= render @repository %> - -
- <%= link_to "Edit this repository", edit_repository_path(@repository) %> | - <%= link_to "Back to repositories", repositories_path %> - - <%= button_to "Destroy this repository", @repository, method: :delete %> +
+
<%= @repository.name %>
+

Full name: <%= @repository.full_name %>

+

Description: <%= @repository.description %>

+

Stars: <%= @repository.stars %>

+

Open issues: <%= @repository.open_issues %>

+

Forks: <%= @repository.forks %>

+ <% if @repository.license != nil %> +

License: <%= @repository.license %>

+ <% end %> + <% if @repository.topics.length() > 0 %> +

Topics: <%= @repository.topics.join(", ")%>

+ <% end %> +

Created at: <%= @repository.origin_created_at %>

+

Last update: <%= @repository.origin_updated_at %>

+

+ <%= link_to "Github Repository", @repository.url, target: :_blank %> +

+

+ Language: <%= link_to "#{@repository.language.name.capitalize}", language_path(@repository.language), {:class => "font-bold hover:text-white duration-300"} %> +

diff --git a/app/views/results/index.html.erb b/app/views/results/index.html.erb index d7c3483eb3..a4fc69aa3a 100644 --- a/app/views/results/index.html.erb +++ b/app/views/results/index.html.erb @@ -1,10 +1,27 @@ -<% @results.each do |repo| %> - Name: <%= repo.name %>
- Full name: <%= repo.full_name %>
- Stars: <%= repo.stars %>
- Forks: <%= repo.forks %>
- Url: <%= link_to "repo url", repo.url, target: :_blank %>
- Language: <%= link_to "#{repo.language.name}", language_path(repo.language) %>
- <%= link_to "Check all details of the repo", repository_path(repo) %>
-
-<% end %> +
+

Results

+
+ <% @results.each do |repo| %> +
+

<%= repo.name %>

+

+ Full name: <%= repo.full_name.truncate(45) %> +

+

+ Stars: <%= repo.stars %> +

+

+ Forks: <%= repo.forks %> +

+

+ Language: <%= repo.language.name.capitalize %> +

+

+ <%= link_to "Github Repository", repo.url, target: :_blank %> +

+ <%= link_to "Check all repository's details", repository_path(repo), {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300 absolute left-0 right-0 w-[260px] bottom-4 mx-auto"} %> +
+ <% end %> +
+ <%= link_to "Back to Home", languages_path, {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300"} %> +
From bfdb0daca422011baaae88cc6a055369608cb8d5 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 18:01:40 -0300 Subject: [PATCH 16/33] removes unnecessaryy code and change routes --- app/controllers/languages_controller.rb | 22 +-------- app/controllers/repositories_controller.rb | 7 +-- app/controllers/results_controller.rb | 52 ++++++++++++++-------- config/routes.rb | 4 +- 4 files changed, 37 insertions(+), 48 deletions(-) diff --git a/app/controllers/languages_controller.rb b/app/controllers/languages_controller.rb index 92bd2f5747..e7e7287c99 100644 --- a/app/controllers/languages_controller.rb +++ b/app/controllers/languages_controller.rb @@ -1,5 +1,5 @@ class LanguagesController < ApplicationController - before_action :set_language, only: %i[ show edit update destroy ] + before_action :set_language, only: %i[ show ] # GET /languages or /languages.json def index @@ -10,26 +10,6 @@ def index def show end - # GET /languages/new - def new - @language = Language.new - end - - # POST /languages or /languages.json - def create - @language = Language.new(language_params) - - respond_to do |format| - if @language.save - format.html { redirect_to language_url(@language), notice: "Language was successfully created." } - format.json { render :show, status: :created, location: @language } - else - format.html { render :new, status: :unprocessable_entity } - format.json { render json: @language.errors, status: :unprocessable_entity } - end - end - end - private # Use callbacks to share common setup or constraints between actions. def set_language diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 73de2aa550..ef54b57980 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -1,10 +1,5 @@ class RepositoriesController < ApplicationController - before_action :set_repository, only: %i[ show edit update destroy ] - - # GET /repositories or /repositories.json - def index - @repositories = Repository.all - end + before_action :set_repository, only: %i[ show ] # GET /repositories/1 or /repositories/1.json def show diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index 3db3b924ea..25accedf72 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -5,6 +5,7 @@ class ResultsController < ApplicationController def index @languages = Language.all @results = @languages.map do |language| + puts "\naqui foi #{language.name}\n" uri = URI.parse("https://api.github.com/search/repositories?q=language:#{language.name}&per_page=1") res = HTTParty.get(uri, { headers: { @@ -12,28 +13,41 @@ def index "Authorization" => ENV['GITHUB_TOKEN'] } }) - res_body_json = ActiveSupport::JSON.decode(res.body) - repository = res_body_json['items'][0] + + if res.code == 200 + res_body_json = ActiveSupport::JSON.decode(res.body) + repository = res_body_json['items'][0] + else + return + end begin + new_repository = Repository.find_by(github_id: repository['id']) + puts "\n#{new_repository.name} repo existente\n" + new_repository + rescue => e + puts "\nrepo nao existente\n" new_repository = Repository.create!( - name: repository['name'], - description: repository['description'], - node_id: repository['node_id'], - github_id: repository['id'], - full_name: repository['full_name'], - stars: repository['stargazers_count'], - url: repository['html_url'], - forks: repository['forks_count'], - open_issues: repository['open_issues'], - license: repository['license']['name'], - origin_created_at: DateTime.parse(repository['created_at']), - origin_updated_at: DateTime.parse(repository['updated_at']), - topics: repository['topics'], - language: language - ) - rescue => exception - Repository.find_by(github_id: repository['id']) + name: repository['name'], + description: repository['description'], + node_id: repository['node_id'], + github_id: repository['id'], + full_name: repository['full_name'], + stars: repository['stargazers_count'], + url: repository['html_url'], + forks: repository['forks_count'], + open_issues: repository['open_issues'], + license: repository['license'] != nil ? repository['license']['name'] : nil, + origin_created_at: DateTime.parse(repository['created_at']), + origin_updated_at: DateTime.parse(repository['updated_at']), + topics: repository['topics'], + language: language + ) + puts "\nrepo adicionado\n" + new_repository end + new_repository end + puts "\n\n#{@results.length()}\n\n" + @results.compact.length() > 0 ? @results.compact : [] end end diff --git a/config/routes.rb b/config/routes.rb index ddbcf11902..5a84994923 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,6 @@ Rails.application.routes.draw do root "languages#index" - resources :repositories - resources :languages, param: :slug + resources :repositories, only: [:show] + resources :languages, param: :slug, only: [:show, :index] get 'results', to: 'results#index' end From e5e55839d2c1a9d1e816e16e6d1ec650c17cb4b6 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 18:51:43 -0300 Subject: [PATCH 17/33] adds languages controller test --- Gemfile | 1 + Gemfile.lock | 5 +++++ spec/requests/languages_spec.rb | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 spec/requests/languages_spec.rb diff --git a/Gemfile b/Gemfile index bac6b80d7e..9083bb6b33 100644 --- a/Gemfile +++ b/Gemfile @@ -76,3 +76,4 @@ group :test do end gem "tailwindcss-rails", "~> 2.0" +gem 'rails-controller-testing' diff --git a/Gemfile.lock b/Gemfile.lock index fa7ac221de..014c46b628 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -158,6 +158,10 @@ GEM activesupport (= 7.0.4) bundler (>= 1.15.0) railties (= 7.0.4) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) @@ -247,6 +251,7 @@ DEPENDENCIES pg (~> 1.1) puma (~> 5.0) rails (~> 7.0.4) + rails-controller-testing rspec-rails (~> 6.0.0) selenium-webdriver sprockets-rails diff --git a/spec/requests/languages_spec.rb b/spec/requests/languages_spec.rb new file mode 100644 index 0000000000..60aaa07a7e --- /dev/null +++ b/spec/requests/languages_spec.rb @@ -0,0 +1,30 @@ +require 'rails_helper' + +RSpec.describe "Languages", type: :request do + describe "GET /index" do + it 'should get all languages' do + language1 = Language.create!(name: 'javascript') + language2 = Language.create!(name: 'ruby') + get "/" + expect(assigns(:languages)).to eq([language1, language2]) + end + + it "renders the index template" do + get "/" + expect(response).to render_template(:index) + end + end + + describe "GET /show" do + it 'should get language by slug' do + language = Language.create!(name: 'javascript') + get "/languages/#{language.slug}" + expect(response).to render_template(:show) + end + + it 'should raise error if id is passed instead of slug' do + language = Language.create!(name: 'javascript') + expect { get "/languages/#{language.id}" }.to raise_error(StandardError) + end + end +end From 9586e3ba3f61664e0ce0c12b51927d3197b02d7a Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 19:00:02 -0300 Subject: [PATCH 18/33] adds tests to repositories#show --- spec/requests/languages_spec.rb | 6 ++-- spec/requests/repositories_spec.rb | 45 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 spec/requests/repositories_spec.rb diff --git a/spec/requests/languages_spec.rb b/spec/requests/languages_spec.rb index 60aaa07a7e..29383fa2d3 100644 --- a/spec/requests/languages_spec.rb +++ b/spec/requests/languages_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' RSpec.describe "Languages", type: :request do - describe "GET /index" do + describe "GET #index" do it 'should get all languages' do language1 = Language.create!(name: 'javascript') language2 = Language.create!(name: 'ruby') @@ -9,13 +9,13 @@ expect(assigns(:languages)).to eq([language1, language2]) end - it "renders the index template" do + it "renders the languages#index template" do get "/" expect(response).to render_template(:index) end end - describe "GET /show" do + describe "GET #show" do it 'should get language by slug' do language = Language.create!(name: 'javascript') get "/languages/#{language.slug}" diff --git a/spec/requests/repositories_spec.rb b/spec/requests/repositories_spec.rb new file mode 100644 index 0000000000..a55d14e1c7 --- /dev/null +++ b/spec/requests/repositories_spec.rb @@ -0,0 +1,45 @@ +require 'rails_helper' + +RSpec.describe "Repositories", type: :request do + describe "GET #show" do + it 'should render repositories#show template' do + language = Language.create!(name: 'python') + repository = Repository.create!( + name: "Python", + full_name: "TheAlgorithms/Python", + description: "All Algorithms implemented in Python", + stars: 0, + forks: 0, + open_issues: 0, + license: "license", + topics: [], + origin_created_at: DateTime.now, + origin_updated_at: DateTime.now, + url: "https://github.com/TheAlgorithms/Python", + language: language + ) + get "/repositories/#{repository.id}" + expect(response).to render_template(:show) + end + + it 'should get correct repository' do + language = Language.create!(name: 'python') + repository = Repository.create!( + name: "Python", + full_name: "TheAlgorithms/Python", + description: "All Algorithms implemented in Python", + stars: 0, + forks: 0, + open_issues: 0, + license: "license", + topics: [], + origin_created_at: DateTime.now, + origin_updated_at: DateTime.now, + url: "https://github.com/TheAlgorithms/Python", + language: language + ) + get "/repositories/#{repository.id}" + expect(assigns(:repository)).to eq(repository) + end + end +end From 086290e21de14624e8cbc54d24c6f2b507c34659 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 20:02:22 -0300 Subject: [PATCH 19/33] removes http call from controller to apimodel --- Gemfile | 3 +- Gemfile.lock | 30 ++++++++++ app/controllers/results_controller.rb | 57 ++++++------------- app/models/github_api_model.rb | 15 +++++ ...20230114224041_create_github_api_models.rb | 8 +++ db/schema.rb | 7 ++- spec/models/github_api_model_spec.rb | 5 ++ 7 files changed, 83 insertions(+), 42 deletions(-) create mode 100644 app/models/github_api_model.rb create mode 100644 db/migrate/20230114224041_create_github_api_models.rb create mode 100644 spec/models/github_api_model_spec.rb diff --git a/Gemfile b/Gemfile index 9083bb6b33..2d368863c5 100644 --- a/Gemfile +++ b/Gemfile @@ -48,8 +48,6 @@ gem "bootsnap", require: false # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] # gem "image_processing", "~> 1.2" -gem "httparty" - group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem "debug", platforms: %i[ mri mingw x64_mingw ] @@ -77,3 +75,4 @@ end gem "tailwindcss-rails", "~> 2.0" gem 'rails-controller-testing' +gem 'rest-client' diff --git a/Gemfile.lock b/Gemfile.lock index 014c46b628..b19431ce4a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -88,13 +88,22 @@ GEM irb (>= 1.5.0) reline (>= 0.3.1) diff-lcs (1.5.0) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) dotenv (2.8.1) dotenv-rails (2.8.1) dotenv (= 2.8.1) railties (>= 3.2) erubi (1.12.0) + faraday (2.7.2) + faraday-net_http (>= 2.0, < 3.1) + ruby2_keywords (>= 0.0.4) + faraday-net_http (3.0.2) globalid (1.0.0) activesupport (>= 5.0) + http-accept (1.7.0) + http-cookie (1.0.5) + domain_name (~> 0.5) httparty (0.21.0) mini_mime (>= 1.0.0) multi_xml (>= 0.5.2) @@ -120,6 +129,9 @@ GEM marcel (1.0.2) matrix (0.4.2) method_source (1.0.0) + mime-types (3.4.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2022.0105) mini_mime (1.1.2) minitest (5.17.0) msgpack (1.6.0) @@ -133,9 +145,13 @@ GEM timeout net-smtp (0.3.3) net-protocol + netrc (0.11.0) nio4r (2.5.8) nokogiri (1.13.10-x86_64-linux) racc (~> 1.4) + octokit (5.6.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) pg (1.4.5) public_suffix (5.0.1) puma (5.6.5) @@ -178,6 +194,11 @@ GEM regexp_parser (2.6.1) reline (0.3.2) io-console (~> 0.5) + rest-client (2.1.0) + http-accept (>= 1.7.0, < 2.0) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) rexml (3.2.5) rspec-core (3.12.0) rspec-support (~> 3.12.0) @@ -196,7 +217,11 @@ GEM rspec-mocks (~> 3.11) rspec-support (~> 3.11) rspec-support (3.12.0) + ruby2_keywords (0.0.5) rubyzip (2.3.2) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) selenium-webdriver (4.7.1) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) @@ -220,6 +245,9 @@ GEM railties (>= 6.0.0) tzinfo (2.0.5) concurrent-ruby (~> 1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) web-console (4.2.0) actionview (>= 6.0.0) activemodel (>= 6.0.0) @@ -248,10 +276,12 @@ DEPENDENCIES httparty importmap-rails jbuilder + octokit (~> 5.0) pg (~> 1.1) puma (~> 5.0) rails (~> 7.0.4) rails-controller-testing + rest-client rspec-rails (~> 6.0.0) selenium-webdriver sprockets-rails diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index 25accedf72..b38d58bc08 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -1,53 +1,32 @@ require 'uri' -require 'httparty' class ResultsController < ApplicationController def index @languages = Language.all @results = @languages.map do |language| - puts "\naqui foi #{language.name}\n" - uri = URI.parse("https://api.github.com/search/repositories?q=language:#{language.name}&per_page=1") - res = HTTParty.get(uri, { - headers: { - "User-Agent" => "Httparty", - "Authorization" => ENV['GITHUB_TOKEN'] - } - }) - - if res.code == 200 - res_body_json = ActiveSupport::JSON.decode(res.body) - repository = res_body_json['items'][0] - else - return - end + repository_response = GithubApiModel.retrieve_language_repo(language.name) begin - new_repository = Repository.find_by(github_id: repository['id']) - puts "\n#{new_repository.name} repo existente\n" - new_repository + repository = Repository.find_by(github_id: repository_response['id']) rescue => e - puts "\nrepo nao existente\n" - new_repository = Repository.create!( - name: repository['name'], - description: repository['description'], - node_id: repository['node_id'], - github_id: repository['id'], - full_name: repository['full_name'], - stars: repository['stargazers_count'], - url: repository['html_url'], - forks: repository['forks_count'], - open_issues: repository['open_issues'], - license: repository['license'] != nil ? repository['license']['name'] : nil, - origin_created_at: DateTime.parse(repository['created_at']), - origin_updated_at: DateTime.parse(repository['updated_at']), - topics: repository['topics'], + repository = Repository.create!( + name: repository_response['name'], + description: repository_response['description'], + node_id: repository_response['node_id'], + github_id: repository_response['id'], + full_name: repository_response['full_name'], + stars: repository_response['stargazers_count'], + url: repository_response['html_url'], + forks: repository_response['forks_count'], + open_issues: repository_response['open_issues'], + license: repository_response['license'] != nil ? repository_response['license']['name'] : nil, + origin_created_at: DateTime.parse(repository_response['created_at']), + origin_updated_at: DateTime.parse(repository_response['updated_at']), + topics: repository_response['topics'], language: language ) - puts "\nrepo adicionado\n" - new_repository + repository end - new_repository + repository end - puts "\n\n#{@results.length()}\n\n" - @results.compact.length() > 0 ? @results.compact : [] end end diff --git a/app/models/github_api_model.rb b/app/models/github_api_model.rb new file mode 100644 index 0000000000..dc7b782659 --- /dev/null +++ b/app/models/github_api_model.rb @@ -0,0 +1,15 @@ +class GithubApiModel < ApplicationRecord + require 'rest_client' + + @url + + def self.getData + response = RestClient.get(@url, { :content_type => :json, "Authorization" => ENV['GITHUB_TOKEN'] }) + end + + def self.retrieve_language_repo(language_name) + @url = "https://api.github.com/search/repositories?q=language:#{language_name}&per_page=1" + parsed_json = JSON.parse(GithubApiModel.getData) + parsed_json["items"][0] + end +end diff --git a/db/migrate/20230114224041_create_github_api_models.rb b/db/migrate/20230114224041_create_github_api_models.rb new file mode 100644 index 0000000000..1a7548939d --- /dev/null +++ b/db/migrate/20230114224041_create_github_api_models.rb @@ -0,0 +1,8 @@ +class CreateGithubApiModels < ActiveRecord::Migration[7.0] + def change + create_table :github_api_models do |t| + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 133c58c7b9..82a7388f1e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,10 +10,15 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_01_14_162107) do +ActiveRecord::Schema[7.0].define(version: 2023_01_14_224041) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "github_api_models", force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "languages", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", null: false diff --git a/spec/models/github_api_model_spec.rb b/spec/models/github_api_model_spec.rb new file mode 100644 index 0000000000..20323ab14f --- /dev/null +++ b/spec/models/github_api_model_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe GithubApiModel, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 71bbbe6601adddcfb7c7e6b85535ec28cc3892f3 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 22:09:29 -0300 Subject: [PATCH 20/33] adds tests to results and refactor results controller --- app/controllers/results_controller.rb | 7 +++---- spec/requests/results_spec.rb | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 spec/requests/results_spec.rb diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index b38d58bc08..ded9c36475 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -5,10 +5,11 @@ def index @languages = Language.all @results = @languages.map do |language| repository_response = GithubApiModel.retrieve_language_repo(language.name) + begin - repository = Repository.find_by(github_id: repository_response['id']) + Repository.find_by!(github_id: repository_response['id']) rescue => e - repository = Repository.create!( + Repository.create( name: repository_response['name'], description: repository_response['description'], node_id: repository_response['node_id'], @@ -24,9 +25,7 @@ def index topics: repository_response['topics'], language: language ) - repository end - repository end end end diff --git a/spec/requests/results_spec.rb b/spec/requests/results_spec.rb new file mode 100644 index 0000000000..0593f3e0b7 --- /dev/null +++ b/spec/requests/results_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' + +RSpec.describe "Results", type: :request do + describe "GET /index" do + it 'should render #index template' do + get '/results' + expect(response).to render_template(:index) + end + + it 'should return repos from all languages' do + language = Language.create(name: 'python') + repository = { "id"=>54346799, "node_id"=>"MDEwOlJlcG9zaXRvcnk1NDM0Njc5OQ==", "name"=>"public-apis", "full_name"=>"public-apis/public-apis", "private"=>false, "owner"=>{"login"=>"public-apis", "id"=>51121562, "node_id"=>"MDEyOk9yZ2FuaXphdGlvbjUxMTIxNTYy", "avatar_url"=>"https://avatars.githubusercontent.com/u/51121562?v=4", "gravatar_id"=>"", "url"=>"https://api.github.com/users/public-apis", "html_url"=>"https://github.com/public-apis", "followers_url"=>"https://api.github.com/users/public-apis/followers", "following_url"=>"https://api.github.com/users/public-apis/following{/other_user}", "gists_url"=>"https://api.github.com/users/public-apis/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/public-apis/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/public-apis/subscriptions", "organizations_url"=>"https://api.github.com/users/public-apis/orgs", "repos_url"=>"https://api.github.com/users/public-apis/repos", "events_url"=>"https://api.github.com/users/public-apis/events{/privacy}", "received_events_url"=>"https://api.github.com/users/public-apis/received_events", "type"=>"Organization", "site_admin"=>false}, "html_url"=>"https://github.com/public-apis/public-apis", "description"=>"A collective list of free APIs", "fork"=>false, "url"=>"https://api.github.com/repos/public-apis/public-apis", "forks_url"=>"https://api.github.com/repos/public-apis/public-apis/forks", "keys_url"=>"https://api.github.com/repos/public-apis/public-apis/keys{/key_id}", "collaborators_url"=>"https://api.github.com/repos/public-apis/public-apis/collaborators{/collaborator}", "teams_url"=>"https://api.github.com/repos/public-apis/public-apis/teams", "hooks_url"=>"https://api.github.com/repos/public-apis/public-apis/hooks", "issue_events_url"=>"https://api.github.com/repos/public-apis/public-apis/issues/events{/number}", "events_url"=>"https://api.github.com/repos/public-apis/public-apis/events", "assignees_url"=>"https://api.github.com/repos/public-apis/public-apis/assignees{/user}", "branches_url"=>"https://api.github.com/repos/public-apis/public-apis/branches{/branch}", "tags_url"=>"https://api.github.com/repos/public-apis/public-apis/tags", "blobs_url"=>"https://api.github.com/repos/public-apis/public-apis/git/blobs{/sha}", "git_tags_url"=>"https://api.github.com/repos/public-apis/public-apis/git/tags{/sha}", "git_refs_url"=>"https://api.github.com/repos/public-apis/public-apis/git/refs{/sha}", "trees_url"=>"https://api.github.com/repos/public-apis/public-apis/git/trees{/sha}", "statuses_url"=>"https://api.github.com/repos/public-apis/public-apis/statuses/{sha}", "languages_url"=>"https://api.github.com/repos/public-apis/public-apis/languages", "stargazers_url"=>"https://api.github.com/repos/public-apis/public-apis/stargazers", "contributors_url"=>"https://api.github.com/repos/public-apis/public-apis/contributors", "subscribers_url"=>"https://api.github.com/repos/public-apis/public-apis/subscribers", "subscription_url"=>"https://api.github.com/repos/public-apis/public-apis/subscription", "commits_url"=>"https://api.github.com/repos/public-apis/public-apis/commits{/sha}", "git_commits_url"=>"https://api.github.com/repos/public-apis/public-apis/git/commits{/sha}", "comments_url"=>"https://api.github.com/repos/public-apis/public-apis/comments{/number}", "issue_comment_url"=>"https://api.github.com/repos/public-apis/public-apis/issues/comments{/number}", "contents_url"=>"https://api.github.com/repos/public-apis/public-apis/contents/{+path}", "compare_url"=>"https://api.github.com/repos/public-apis/public-apis/compare/{base}...{head}", "merges_url"=>"https://api.github.com/repos/public-apis/public-apis/merges", "archive_url"=>"https://api.github.com/repos/public-apis/public-apis/{archive_format}{/ref}", "downloads_url"=>"https://api.github.com/repos/public-apis/public-apis/downloads", "issues_url"=>"https://api.github.com/repos/public-apis/public-apis/issues{/number}", "pulls_url"=>"https://api.github.com/repos/public-apis/public-apis/pulls{/number}", "milestones_url"=>"https://api.github.com/repos/public-apis/public-apis/milestones{/number}", "notifications_url"=>"https://api.github.com/repos/public-apis/public-apis/notifications{?since,all,participating}", "labels_url"=>"https://api.github.com/repos/public-apis/public-apis/labels{/name}", "releases_url"=>"https://api.github.com/repos/public-apis/public-apis/releases{/id}", "deployments_url"=>"https://api.github.com/repos/public-apis/public-apis/deployments", "created_at"=>"2016-03-20T23:49:42Z", "updated_at"=>"2023-01-14T23:33:01Z", "pushed_at"=>"2023-01-14T19:13:05Z", "git_url"=>"git://github.com/public-apis/public-apis.git", "ssh_url"=>"git@github.com:public-apis/public-apis.git", "clone_url"=>"https://github.com/public-apis/public-apis.git", "svn_url"=>"https://github.com/public-apis/public-apis", "homepage"=>"http://public-apis.org", "size"=>4948, "stargazers_count"=>224650, "watchers_count"=>224650, "language"=>"Python", "has_issues"=>true, "has_projects"=>false, "has_downloads"=>true, "has_wiki"=>false, "has_pages"=>false, "has_discussions"=>false, "forks_count"=>25593, "mirror_url"=>nil, "archived"=>false, "disabled"=>false, "open_issues_count"=>124, "license"=>{"key"=>"mit", "name"=>"MIT License", "spdx_id"=>"MIT", "url"=>"https://api.github.com/licenses/mit", "node_id"=>"MDc6TGljZW5zZTEz"}, "allow_forking"=>true, "is_template"=>false, "web_commit_signoff_required"=>false, "topics"=>["api", "apis", "dataset", "development", "free", "list", "lists", "open-source", "public", "public-api", "public-apis", "resources", "software"], "visibility"=>"public", "forks"=>25593, "open_issues"=>124, "watchers"=>224650, "default_branch"=>"master", "score"=>1.0 } + allow(GithubApiModel).to receive(:retrieve_language_repo).with('python').and_return(repository) + + get '/results' + expect(assigns(:results)).to eq([Repository.find_by(github_id: repository['id'])]) + end + end +end From 7fc929ebb05edb4a7e4d8c804a424cdd060d37f4 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 22:18:06 -0300 Subject: [PATCH 21/33] adds test do GithubApiModel --- spec/models/github_api_model_spec.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/spec/models/github_api_model_spec.rb b/spec/models/github_api_model_spec.rb index 20323ab14f..d9aa0ed9f9 100644 --- a/spec/models/github_api_model_spec.rb +++ b/spec/models/github_api_model_spec.rb @@ -1,5 +1,14 @@ require 'rails_helper' RSpec.describe GithubApiModel, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + # this is a flaky test, 'cause it depends of an external api call + describe 'something' do + let(:github_response) { GithubApiModel.retrieve_language_repo('javascript') } + it 'should do something' do + expect(github_response).to be_kind_of(Hash) + expect(github_response).to have_key("id") + expect(github_response).to have_key("name") + expect(github_response).to have_key("full_name") + end + end end From b36889d9bb59defb4063fc689ea053ab4288255b Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 23:51:32 -0300 Subject: [PATCH 22/33] changes repository columns constraints --- app/models/repository.rb | 1 + ...t_null_constraint_to_repository_columns.rb | 14 ++++++++++++ db/schema.rb | 22 +++++++++---------- 3 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 db/migrate/20230115012404_add_not_null_constraint_to_repository_columns.rb diff --git a/app/models/repository.rb b/app/models/repository.rb index c6743c9eb5..2dabc2b7c1 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,3 +1,4 @@ class Repository < ApplicationRecord belongs_to :language + validates :name, :full_name, :github_id, :node_id, :stars, :url, :forks, :open_issues, :origin_created_at, :origin_updated_at, presence: true end diff --git a/db/migrate/20230115012404_add_not_null_constraint_to_repository_columns.rb b/db/migrate/20230115012404_add_not_null_constraint_to_repository_columns.rb new file mode 100644 index 0000000000..90175d4acc --- /dev/null +++ b/db/migrate/20230115012404_add_not_null_constraint_to_repository_columns.rb @@ -0,0 +1,14 @@ +class AddNotNullConstraintToRepositoryColumns < ActiveRecord::Migration[7.0] + def change + change_column_null :repositories, :name, false + change_column_null :repositories, :full_name, false + change_column_null :repositories, :github_id, false + change_column_null :repositories, :node_id, false + change_column_null :repositories, :stars, false + change_column_null :repositories, :url, false + change_column_null :repositories, :forks, false + change_column_null :repositories, :open_issues, false + change_column_null :repositories, :origin_created_at, false + change_column_null :repositories, :origin_updated_at, false + end +end diff --git a/db/schema.rb b/db/schema.rb index 82a7388f1e..82b7a1040d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_01_14_224041) do +ActiveRecord::Schema[7.0].define(version: 2023_01_15_012404) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -27,18 +27,18 @@ end create_table "repositories", force: :cascade do |t| - t.string "name" + t.string "name", null: false t.text "description" - t.string "node_id" - t.integer "github_id" - t.string "full_name" - t.integer "stars" - t.string "url" - t.integer "forks" - t.integer "open_issues" + t.string "node_id", null: false + t.integer "github_id", null: false + t.string "full_name", null: false + t.integer "stars", null: false + t.string "url", null: false + t.integer "forks", null: false + t.integer "open_issues", null: false t.string "license" - t.datetime "origin_created_at" - t.string "origin_updated_at" + t.datetime "origin_created_at", null: false + t.string "origin_updated_at", null: false t.string "topics", default: [], array: true t.bigint "language_id", null: false t.datetime "created_at", null: false From b55c2a4464dbf89d5998368b6a3b827a41f6c8af Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 23:51:54 -0300 Subject: [PATCH 23/33] adds tests to results controller --- spec/requests/results_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/requests/results_spec.rb b/spec/requests/results_spec.rb index 0593f3e0b7..6087f39093 100644 --- a/spec/requests/results_spec.rb +++ b/spec/requests/results_spec.rb @@ -2,12 +2,12 @@ RSpec.describe "Results", type: :request do describe "GET /index" do - it 'should render #index template' do + it "should render #index template" do get '/results' expect(response).to render_template(:index) end - it 'should return repos from all languages' do + it "should return repos from all languages" do language = Language.create(name: 'python') repository = { "id"=>54346799, "node_id"=>"MDEwOlJlcG9zaXRvcnk1NDM0Njc5OQ==", "name"=>"public-apis", "full_name"=>"public-apis/public-apis", "private"=>false, "owner"=>{"login"=>"public-apis", "id"=>51121562, "node_id"=>"MDEyOk9yZ2FuaXphdGlvbjUxMTIxNTYy", "avatar_url"=>"https://avatars.githubusercontent.com/u/51121562?v=4", "gravatar_id"=>"", "url"=>"https://api.github.com/users/public-apis", "html_url"=>"https://github.com/public-apis", "followers_url"=>"https://api.github.com/users/public-apis/followers", "following_url"=>"https://api.github.com/users/public-apis/following{/other_user}", "gists_url"=>"https://api.github.com/users/public-apis/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/public-apis/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/public-apis/subscriptions", "organizations_url"=>"https://api.github.com/users/public-apis/orgs", "repos_url"=>"https://api.github.com/users/public-apis/repos", "events_url"=>"https://api.github.com/users/public-apis/events{/privacy}", "received_events_url"=>"https://api.github.com/users/public-apis/received_events", "type"=>"Organization", "site_admin"=>false}, "html_url"=>"https://github.com/public-apis/public-apis", "description"=>"A collective list of free APIs", "fork"=>false, "url"=>"https://api.github.com/repos/public-apis/public-apis", "forks_url"=>"https://api.github.com/repos/public-apis/public-apis/forks", "keys_url"=>"https://api.github.com/repos/public-apis/public-apis/keys{/key_id}", "collaborators_url"=>"https://api.github.com/repos/public-apis/public-apis/collaborators{/collaborator}", "teams_url"=>"https://api.github.com/repos/public-apis/public-apis/teams", "hooks_url"=>"https://api.github.com/repos/public-apis/public-apis/hooks", "issue_events_url"=>"https://api.github.com/repos/public-apis/public-apis/issues/events{/number}", "events_url"=>"https://api.github.com/repos/public-apis/public-apis/events", "assignees_url"=>"https://api.github.com/repos/public-apis/public-apis/assignees{/user}", "branches_url"=>"https://api.github.com/repos/public-apis/public-apis/branches{/branch}", "tags_url"=>"https://api.github.com/repos/public-apis/public-apis/tags", "blobs_url"=>"https://api.github.com/repos/public-apis/public-apis/git/blobs{/sha}", "git_tags_url"=>"https://api.github.com/repos/public-apis/public-apis/git/tags{/sha}", "git_refs_url"=>"https://api.github.com/repos/public-apis/public-apis/git/refs{/sha}", "trees_url"=>"https://api.github.com/repos/public-apis/public-apis/git/trees{/sha}", "statuses_url"=>"https://api.github.com/repos/public-apis/public-apis/statuses/{sha}", "languages_url"=>"https://api.github.com/repos/public-apis/public-apis/languages", "stargazers_url"=>"https://api.github.com/repos/public-apis/public-apis/stargazers", "contributors_url"=>"https://api.github.com/repos/public-apis/public-apis/contributors", "subscribers_url"=>"https://api.github.com/repos/public-apis/public-apis/subscribers", "subscription_url"=>"https://api.github.com/repos/public-apis/public-apis/subscription", "commits_url"=>"https://api.github.com/repos/public-apis/public-apis/commits{/sha}", "git_commits_url"=>"https://api.github.com/repos/public-apis/public-apis/git/commits{/sha}", "comments_url"=>"https://api.github.com/repos/public-apis/public-apis/comments{/number}", "issue_comment_url"=>"https://api.github.com/repos/public-apis/public-apis/issues/comments{/number}", "contents_url"=>"https://api.github.com/repos/public-apis/public-apis/contents/{+path}", "compare_url"=>"https://api.github.com/repos/public-apis/public-apis/compare/{base}...{head}", "merges_url"=>"https://api.github.com/repos/public-apis/public-apis/merges", "archive_url"=>"https://api.github.com/repos/public-apis/public-apis/{archive_format}{/ref}", "downloads_url"=>"https://api.github.com/repos/public-apis/public-apis/downloads", "issues_url"=>"https://api.github.com/repos/public-apis/public-apis/issues{/number}", "pulls_url"=>"https://api.github.com/repos/public-apis/public-apis/pulls{/number}", "milestones_url"=>"https://api.github.com/repos/public-apis/public-apis/milestones{/number}", "notifications_url"=>"https://api.github.com/repos/public-apis/public-apis/notifications{?since,all,participating}", "labels_url"=>"https://api.github.com/repos/public-apis/public-apis/labels{/name}", "releases_url"=>"https://api.github.com/repos/public-apis/public-apis/releases{/id}", "deployments_url"=>"https://api.github.com/repos/public-apis/public-apis/deployments", "created_at"=>"2016-03-20T23:49:42Z", "updated_at"=>"2023-01-14T23:33:01Z", "pushed_at"=>"2023-01-14T19:13:05Z", "git_url"=>"git://github.com/public-apis/public-apis.git", "ssh_url"=>"git@github.com:public-apis/public-apis.git", "clone_url"=>"https://github.com/public-apis/public-apis.git", "svn_url"=>"https://github.com/public-apis/public-apis", "homepage"=>"http://public-apis.org", "size"=>4948, "stargazers_count"=>224650, "watchers_count"=>224650, "language"=>"Python", "has_issues"=>true, "has_projects"=>false, "has_downloads"=>true, "has_wiki"=>false, "has_pages"=>false, "has_discussions"=>false, "forks_count"=>25593, "mirror_url"=>nil, "archived"=>false, "disabled"=>false, "open_issues_count"=>124, "license"=>{"key"=>"mit", "name"=>"MIT License", "spdx_id"=>"MIT", "url"=>"https://api.github.com/licenses/mit", "node_id"=>"MDc6TGljZW5zZTEz"}, "allow_forking"=>true, "is_template"=>false, "web_commit_signoff_required"=>false, "topics"=>["api", "apis", "dataset", "development", "free", "list", "lists", "open-source", "public", "public-api", "public-apis", "resources", "software"], "visibility"=>"public", "forks"=>25593, "open_issues"=>124, "watchers"=>224650, "default_branch"=>"master", "score"=>1.0 } allow(GithubApiModel).to receive(:retrieve_language_repo).with('python').and_return(repository) From 093cc172d61036851e0eabf6dbd1152440ddf87a Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 23:52:13 -0300 Subject: [PATCH 24/33] fix repositories controller tests --- spec/requests/repositories_spec.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/requests/repositories_spec.rb b/spec/requests/repositories_spec.rb index a55d14e1c7..98f03de6c3 100644 --- a/spec/requests/repositories_spec.rb +++ b/spec/requests/repositories_spec.rb @@ -16,7 +16,9 @@ origin_created_at: DateTime.now, origin_updated_at: DateTime.now, url: "https://github.com/TheAlgorithms/Python", - language: language + language: language, + github_id: 123, + node_id: "123abc" ) get "/repositories/#{repository.id}" expect(response).to render_template(:show) @@ -36,7 +38,9 @@ origin_created_at: DateTime.now, origin_updated_at: DateTime.now, url: "https://github.com/TheAlgorithms/Python", - language: language + language: language, + github_id: 123, + node_id: "123abc" ) get "/repositories/#{repository.id}" expect(assigns(:repository)).to eq(repository) From 288c921f994d61dc69cd47af702006726f9bb124 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 23:52:28 -0300 Subject: [PATCH 25/33] adds tests to githubmodelapi --- spec/models/github_api_model_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/github_api_model_spec.rb b/spec/models/github_api_model_spec.rb index d9aa0ed9f9..02e878f081 100644 --- a/spec/models/github_api_model_spec.rb +++ b/spec/models/github_api_model_spec.rb @@ -2,9 +2,9 @@ RSpec.describe GithubApiModel, type: :model do # this is a flaky test, 'cause it depends of an external api call - describe 'something' do + context "when api is available" do let(:github_response) { GithubApiModel.retrieve_language_repo('javascript') } - it 'should do something' do + it "should return a hash with data from an repository" do expect(github_response).to be_kind_of(Hash) expect(github_response).to have_key("id") expect(github_response).to have_key("name") From a48de5fccc32aae2bdfaf11fb7abeac29887e345 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sat, 14 Jan 2023 23:52:39 -0300 Subject: [PATCH 26/33] adds model tests to repository --- spec/models/repository_spec.rb | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 spec/models/repository_spec.rb diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb new file mode 100644 index 0000000000..c5af24e958 --- /dev/null +++ b/spec/models/repository_spec.rb @@ -0,0 +1,102 @@ +require 'rails_helper' + +RSpec.describe Repository, type: :model do + context "only with all not nullable fields filled" do + it "should create repository" do + language = Language.create!(name: "python") + Repository.create!( + name: "django", + description: "The Web framework for perfectionists with deadlines.", + node_id: "MDEwOlJlcG9zaXRvcnk0MTY0NDgy", + github_id: 4164482, + full_name: "django/django", + stars: 68179, + url: "https://github.com/django/django", + forks: 28443, + open_issues: 161, + license: "BSD 3-Clause \"New\" or \"Revised\" License", + origin_created_at: DateTime.now, + origin_updated_at: DateTime.now, + topics: ["apps", "django", "framework", "models", "orm", "python", "templates", "views", "web"], + language: language + ) + expect(Repository.last.github_id).to eq(4164482) + end + end + + context "the repository won't be created if" do + let(:repository_data) do + language = Language.create!(name: "python") + { + name: "django", + description: "The Web framework for perfectionists with deadlines.", + node_id: "MDEwOlJlcG9zaXRvcnk0MTY0NDgy", + github_id: 4164482, + full_name: "django/django", + stars: 68179, + url: "https://github.com/django/django", + forks: 28443, + open_issues: 161, + license: "BSD 3-Clause \"New\" or \"Revised\" License", + origin_created_at: DateTime.now, + origin_updated_at: DateTime.now, + topics: ["apps", "django", "framework", "models", "orm", "python", "templates", "views", "web"], + language: language + } + end + it "is missing name" do + repository_data[:name] = "" + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing full_name" do + repository_data[:full_name] = "" + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing node_id" do + repository_data[:node_id] = "" + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing github_id" do + repository_data[:github_id] = nil + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing stars" do + repository_data[:stars] = nil + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing forks" do + repository_data[:forks] = nil + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing url" do + repository_data[:url] = "" + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing open_issues" do + repository_data[:open_issues] = nil + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing origin_created_at" do + repository_data[:origin_created_at] = nil + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing origin_updated_at" do + repository_data[:origin_updated_at] = nil + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + + it "is missing origin_updated_at" do + repository_data[:language] = nil + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) + end + end +end From 5cb8194d994ba5049f7f01ca17bf7bb97de74be6 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sun, 15 Jan 2023 09:50:44 -0300 Subject: [PATCH 27/33] finishes styling in both dark mode and light mode --- app/views/languages/show.html.erb | 2 +- app/views/repositories/show.html.erb | 4 ++-- app/views/results/index.html.erb | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/languages/show.html.erb b/app/views/languages/show.html.erb index 13e80b462d..166659479e 100644 --- a/app/views/languages/show.html.erb +++ b/app/views/languages/show.html.erb @@ -13,7 +13,7 @@

Forks: <%= repo.forks %>

-

+

<%= link_to "Github Repository", repo.url, target: :_blank %>

<%= link_to "Check all repository's details", repository_path(repo), {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300 absolute left-0 right-0 w-[260px] bottom-4 mx-auto"} %> diff --git a/app/views/repositories/show.html.erb b/app/views/repositories/show.html.erb index 965ebbf8ac..ae9067c53f 100644 --- a/app/views/repositories/show.html.erb +++ b/app/views/repositories/show.html.erb @@ -13,10 +13,10 @@ <% end %>

Created at: <%= @repository.origin_created_at %>

Last update: <%= @repository.origin_updated_at %>

-

+

<%= link_to "Github Repository", @repository.url, target: :_blank %>

- Language: <%= link_to "#{@repository.language.name.capitalize}", language_path(@repository.language), {:class => "font-bold hover:text-white duration-300"} %> + Language: <%= link_to "#{@repository.language.name.capitalize}", language_path(@repository.language), {:class => "font-bold hover:text-black dark:hover:text-white duration-300"} %>

diff --git a/app/views/results/index.html.erb b/app/views/results/index.html.erb index a4fc69aa3a..94ff00c4e7 100644 --- a/app/views/results/index.html.erb +++ b/app/views/results/index.html.erb @@ -13,10 +13,10 @@

Forks: <%= repo.forks %>

-

- Language: <%= repo.language.name.capitalize %> +

+ Language: <%= link_to "#{repo.language.name.capitalize}", language_path(repo.language), {:class => "font-bold hover:text-black dark:hover:text-white duration-300"} %>

-

+

<%= link_to "Github Repository", repo.url, target: :_blank %>

<%= link_to "Check all repository's details", repository_path(repo), {:class => "rounded-lg px-4 py-2 text-md font-bold text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 duration-300 absolute left-0 right-0 w-[260px] bottom-4 mx-auto"} %> From 4a19c4ae330d06cfc0e8285310d19c5cbb413ec5 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sun, 15 Jan 2023 15:28:38 -0300 Subject: [PATCH 28/33] update gemfile.lock --- Gemfile.lock | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b19431ce4a..776be0db57 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -95,18 +95,11 @@ GEM dotenv (= 2.8.1) railties (>= 3.2) erubi (1.12.0) - faraday (2.7.2) - faraday-net_http (>= 2.0, < 3.1) - ruby2_keywords (>= 0.0.4) - faraday-net_http (3.0.2) globalid (1.0.0) activesupport (>= 5.0) http-accept (1.7.0) http-cookie (1.0.5) domain_name (~> 0.5) - httparty (0.21.0) - mini_mime (>= 1.0.0) - multi_xml (>= 0.5.2) i18n (1.12.0) concurrent-ruby (~> 1.0) importmap-rails (1.1.5) @@ -121,7 +114,7 @@ GEM loofah (2.19.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.8.0) + mail (2.8.0.1) mini_mime (>= 0.1.1) net-imap net-pop @@ -135,7 +128,6 @@ GEM mini_mime (1.1.2) minitest (5.17.0) msgpack (1.6.0) - multi_xml (0.6.0) net-imap (0.3.4) date net-protocol @@ -147,11 +139,8 @@ GEM net-protocol netrc (0.11.0) nio4r (2.5.8) - nokogiri (1.13.10-x86_64-linux) + nokogiri (1.14.0-x86_64-linux) racc (~> 1.4) - octokit (5.6.1) - faraday (>= 1, < 3) - sawyer (~> 0.9) pg (1.4.5) public_suffix (5.0.1) puma (5.6.5) @@ -217,11 +206,7 @@ GEM rspec-mocks (~> 3.11) rspec-support (~> 3.11) rspec-support (3.12.0) - ruby2_keywords (0.0.5) rubyzip (2.3.2) - sawyer (0.9.2) - addressable (>= 2.3.5) - faraday (>= 0.17.3, < 3) selenium-webdriver (4.7.1) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) @@ -273,10 +258,8 @@ DEPENDENCIES capybara debug dotenv-rails - httparty importmap-rails jbuilder - octokit (~> 5.0) pg (~> 1.1) puma (~> 5.0) rails (~> 7.0.4) From 4d40cebe38875ff000b3981ca16eb520d3827152 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sun, 15 Jan 2023 15:49:46 -0300 Subject: [PATCH 29/33] update .env.example --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index ce1440ef74..0d7cf7dc0a 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ DATABASE_USERNAME=username DATABASE_PASSWORD=password DATABASE_HOST=host +GITHUB_TOKEN=token From 27d0636c9c20bad6c2f7ee862e524a7fbc549119 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sun, 15 Jan 2023 16:22:47 -0300 Subject: [PATCH 30/33] update readme file --- README.example.md | 24 ---------------- README.md | 70 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 40 deletions(-) delete mode 100644 README.example.md diff --git a/README.example.md b/README.example.md deleted file mode 100644 index 28feefee53..0000000000 --- a/README.example.md +++ /dev/null @@ -1,24 +0,0 @@ -# README - -This README would normally document whatever steps are necessary to get the -application up and running. - -Things you may want to cover: - -- Ruby version - -- System dependencies - -- Configuration - -- Database creation - -- Database initialization - -- How to run the test suite - -- Services (job queues, cache servers, search engines, etc.) - -- Deployment instructions - -- ... diff --git a/README.md b/README.md index 3f1e493650..0433bf8dbc 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,60 @@ -# Desafio técnico para desenvolvedores +# GitHub Search -Construa uma nova aplicação, utilizando o framework de sua preferência (Ruby on Rails, Elixir Phoenix, Python Django ou Flask, NodeJS Sails, Java Spring, ASP.NET ou outro), a qual deverá conectar na API do GitHub e disponibilizar as seguintes funcionalidades: +Aplicação que busca os repositórios mais relevantes das 5 linguagens pré-selecionadas no início do projeto (JavaScript, Python, Ruby, Elixir, TypeScript) -- Botão para buscar e armazenar os repositórios destaques de 5 linguagens à sua escolha; -- Listar os repositórios encontrados; -- Visualizar os detalhes de cada repositório. +## Antes de executar o projeto -Alguns requisitos: +### Pré-requisito -- Deve ser uma aplicação totalmente nova; -- A solução deve estar em um repositório público do GitHub; -- A aplicação deve armazenar as informações encontradas; -- Utilizar PostgreSQL, MySQL ou SQL Server; -- O deploy deve ser realizado, preferencialmente, no Heroku, AWS ou no Azure; -- A aplicação precisa ter testes automatizados; -- Preferenciamente dockerizar a aplicação; -- Por favor atualizar o readme da aplicação com passo a passo com instrução para subir o ambiente. +É preciso que tenha [Docker](https://docs.docker.com/engine/install/) e [Docker Compose](https://docs.docker.com/compose/gettingstarted/) instalados na sua máquina. -Quando terminar, faça um Pull Request neste repo e avise-nos por email. +### .env -**IMPORTANTE:** se você não conseguir finalizar o teste, por favor nos diga o motivo e descreva quais foram as suas dificuldades. Você pode também sugerir uma outra abordagem para avaliarmos seus skills técnicos, vender seu peixe, mostrar-nos do que é capaz. +Com o repositório clonado na sua máquina, entre no diretório do projeto e crie um arquivo `.env`. Sem ele, não será possível executar o projeto. Utilize o arquivo `.env.example` localizado na raiz do projeto como referência para criar o seu arquivo `.env`. + +Certifique-se de que o valor de `DATABASE_PASSWORD` localizado no arquivo `.env` possui o mesmo valor de `POSTGRES_PASSWORD` localizando no `docker-compose.yml`. O valor do `GITHUB_TOKEN` deve ser gerado no próprio GitHub, pode seguir esse [tutorial](https://docs.github.com/pt/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) caso ainda não possua um token a ser utilizado + +## Executando o projeto + +Se o arquivo `.env` foi devidamente criado, agora você já tem o que é preciso para rodar o projeto. + +### Build da aplicação + +Primeiro, é necessário que você faça o build da aplicação. Para isso, execute o comando abaixo + +``` +docker-compose build +``` + +### Criação do banco de dados + +Após finalizado o build da aplicação, é necessário criar o banco de dados, executar as migrações e fazer o seed. Para isso, execute o comando abaixo. + +``` +docker-compose run web rails db:create db:migrate db:seed +``` + +### TailwindCSS + +Essa aplicação utiliza o TailwindCSS para estilização e é necessário que execute esses comandos em sequência para que a aplicação seja devidamente estilizada. + +``` +docker-compose run web bin/rails tailwindcss:install +docker-compose run web rake tailwindcss:build +``` + +### Rodar o projeto + +Agora, execute o comando abaixo e a aplicação estará disponível na porta 3000, através desse [link](localhost:3000) ou desse [link](0.0.0.0:3000). + +``` +docker-compose up +``` + +## Testes + +Os testes podem ser executados com o comando abaixo. + +``` +docker-compose run web bundle exec rspec +``` From 2886a400ab9ce3c0709b8b50752b5c0025348a31 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sun, 15 Jan 2023 16:29:38 -0300 Subject: [PATCH 31/33] turns language name column unique --- .../20230115192712_add_unique_contraint_to_language_name.rb | 5 +++++ db/schema.rb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20230115192712_add_unique_contraint_to_language_name.rb diff --git a/db/migrate/20230115192712_add_unique_contraint_to_language_name.rb b/db/migrate/20230115192712_add_unique_contraint_to_language_name.rb new file mode 100644 index 0000000000..52a95d0498 --- /dev/null +++ b/db/migrate/20230115192712_add_unique_contraint_to_language_name.rb @@ -0,0 +1,5 @@ +class AddUniqueContraintToLanguageName < ActiveRecord::Migration[7.0] + def change + add_index :languages, :name, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 82b7a1040d..f6d95dc03e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_01_15_012404) do +ActiveRecord::Schema[7.0].define(version: 2023_01_15_192712) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -24,6 +24,7 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "slug", default: "", null: false + t.index ["name"], name: "index_languages_on_name", unique: true end create_table "repositories", force: :cascade do |t| From fc539dc588a894c1f21dc3bb71a41a1403425a80 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sun, 15 Jan 2023 16:33:38 -0300 Subject: [PATCH 32/33] adds test to ensure uniqueness of languages and repositories --- spec/models/language_spec.rb | 7 +++++++ spec/models/repository_spec.rb | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/spec/models/language_spec.rb b/spec/models/language_spec.rb index 8467898f24..aa721d3574 100644 --- a/spec/models/language_spec.rb +++ b/spec/models/language_spec.rb @@ -28,4 +28,11 @@ expect(language.slug).to eq('language-name') end end + + context 'when creating a new language with the same name of an existing language name' do + it 'should raise error' do + Language.create!(name: 'javascript') + expect { Language.create!(name: 'javascript') }.to raise_error(ActiveRecord::RecordNotUnique) + end + end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index c5af24e958..bc0b98b006 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -98,5 +98,10 @@ repository_data[:language] = nil expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordInvalid) end + + it "has the same github_id of an existing repository" do + Repository.create!(repository_data) + expect { Repository.create!(repository_data) }.to raise_error(ActiveRecord::RecordNotUnique) + end end end From 2b8e08e9ad10b8a0269f31e05148c9355d9acc67 Mon Sep 17 00:00:00 2001 From: bielzin Date: Sun, 15 Jan 2023 16:36:21 -0300 Subject: [PATCH 33/33] removes unnecessary files --- app/views/languages/new.html.erb | 9 --- app/views/repositories/_form.html.erb | 82 ---------------------- app/views/repositories/index.html.erb | 14 ---- app/views/repositories/index.json.jbuilder | 1 - 4 files changed, 106 deletions(-) delete mode 100644 app/views/languages/new.html.erb delete mode 100644 app/views/repositories/_form.html.erb delete mode 100644 app/views/repositories/index.html.erb delete mode 100644 app/views/repositories/index.json.jbuilder diff --git a/app/views/languages/new.html.erb b/app/views/languages/new.html.erb deleted file mode 100644 index bebcc3df0d..0000000000 --- a/app/views/languages/new.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -

New language

- -<%= render "form", language: @language %> - -
- -
- <%= link_to "Back to languages", languages_path %> -
diff --git a/app/views/repositories/_form.html.erb b/app/views/repositories/_form.html.erb deleted file mode 100644 index c6b38f09a2..0000000000 --- a/app/views/repositories/_form.html.erb +++ /dev/null @@ -1,82 +0,0 @@ -<%= form_with(model: repository) do |form| %> - <% if repository.errors.any? %> -
-

<%= pluralize(repository.errors.count, "error") %> prohibited this repository from being saved:

- -
    - <% repository.errors.each do |error| %> -
  • <%= error.full_message %>
  • - <% end %> -
-
- <% end %> - -
- <%= form.label :name, style: "display: block" %> - <%= form.text_field :name %> -
- -
- <%= form.label :node_id, style: "display: block" %> - <%= form.text_field :node_id %> -
- -
- <%= form.label :github_id, style: "display: block" %> - <%= form.number_field :github_id %> -
- -
- <%= form.label :full_name, style: "display: block" %> - <%= form.text_field :full_name %> -
- -
- <%= form.label :stars, style: "display: block" %> - <%= form.number_field :stars %> -
- -
- <%= form.label :url, style: "display: block" %> - <%= form.text_field :url %> -
- -
- <%= form.label :forks, style: "display: block" %> - <%= form.number_field :forks %> -
- -
- <%= form.label :open_issues, style: "display: block" %> - <%= form.number_field :open_issues %> -
- -
- <%= form.label :license, style: "display: block" %> - <%= form.text_field :license %> -
- -
- <%= form.label :origin_created_at, style: "display: block" %> - <%= form.datetime_field :origin_created_at %> -
- -
- <%= form.label :origin_updated_at, style: "display: block" %> - <%= form.text_field :origin_updated_at %> -
- -
- <%= form.label :topics, style: "display: block" %> - <%= form.text_area :topics %> -
- -
- <%= form.label :language_id, style: "display: block" %> - <%= form.text_field :language_id %> -
- -
- <%= form.submit %> -
-<% end %> diff --git a/app/views/repositories/index.html.erb b/app/views/repositories/index.html.erb deleted file mode 100644 index 5d7ad9ddaa..0000000000 --- a/app/views/repositories/index.html.erb +++ /dev/null @@ -1,14 +0,0 @@ -

<%= notice %>

- -

Repositories

- -
- <% @repositories.each do |repository| %> - <%= render repository %> -

- <%= link_to "Show this repository", repository %> -

- <% end %> -
- -<%= link_to "New repository", new_repository_path %> diff --git a/app/views/repositories/index.json.jbuilder b/app/views/repositories/index.json.jbuilder deleted file mode 100644 index 1dca2fe40d..0000000000 --- a/app/views/repositories/index.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.array! @repositories, partial: "repositories/repository", as: :repository