├── .browserslistrc ├── .dockerignore ├── .env ├── .eslintrc.json ├── .gemrc ├── .github ├── FUNDING.yml └── workflows │ ├── deploy.yml │ ├── docker-build-and-push-develpoment.yml │ └── docker-build-and-push-production.yml ├── .gitignore ├── .old-travis.yml ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .ruby-gemset ├── .ruby-version ├── .snyk ├── CONTRIBUTE.md ├── Capfile ├── Gemfile ├── Gemfile.lock ├── LICENSE.md ├── Makefile ├── README.md ├── Rakefile ├── VERSION ├── app ├── assets │ ├── config │ │ └── manifest.js │ ├── fonts │ │ ├── HelveticaNeue-Bold.otf │ │ ├── HelveticaNeue-BoldItalic.otf │ │ ├── HelveticaNeue-CondensedBlack.otf │ │ ├── HelveticaNeue-CondensedBold.otf │ │ ├── HelveticaNeue-Italic.otf │ │ ├── HelveticaNeue-Light.otf │ │ ├── HelveticaNeue-LightItalic.otf │ │ ├── HelveticaNeue-Medium.otf │ │ ├── HelveticaNeue-MediumItalic.otf │ │ ├── HelveticaNeue-Thin.otf │ │ ├── HelveticaNeue-ThinItalic.otf │ │ ├── HelveticaNeue-UltraLight.otf │ │ ├── HelveticaNeue-UltraLightItalic.otf │ │ └── HelveticaNeue.otf │ ├── images │ │ ├── app-store-badge.svg │ │ ├── avatars_fallback │ │ │ ├── default.png │ │ │ ├── square_150_default.png │ │ │ ├── square_25_default.png │ │ │ └── square_50_default.png │ │ ├── events_fallback │ │ │ ├── default.png │ │ │ ├── fb_1200_default.png │ │ │ └── square_500_default.png │ │ ├── google-play-badge.png │ │ ├── it52-logo-144x144.png │ │ ├── it52-logo-16x16.png │ │ ├── it52-logo-180x180.png │ │ ├── it52-logo-192x192.png │ │ ├── it52-logo-32x32.png │ │ ├── it52-logo-96x96.png │ │ ├── it52_favicon.ico │ │ ├── it52_logo_fb@2x.png │ │ ├── it52_logo_white_clean.svg │ │ └── itgorky-logo.svg │ └── stylesheets │ │ ├── _material.sass │ │ ├── app.sass │ │ ├── application.css │ │ ├── events.sass │ │ ├── theme │ │ ├── _type.sass │ │ ├── _variables.sass │ │ ├── bootstrap_and_overrides.sass │ │ ├── common_styles.sass │ │ └── typography.sass │ │ └── user_profiles.sass ├── controllers │ ├── api │ │ ├── v1 │ │ │ ├── api_controller.rb │ │ │ ├── events_controller.rb │ │ │ └── users_controller.rb │ │ └── v2 │ │ │ ├── api_controller.rb │ │ │ ├── events_controller.rb │ │ │ └── tags_controller.rb │ ├── application_controller.rb │ ├── concerns │ │ └── .keep │ ├── errors_controller.rb │ ├── event_participations_controller.rb │ ├── events_controller.rb │ ├── letsencrypt_controller.rb │ ├── mailchimp_hooks_controller.rb │ ├── my.rb │ ├── my │ │ ├── authentications_controller.rb │ │ └── users_controller.rb │ ├── omniauth_callbacks_controller.rb │ ├── pages_controller.rb │ ├── sitemaps_controller.rb │ ├── startups_controller.rb │ ├── telegram_hooks_controller.rb │ ├── turbo │ │ └── events_controller.rb │ └── users_controller.rb ├── decorators │ ├── authentication_decorator.rb │ ├── event_decorator.rb │ └── user_decorator.rb ├── helpers │ ├── application_helper.rb │ └── events_helper.rb ├── javascript │ └── packs │ │ ├── application.ts │ │ ├── editor.ts │ │ ├── helpers │ │ └── foreign-link-switcher.ts │ │ ├── mdc │ │ └── mdc-init.ts │ │ └── yandex │ │ └── yandex-init.ts ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── ability.rb │ ├── address.rb │ ├── application_record.rb │ ├── authentication.rb │ ├── calendar.rb │ ├── concerns │ │ └── .keep │ ├── donation.rb │ ├── event.rb │ ├── event_participation.rb │ ├── mailchimp_synchronizer.rb │ ├── startup.rb │ ├── telegram.rb │ ├── telegram │ │ ├── botan.rb │ │ ├── channel.rb │ │ ├── message.rb │ │ └── request.rb │ └── user.rb ├── serializers │ ├── authentication_serializer.rb │ ├── event_brief_serializer.rb │ ├── event_serializer.rb │ ├── startup_serializer.rb │ ├── user_serializer.rb │ └── v2 │ │ ├── event_serializer.rb │ │ ├── tag_serializer.rb │ │ └── user_serializer.rb ├── services │ ├── extract_event_address_service.rb │ ├── render_ar_collection_to_csv.rb │ ├── update_event_pageviews.rb │ └── update_user_from_omniauth.rb ├── uploaders │ ├── concerns │ │ └── uploader_concern.rb │ ├── event_title_image_uploader.rb │ ├── startup_logo_uploader.rb │ └── user_avatar_uploader.rb └── views │ ├── authentications │ ├── _authentication.html.slim │ └── _unlinked.html.slim │ ├── devise │ ├── confirmations │ │ └── new.html.slim │ ├── mailer │ │ ├── confirmation_instructions.html.slim │ │ ├── reset_password_instructions.html.slim │ │ └── unlock_instructions.html.slim │ ├── passwords │ │ ├── edit.html.slim │ │ └── new.html.slim │ ├── registrations │ │ ├── edit.html.slim │ │ └── new.html.slim │ ├── sessions │ │ └── new.html.slim │ ├── shared │ │ └── _links.slim │ └── unlocks │ │ └── new.html.slim │ ├── errors │ └── error_404.html.slim │ ├── events │ ├── _admin_info.html.slim │ ├── _event-item.rss.slim │ ├── _event.html.slim │ ├── _form.html.slim │ ├── _participants_block.html.slim │ ├── _participate_block.html.slim │ ├── edit.html.slim │ ├── index.atom.builder │ ├── index.html.slim │ ├── index.rss.builder │ ├── new.html.slim │ └── show.html.slim │ ├── layouts │ └── application.html.slim │ ├── my │ ├── authentications │ │ └── _authentication.html.slim │ └── users │ │ ├── edit.html.slim │ │ └── show.html.slim │ ├── pages │ ├── about.ru.html.slim │ ├── communities.html.slim │ ├── donate.html.slim │ ├── manifesto.ru.html.slim │ └── thankyou.html.slim │ ├── shared │ ├── _footer.html.slim │ ├── _nav.html.slim │ ├── _oauth_login_block.html.slim │ ├── _sidebar.html.slim │ └── _small_screens_footer.html.slim │ ├── sitemaps │ └── index.xml.slim │ ├── startups │ ├── _form.html.slim │ ├── _startup.html.slim │ ├── edit.html.slim │ ├── index.html.slim │ ├── new.html.slim │ └── show.html.slim │ ├── turbo │ └── events │ │ ├── _event.rss.builder │ │ └── index.rss.builder │ └── users │ ├── _user-events.html.slim │ ├── _user.html.slim │ ├── index.html.slim │ └── show.html.slim ├── babel.config.js ├── bin ├── annotate ├── bundle ├── byebug ├── cc-tddium-post-worker ├── codeclimate-test-reporter ├── coderay ├── figaro ├── foreman ├── htmldiff ├── it52 ├── launchy ├── ldiff ├── listen ├── mongrel_rpm ├── newrelic ├── newrelic_cmd ├── nokogiri ├── nrdebug ├── oauth ├── pry ├── puma ├── pumactl ├── rackup ├── rails ├── rake ├── rdoc ├── redcarpet ├── restclient ├── ri ├── rollbar-rails-runner ├── rspec ├── rubocop ├── ruby-parse ├── ruby-rewrite ├── safe_yaml ├── sdoc ├── sdoc-merge ├── setup ├── sidekiq ├── sidekiqctl ├── slimrb ├── spring ├── sprockets ├── sync_db ├── thor ├── tilt ├── update ├── webpack ├── webpack-dev-server └── yarn ├── codecov.yml ├── config.ru ├── config ├── REFACTOR.md ├── application.rb ├── application.yml ├── boot.rb ├── cable.yml ├── credentials.yml.enc ├── database.yml ├── deploy.rb ├── deploy │ ├── production.rb │ └── staging.rb ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ ├── staging.rb │ └── test.rb ├── initializers │ ├── apipie.rb │ ├── application_controller_renderer.rb │ ├── asset_sync.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── carrier_wave.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── da_data.rb │ ├── devise.rb │ ├── draper.rb │ ├── filter_parameter_logging.rb │ ├── friendly_id.rb │ ├── high_voltage.rb │ ├── inflections.rb │ ├── kaminari_config.rb │ ├── meta_tags.rb │ ├── mime_types.rb │ ├── new_framework_defaults_5_2.rb │ ├── pluralization.rb │ ├── rollbar.rb │ ├── runtimeerror_notifier.rb │ ├── session_store.rb │ ├── sidekiq.rb │ ├── silencer.rb │ ├── simple_form.rb │ ├── simple_form_bootstrap.rb │ ├── string_to_url_extender.rb │ ├── string_unicode_path.rb │ ├── taggable.rb │ └── wrap_parameters.rb ├── locales │ ├── activerecord.ru.yml │ ├── datetime.ru.yml │ ├── devise.en.yml │ ├── devise.ru.yml │ ├── en.yml │ ├── kaminari-ru.yml │ ├── plurals.rb │ ├── ru.yml │ ├── simple_form.en.yml │ ├── simple_form.ru.yml │ └── telegram.ru.yml ├── newrelic.yml ├── puma.rb ├── routes.rb ├── sidekiq.yml ├── spring.rb ├── storage.yml ├── telegram_channels.yml ├── unicorn │ ├── production.rb │ └── staging.rb ├── webpack │ ├── development.js │ ├── environment.js │ ├── production.js │ └── test.js └── webpacker.yml ├── db ├── migrate │ ├── 20140430090217_sorcery_core.rb │ ├── 20140430090218_sorcery_remember_me.rb │ ├── 20140430090219_sorcery_reset_password.rb │ ├── 20140430090220_sorcery_external.rb │ ├── 20140430090221_sorcery_activity_logging.rb │ ├── 20140430090944_add_name_to_users.rb │ ├── 20140430100247_create_events.rb │ ├── 20140507084053_add_role_to_users.rb │ ├── 20140507093209_add_organizer_referenses_to_events.rb │ ├── 20140507093336_add_published_to_events.rb │ ├── 20140508095102_add_description_and_started_at_to_events.rb │ ├── 20140508105348_create_event_participations.rb │ ├── 20140520095617_add_first_name_and_last_name_to_users.rb │ ├── 20140520095824_add_bio_to_users.rb │ ├── 20140521054705_add_title_image_to_events.rb │ ├── 20140521062142_add_avatar_image_to_users.rb │ ├── 20140521082751_nullable_sorcery_core.rb │ ├── 20140522134058_add_link_to_authentications.rb │ ├── 20140602183636_add_place_to_events.rb │ ├── 20140829113714_add_devise_to_users.rb │ ├── 20140901165216_add_token_to_authentications.rb │ ├── 20140902165236_rename_users_name_to_nickname.rb │ ├── 20140902180100_create_friendly_id_slugs.rb │ ├── 20140902181203_add_slug_to_users.rb │ ├── 20140902183616_add_website_to_user.rb │ ├── 20141111093102_drop_index_users_on_email.rb │ ├── 20141125211802_add_published_at_to_events.rb │ ├── 20141126154826_add_slug_to_events.rb │ ├── 20141127113116_add_subscription_to_users.rb │ ├── 20150516133610_add_point_to_events.rb │ ├── 20181010093500_add_employment_to_users.rb │ ├── 20181011094902_add_foreign_link_to_event.rb │ ├── 20181119192414_add_pageviews_to_events.rb │ ├── 20190301095130_add_kind_to_events.rb │ ├── 20190301180740_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb │ ├── 20190301180741_add_missing_unique_indices.acts_as_taggable_on_engine.rb │ ├── 20190301180742_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb │ ├── 20190301180743_add_missing_taggable_index.acts_as_taggable_on_engine.rb │ ├── 20190301180744_change_collation_for_tag_names.acts_as_taggable_on_engine.rb │ ├── 20190301180745_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb │ ├── 20190605125210_create_donations.rb │ ├── 20190612020134_create_addresses.rb │ ├── 20190612020440_add_address_id_to_event.rb │ └── 20190624125250_create_startups.rb ├── schema.rb └── seeds.rb ├── deploy ├── nginx │ ├── it52.info.conf │ └── metabase.it52.info.conf └── systemd │ ├── it52.service │ └── metabase.service ├── doc └── apipie_examples.json ├── docker ├── Dockerfile ├── Dockerfile.production ├── docker-compose.production.yml └── docker-compose.yml ├── lib ├── assets │ └── .keep ├── capistrano │ └── tasks │ │ └── db.rake ├── da_data.rb ├── da_data │ ├── configuration.rb │ └── request.rb ├── rails │ └── sub_test_task.rb ├── tasks │ └── events.rake └── templates │ └── slim │ └── scaffold │ └── _form.html.slim ├── log └── .keep ├── package.json ├── postcss.config.js ├── public ├── 404.html ├── 422.html ├── 500.html ├── ads.txt ├── app-ads.txt ├── favicon.ico ├── it52_logo_white_clean.svg ├── logo-it52-96x96.png ├── robots.txt └── yandex_637a660a79fbb6d1.html ├── spec ├── controllers │ ├── api │ │ └── v2 │ │ │ ├── events_controller_spec.rb │ │ │ └── tags_controller_spec.rb │ ├── events_controller_spec.rb │ ├── mailchimp_hooks_controller_spec.rb │ ├── sitemaps_controller_spec.rb │ ├── startups_controller_spec.rb │ └── turbo │ │ └── events_controller_spec.rb ├── decorators │ └── event_decorator_spec.rb ├── factories │ ├── addresses.rb │ ├── event.rb │ ├── startups.rb │ └── user.rb ├── fixtures │ ├── dadata_response.json │ └── logo.png ├── lib │ └── da_data │ │ └── request_spec.rb ├── models │ ├── event_spec.rb │ └── user_spec.rb ├── rails_helper.rb ├── spec_helper.rb └── support │ ├── codecov.rb │ ├── database_cleaner.rb │ ├── factory_bot.rb │ ├── helpers │ └── response.rb │ └── webmock.rb ├── start_server.sh ├── swagger.json ├── swagger.yml ├── tsconfig.json └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .byebug_history 2 | .bundle/ 3 | .dockerignore 4 | .env* 5 | .git 6 | .github/* 7 | .gitignore 8 | .idea 9 | .vagrant/* 10 | coverage/* 11 | config/master.key 12 | docker/Dockerfile* 13 | docker/docker-compose.* 14 | log/* 15 | node_modules/* 16 | Procfile* 17 | public/assets/* 18 | public/packs/* 19 | public/packs-test/* 20 | public/system/* 21 | public/sitemap* 22 | public/uploads/* 23 | storage/* 24 | tmp/* 25 | vendor/* 26 | yarn-error.log 27 | 28 | *.sublime-project 29 | *.sublime-workspace 30 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | COMPOSE_PROJECT_NAME=it52 2 | VCS_REF=$(git rev-parse --short HEAD) 3 | BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") 4 | VERSION=latest 5 | REDIS_URL=redis://redis:6379 6 | 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { "browser": true }, 3 | "extends": ["airbnb"], 4 | "plugins": ["@typescript-eslint"], 5 | "parser": "@typescript-eslint/parser", 6 | "parserOptions": { "project": ["./tsconfig.json"] }, 7 | "rules": { 8 | "import/no-unresolved": 0, 9 | "react/jsx-filename-extension": [1, { "extensions": [".jsx", ".tsx"] }] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gemrc: -------------------------------------------------------------------------------- 1 | install: --no-document 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [kugaevsky, r3nya, ujifyxbr, noroot] 4 | patreon: it52 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://www.it52.info/donate 13 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy container to production 2 | on: workflow_dispatch 3 | jobs: 4 | deploy: 5 | name: deploy 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Update and restart docker container 9 | uses: appleboy/ssh-action@master 10 | with: 11 | host: ${{ secrets.DEPLOY_HOST }} 12 | username: ${{ secrets.DEPLOY_USERNAME }} 13 | key: ${{ secrets.DEPLOY_KEY }} 14 | script: sudo /opt/it52/update_docker 15 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-and-push-develpoment.yml: -------------------------------------------------------------------------------- 1 | name: Docker build and push develpoment 2 | on: 3 | push 4 | jobs: 5 | build-development: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - 9 | name: Checkout 10 | uses: actions/checkout@v4 11 | - 12 | name: Login to Docker Hub 13 | uses: docker/login-action@v3 14 | with: 15 | username: ${{ secrets.DOCKER_HUB_USERNAME }} 16 | password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} 17 | - 18 | name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v3 20 | - 21 | name: Build and push 22 | uses: docker/build-push-action@v5 23 | with: 24 | context: ./ 25 | file: ./docker/Dockerfile 26 | build-args: RAILS_MASTER_KEY=${{ secrets.RAILS_MASTER_KEY }} 27 | builder: ${{ steps.buildx.outputs.name }} 28 | push: true 29 | tags: it52/rails:latest 30 | cache-from: type=registry,ref=it52/rails:buildcache-dev 31 | cache-to: type=registry,ref=it52/rails:buildcache-dev,mode=max 32 | -------------------------------------------------------------------------------- /.github/workflows/docker-build-and-push-production.yml: -------------------------------------------------------------------------------- 1 | name: Docker build and push production 2 | on: 3 | push: 4 | branches: 5 | - 'it52' 6 | jobs: 7 | build-production: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - 11 | name: Checkout 12 | uses: actions/checkout@v4 13 | - 14 | name: Login to Docker Hub 15 | uses: docker/login-action@v3 16 | with: 17 | username: ${{ secrets.DOCKER_HUB_USERNAME }} 18 | password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} 19 | - 20 | name: Set up Docker Buildx 21 | uses: docker/setup-buildx-action@v3 22 | - 23 | name: Build and push 24 | uses: docker/build-push-action@v5 25 | with: 26 | context: ./ 27 | file: ./docker/Dockerfile.production 28 | build-args: RAILS_MASTER_KEY=${{ secrets.RAILS_MASTER_KEY }} 29 | builder: ${{ steps.buildx.outputs.name }} 30 | push: true 31 | tags: it52/rails:production 32 | cache-from: type=registry,ref=it52/rails:buildcache-prod 33 | cache-to: type=registry,ref=it52/rails:buildcache-prod,mode=max 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore the default SQLite database. 8 | /db/*.sqlite3 9 | /db/*.sqlite3-journal 10 | 11 | # Ignore all logfiles and tempfiles. 12 | /log/* 13 | /tmp/* 14 | !/log/.keep 15 | !/tmp/.keep 16 | 17 | # Ignore production environment 18 | .env.production 19 | 20 | # Ignore Byebug command history file. 21 | .byebug_history 22 | 23 | # Custom ignorance settings 24 | 25 | /db/*.sqlite3 26 | /db/*.sqlite3-journal 27 | /db/sphinx 28 | 29 | /log/development.sphinx.pid 30 | .tags 31 | .tags_sorted_by_file 32 | .irb-history 33 | nginx_rewrite.txt 34 | .powenv 35 | 36 | *.sublime-project 37 | *.sublime-workspace 38 | .idea 39 | 40 | # Ignore user files and compiled assets 41 | /public/assets 42 | /public/packs 43 | /public/packs-test 44 | /public/sitemap* 45 | /public/system 46 | /public/uploads 47 | 48 | # Ignore test coverage reports 49 | /coverage/ 50 | 51 | # Vagrant vm 52 | .vagrant 53 | 54 | # Ignore master key for decrypting credentials and more. 55 | /config/master.key 56 | 57 | # Ignore javascript dependencies 58 | /node_modules/ 59 | /yarn-error.log 60 | yarn-debug.log* 61 | .yarn-integrity 62 | 63 | # Ignore ruby dependencies 64 | /.bundle 65 | /vendor 66 | 67 | /public/packs 68 | /public/packs-test 69 | /node_modules 70 | /yarn-error.log 71 | yarn-debug.log* 72 | .yarn-integrity 73 | -------------------------------------------------------------------------------- /.old-travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | 3 | services: 4 | - docker 5 | 6 | before_install: 7 | - docker pull it52/rails:latest 8 | 9 | install: 10 | - make build 11 | 12 | before_script: 13 | - docker-compose -f docker/docker-compose.yml run rails sh -c "bin/rails db:create && bin/rails db:schema:load" 14 | 15 | script: 16 | - make test 17 | 18 | before_cache: 19 | - sudo rm -fr coverage public/uploads/* tmp/cache tmp/uploads 20 | 21 | before_deploy: 22 | - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 23 | - docker push it52/rails:latest 24 | 25 | deploy: 26 | provider: script 27 | script: bash -c "make build_and_publish_prod" 28 | on: 29 | branch: it52 30 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require rails_helper 3 | --profile 5 4 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | # The behavior of RuboCop can be controlled via the .rubocop.yml 4 | # configuration file. It makes it possible to enable/disable 5 | # certain cops (checks) and to alter their behavior if they accept 6 | # any parameters. The file can be placed either in your home 7 | # directory or in some project directory. 8 | # 9 | # RuboCop will start looking for the configuration file in the directory 10 | # where the inspected file is and continue its way up to the root directory. 11 | # 12 | # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md 13 | 14 | require: 15 | - rubocop-faker 16 | - rubocop-i18n 17 | - rubocop-md 18 | - rubocop-performance 19 | - rubocop-rails 20 | - rubocop-rspec 21 | 22 | AllCops: 23 | Exclude: 24 | - 'node_modules/**/*' 25 | - 'vendor/**/*' 26 | - '.git/**/*' 27 | - 'bin/**/*' 28 | - 'db/schema.rb' 29 | 30 | Style/FrozenStringLiteralComment: 31 | Enabled: false 32 | 33 | Style/HashSyntax: 34 | Exclude: 35 | - 'app/controllers/events_controller.rb' 36 | - 'lib/da_data/request.rb' 37 | 38 | RSpec/MultipleExpectations: 39 | Max: 5 40 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | it52 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.2.2 2 | -------------------------------------------------------------------------------- /Capfile: -------------------------------------------------------------------------------- 1 | # Load DSL and set up stages 2 | require 'capistrano/setup' 3 | 4 | # Include default deployment tasks 5 | require 'capistrano/deploy' 6 | 7 | # Load the SCM plugin appropriate to your project: 8 | # 9 | # require 'capistrano/scm/hg' 10 | # install_plugin Capistrano::SCM::Hg 11 | # or 12 | # require 'capistrano/scm/svn' 13 | # install_plugin Capistrano::SCM::Svn 14 | # or 15 | require 'capistrano/scm/git' 16 | install_plugin Capistrano::SCM::Git 17 | 18 | # Include tasks from other gems included in your Gemfile 19 | # 20 | # For documentation on these, see for example: 21 | # 22 | # https://github.com/capistrano/rvm 23 | # https://github.com/capistrano/rbenv 24 | # https://github.com/capistrano/chruby 25 | # https://github.com/capistrano/bundler 26 | # https://github.com/capistrano/rails 27 | # https://github.com/capistrano/passenger 28 | # 29 | # require 'capistrano/rvm' 30 | # require 'capistrano/rbenv' 31 | # require 'capistrano/chruby' 32 | # require 'capistrano/bundler' 33 | # require 'capistrano/rails/assets' 34 | # require 'capistrano/rails/migrations' 35 | # require 'capistrano/passenger' 36 | 37 | # Load custom tasks from `lib/capistrano/tasks` if you have any defined 38 | Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2019 [NNRUG](https://github.com/NNRUG) 2 | 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | prepare: 2 | docker-compose -f docker/docker-compose.yml pull rails 3 | docker-compose -f docker/docker-compose.yml run rails sh -c "yarn install && bundle install" 4 | docker-compose -f docker/docker-compose.yml run rails sh -c "bin/rails db:setup" 5 | 6 | build: 7 | docker build -f docker/Dockerfile -t it52/rails:latest --cache-from it52/rails:latest . 8 | 9 | lint: 10 | docker-compose -f docker/docker-compose.yml run rails sh -c "bin/rubocop && yarn run lint" 11 | 12 | rspec: 13 | docker-compose -f docker/docker-compose.yml run rails sh -c "bundle exec rspec" 14 | 15 | test: lint rspec 16 | 17 | build_prod: 18 | docker build -f docker/Dockerfile.production -t it52/rails:production --build-arg RAILS_MASTER_KEY --cache-from it52/rails:production . 19 | 20 | publish_prod: 21 | docker push it52/rails:production 22 | 23 | build_and_publish_prod: build_prod publish_prod 24 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake, 4 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 5 | 6 | require_relative 'config/application' 7 | require 'rake/testtask' 8 | 9 | Rails.application.load_tasks 10 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.3 2 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link application.css 2 | //= link_tree ../fonts 3 | //= link_tree ../images 4 | -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-Bold.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-BoldItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-BoldItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-CondensedBlack.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-CondensedBlack.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-CondensedBold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-CondensedBold.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Italic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-Italic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-Light.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-LightItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-LightItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-Medium.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-MediumItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-MediumItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Thin.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-Thin.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-ThinItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-ThinItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-UltraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-UltraLight.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-UltraLightItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue-UltraLightItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/fonts/HelveticaNeue.otf -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/avatars_fallback/default.png -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/square_150_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/avatars_fallback/square_150_default.png -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/square_25_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/avatars_fallback/square_25_default.png -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/square_50_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/avatars_fallback/square_50_default.png -------------------------------------------------------------------------------- /app/assets/images/events_fallback/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/events_fallback/default.png -------------------------------------------------------------------------------- /app/assets/images/events_fallback/fb_1200_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/events_fallback/fb_1200_default.png -------------------------------------------------------------------------------- /app/assets/images/events_fallback/square_500_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/events_fallback/square_500_default.png -------------------------------------------------------------------------------- /app/assets/images/google-play-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/google-play-badge.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52-logo-144x144.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52-logo-16x16.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52-logo-180x180.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52-logo-192x192.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52-logo-32x32.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52-logo-96x96.png -------------------------------------------------------------------------------- /app/assets/images/it52_favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52_favicon.ico -------------------------------------------------------------------------------- /app/assets/images/it52_logo_fb@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/assets/images/it52_logo_fb@2x.png -------------------------------------------------------------------------------- /app/assets/stylesheets/app.sass: -------------------------------------------------------------------------------- 1 | @use "sass:math" 2 | 3 | // Sass 4 | @import "font-awesome-sprockets" 5 | @import "font-awesome" 6 | 7 | @import "theme/variables" 8 | @import "theme/type" 9 | 10 | @import "theme/bootstrap_and_overrides" 11 | 12 | @import "theme/common_styles" 13 | @import "theme/typography" 14 | 15 | @import "events" 16 | @import "user_profiles" 17 | 18 | // CSS 19 | @import "simplemde/dist/simplemde.min" 20 | @import "flatpickr/dist/flatpickr" 21 | @import "flatpickr/dist/themes/airbnb" 22 | 23 | // Material 24 | @import "material" 25 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any styles 10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new 11 | * file per style scope. 12 | * 13 | *= require app 14 | */ 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/user_profiles.sass: -------------------------------------------------------------------------------- 1 | .user-profile-preview 2 | @media (min-width: $screen-sm) 3 | text-align: center 4 | @media (min-width: $screen-md) 5 | margin-bottom: $line-height-computed 6 | a 7 | color: $text-color 8 | display: block 9 | .avatar 10 | margin-bottom: 1em 11 | 12 | .user-profile-page, 13 | .edit_user 14 | .avatar 15 | max-width: 150px 16 | -------------------------------------------------------------------------------- /app/controllers/api/v1/api_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V1 5 | class ApiController < ApplicationController 6 | # before_action :authenticate_with_basic 7 | before_action :set_default_options 8 | before_action :set_allow_cors_headers 9 | 10 | protected 11 | 12 | def callback 13 | params[:callback] 14 | end 15 | 16 | def set_allow_cors_headers 17 | headers['Access-Control-Allow-Origin'] = '*' 18 | headers['Access-Control-Allow-Methods'] = 'GET' 19 | headers['Access-Control-Request-Method'] = 'OPTIONS' 20 | headers['Access-Control-Allow-Headers'] = 'Content-Type' 21 | end 22 | 23 | def set_default_options 24 | @default_options = { root: false } 25 | end 26 | 27 | def render_options 28 | @default_options[:json] = @response_object 29 | callback.present? ? @default_options.merge(callback: callback) : @default_options 30 | end 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /app/controllers/api/v1/events_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V1 5 | class EventsController < ApiController 6 | load_and_authorize_resource 7 | 8 | before_action :prepare_model 9 | 10 | # resource_description do 11 | # short 'События' 12 | # formats ['json'] 13 | # api_version "v1" 14 | # api_base_url 'api/v1/events' 15 | # end 16 | 17 | # api :GET, '/', 'Получить список событий за текущий год' 18 | # api :GET, '/in/:year', 'Получить список событий за указанный год' 19 | # param :year, /\d{4}/, desc: "Year", required: false 20 | def index 21 | year = params[:year].present? ? params[:year].to_i : Time.zone.now.year 22 | month = params[:month].present? ? params[:month].to_i : nil 23 | @response_object = @model.published.held_in(year, month) 24 | render render_options 25 | end 26 | 27 | # api :GET, '/:id', 'Получить информацию по событию' 28 | # param :id, /\d+/, desc: "Event ID", required: true 29 | def show 30 | @response_object = @model.find(params[:id]) 31 | render render_options 32 | end 33 | 34 | private 35 | 36 | def prepare_model 37 | @model = Event.includes(:participants, participants: :authentications) 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /app/controllers/api/v1/users_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V1 5 | class UsersController < ApiController 6 | # resource_description do 7 | # short 'Участники' 8 | # formats ['json'] 9 | # param :id, /\d+/, desc: "User ID", required: true 10 | # api_version "v1" 11 | # api_base_url 'api/v1/users' 12 | # end 13 | 14 | # api :GET, '/:id', 'Получить данные пользователя' 15 | def show 16 | @response_object = User.find(params[:id]) 17 | render render_options 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/controllers/api/v2/api_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V2 5 | class ApiController < ActionController::API 6 | before_action :set_allow_cors_headers 7 | 8 | rescue_from ActiveRecord::RecordNotFound, with: :record_not_found 9 | 10 | protected 11 | 12 | def set_allow_cors_headers 13 | headers['Access-Control-Allow-Origin'] = '*' 14 | headers['Access-Control-Allow-Methods'] = 'GET' 15 | headers['Access-Control-Request-Method'] = 'OPTIONS' 16 | headers['Access-Control-Allow-Headers'] = 'Content-Type' 17 | end 18 | 19 | private 20 | 21 | def record_not_found 22 | head 404 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/controllers/api/v2/events_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V2 5 | class EventsController < ApiController 6 | before_action :prepare_model 7 | 8 | def index 9 | @events = @model.order(published_at: :desc) 10 | @events = @events.tagged_with(params[:tag]) if params[:tag].present? 11 | @events = @events.page(params[:page] || 1) 12 | options = { include: %i[organizer], 13 | is_collection: true, 14 | params: { action: action_name }, 15 | links: { self: events_url(page: @events.current_page), 16 | next: events_url(page: @events.next_page), 17 | prev: events_url(page: @events.prev_page) }, 18 | meta: { total_count: @events.total_count, 19 | total_pages: @events.total_pages } } 20 | render json: ::V2::EventSerializer.new(@events, options).serializable_hash 21 | end 22 | 23 | def show 24 | @event = @model.find(params[:id]) 25 | options = { include: %i[organizer participants], 26 | is_collection: false, 27 | params: { action: action_name }, 28 | links: { self: event_url(@event) } } 29 | render json: ::V2::EventSerializer.new(@event, options).serializable_hash 30 | end 31 | 32 | private 33 | 34 | def prepare_model 35 | @model = Event.includes(:organizer, :participants).published 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /app/controllers/api/v2/tags_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V2 5 | class TagsController < ApiController 6 | TAGS_PAGE_SIZE = 50 7 | 8 | def index 9 | @tags = ActsAsTaggableOn::Tag.order(taggings_count: :desc) 10 | if params[:q].present? 11 | @tags = @tags.where('name ILIKE ?', "#{params[:q].to_s.downcase}%") 12 | end 13 | options = { is_collection: true, 14 | params: { action: action_name }, 15 | meta: { totalCount: @tags.count } } 16 | render json: ::V2::TagSerializer.new(@tags.limit(TAGS_PAGE_SIZE), options).serializable_hash 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_dependency 'my' 4 | 5 | class ApplicationController < ActionController::Base 6 | # include Styx::Initializer 7 | 8 | # Prevent CSRF attacks by raising an exception. 9 | # For APIs, you may want to use :null_session instead. 10 | protect_from_forgery prepend: true, with: :exception 11 | 12 | add_flash_types :error, :failure, :success, :alert 13 | 14 | before_action :define_common_meta_tags, only: %i[index show new edit] 15 | before_action :authenticate_user!, if: -> { authenticated_path? } 16 | 17 | rescue_from CanCan::AccessDenied do |exception| 18 | redirect_back(fallback_location: root_path, error: exception.message) 19 | end 20 | 21 | def after_sign_in_path_for(resource) 22 | request.env['omniauth.origin'] || 23 | stored_location_for(resource) || 24 | root_path 25 | end 26 | 27 | private 28 | 29 | def define_common_meta_tags 30 | set_meta_tags( 31 | site: t(:app_name), 32 | description: t(:app_description), 33 | keywords: t(:app_keywords), 34 | reverse: true, 35 | charset: 'utf-8', 36 | og: { 37 | site_name: :site, 38 | locale: 'ru_RU' 39 | } 40 | ) 41 | end 42 | 43 | def authenticated_path? 44 | controller_path.split('/').first == 'my' || new_event_path == request.original_fullpath 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/errors_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ErrorsController < ApplicationController 4 | layout false 5 | 6 | def error_404; end 7 | 8 | def image 9 | redirect_to build_attachment_path, status: :permanent_redirect 10 | end 11 | 12 | private 13 | 14 | def build_attachment_path 15 | production_prefix = 'https://assets.it52.info' 16 | [production_prefix, request.path.gsub('uploads/development', 'uploads/production')].join 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/controllers/event_participations_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class EventParticipationsController < ApplicationController 4 | respond_to :html 5 | load_and_authorize_resource param_method: :event_participation_params 6 | 7 | def create 8 | @event_participation.user = current_user || nil 9 | @event_participation.save! 10 | 11 | flash[:success] = t(:event_participation_created, title: @event_participation.event.title) 12 | if @event_participation.event.foreign_link.present? 13 | return redirect_to @event_participation.event.user_foreign_link(current_user) 14 | end 15 | 16 | redirect_back(fallback_location: root_path) 17 | end 18 | 19 | def destroy 20 | @event_participation.destroy! 21 | 22 | flash[:success] = t(:event_participation_canceled, title: @event_participation.event.title) 23 | redirect_back(fallback_location: root_path) 24 | end 25 | 26 | private 27 | 28 | def event_participation_params 29 | params.require(:event_participation).permit(:event_id) 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /app/controllers/letsencrypt_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class LetsencryptController < ApplicationController 4 | # skip_before_action :verify_authenticity_token 5 | 6 | def approve 7 | render text: ENV.fetch('letsencrypt_token') { 'letsencrypt_token' } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/mailchimp_hooks_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MailchimpHooksController < ApplicationController 4 | # skip_before_action :verify_authenticity_token 5 | before_action :set_user, only: :update_subscription 6 | 7 | def update_subscription 8 | subscription = case subscribe_params[:type] 9 | when 'subscribe' 10 | true 11 | when 'unsubscribe' 12 | false 13 | else 14 | @user.subscription 15 | end 16 | status = @user.update(subscription: subscription) ? :ok : :unprocessable_entity 17 | head status 18 | end 19 | 20 | def check 21 | head :ok 22 | end 23 | 24 | private 25 | 26 | def subscribe_params 27 | params.permit(:token, :type, :fired_at, data: [:action, :reason, :id, :list_id, :email, :email_type, :web_id, :ip_opt, :ip_signup, merges: []]) 28 | end 29 | 30 | def set_user 31 | @user = User.find_by(email: subscribe_params[:data][:email]) 32 | rescue ActiveRecord::RecordNotFound 33 | head :unprocessable_entity 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /app/controllers/my.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module My 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/my/authentications_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module My 4 | class AuthenticationsController < ApplicationController 5 | before_action :set_user_and_auth 6 | 7 | def destroy 8 | if @user.authentications.size == 1 && @user.email.blank? 9 | flash[:danger] = t('authentications.not_destroyed') 10 | else 11 | @authentication.destroy 12 | flash[:success] = t('authentications.destroyed', provider: @authentication.provider.capitalize) 13 | end 14 | redirect_to my_profile_path 15 | end 16 | 17 | private 18 | 19 | def set_user_and_auth 20 | @user = current_user 21 | @authentication = @user.authentications.find(params[:id]) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /app/controllers/my/users_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module My 4 | class UsersController < ApplicationController 5 | respond_to :html 6 | responders :flash 7 | 8 | before_action :set_user 9 | after_action :sync_with_mailchimp, only: :update 10 | 11 | def show 12 | @user = @user.decorate 13 | respond_with @user 14 | end 15 | 16 | def edit 17 | respond_with @user 18 | end 19 | 20 | def update 21 | location = @user.update(user_profile_params) ? my_profile_path : edit_my_profile_path 22 | respond_with @user, location: location 23 | end 24 | 25 | private 26 | 27 | def set_user 28 | @user = current_user 29 | authorize! :manage, @user 30 | end 31 | 32 | def user_profile_params 33 | params.require(:user).permit(:first_name, :last_name, :nickname, :employment, 34 | :website, :bio, :avatar_image, :avatar_image_cache, :subscription) 35 | end 36 | 37 | def sync_with_mailchimp 38 | attributes = %i[first_name last_name subscription] 39 | @user.reload 40 | if attributes.any? { |attribute| @user.send(attribute) != user_profile_params[attribute] } 41 | @user.sync_with_mailchimp 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /app/controllers/omniauth_callbacks_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class OmniauthCallbacksController < Devise::OmniauthCallbacksController 4 | %i[facebook github twitter vkontakte google_oauth2].each do |provider| 5 | define_method provider do 6 | auth_for provider 7 | end 8 | end 9 | 10 | private 11 | 12 | def auth_for(kind) 13 | session['devise.oauth_data'] = nil 14 | @user = User.from_omniauth(auth_params, current_user) 15 | @authentication = @user.authentications.find do |a| 16 | a.uid == auth_params[:uid] && a.provider == auth_params[:provider] 17 | end 18 | 19 | if @user.persisted? 20 | if is_navigational_format? 21 | set_flash_message(:notice, :success, kind: kind.to_s.capitalize) 22 | end 23 | sign_in_and_redirect @user, event: :authentication 24 | else 25 | session['devise.oauth_data'] = auth_params 26 | render 'devise/sessions/new', error: "Не получилось войти с помощью #{kind}." 27 | end 28 | end 29 | 30 | def auth_params 31 | request.env['omniauth.auth'].with_indifferent_access 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /app/controllers/pages_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PagesController < ApplicationController 4 | include HighVoltage::StaticPage 5 | 6 | before_action :set_telegram_domain, if: -> { params[:id] == 'communities' } 7 | 8 | private 9 | 10 | def set_telegram_domain 11 | @telegram_domain = ENV.fetch('telegram_domain') { 't.me' } 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/controllers/sitemaps_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SitemapsController < ApplicationController 4 | respond_to :xml 5 | 6 | def index 7 | @events = Event.published 8 | @startups = Startup.all 9 | @pages = HighVoltage.page_ids 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/telegram_hooks_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TelegramHooksController < ApplicationController 4 | # skip_before_action :verify_authenticity_token 5 | 6 | after_action :track_bot_request 7 | 8 | def process_bot_request 9 | @req = Telegram::Request.new bot_request_params 10 | @req.reply! 11 | rescue NoMethodError => e 12 | Rails.logger.error 'Something went wrong' 13 | ensure 14 | render nothing: true, status: :ok 15 | end 16 | 17 | private 18 | 19 | def track_bot_request 20 | token = ENV.fetch('botan_token') { 'botan_token' } 21 | message = { text: @req.text } 22 | action = if @req.action 23 | @req.action.first 24 | else 25 | 'Unkown' 26 | end 27 | puts Telegram::Botan.track(token, @req.user_id, message, action) 28 | rescue StandardError => e 29 | puts e.message 30 | end 31 | 32 | def bot_request_params 33 | params.permit! 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /app/controllers/turbo/events_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Turbo 4 | class EventsController < ApplicationController 5 | respond_to :rss 6 | 7 | def index 8 | @events = Event.includes(:event_participations, :participants, :organizer) 9 | .order(published_at: :asc) 10 | .published.decorate 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UsersController < ApplicationController 4 | respond_to :html 5 | 6 | def index 7 | @users = User.order(:slug).page(params[:page]) 8 | end 9 | 10 | def show 11 | @user = User.friendly.find(params[:id]).decorate 12 | @owned_events = @user.owner_of_events.visible_by_user(current_user) 13 | @attended_events = @user.member_in_events.visible_by_user(current_user) 14 | respond_with @user 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/decorators/authentication_decorator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AuthenticationDecorator < Draper::Decorator 4 | delegate_all 5 | 6 | # Define presentation-specific methods here. Helpers are accessed through 7 | # `helpers` (aka `h`). You can override attributes, for example: 8 | # 9 | # def created_at 10 | # helpers.content_tag :span, class: 'time' do 11 | # object.created_at.strftime("%a %m/%d/%y") 12 | # end 13 | # end 14 | 15 | def link_to_social(css_classes = []) 16 | @css_classes = css_classes 17 | h.link_to object.link, class: css_class, target: :_blank, rel: :noopener do 18 | [icon, h.t("social.#{authentication.provider}.name")].join(' ').html_safe 19 | end 20 | end 21 | 22 | def link_to_destroy(css_classes = []) 23 | @css_classes = css_classes 24 | h.link_to h.my_authentication_path(object), method: :delete, class: css_class, data: { confirm: h.t('authentications.unlink') } do 25 | h.content_tag :i, '', class: 'fas fa-times' 26 | end 27 | end 28 | 29 | def icon 30 | h.content_tag :i, '', class: "fab fa-#{object.provider}" 31 | end 32 | 33 | private 34 | 35 | def css_class 36 | return "btn btn-#{object.provider}" if @css_classes.empty? 37 | 38 | @css_classes.join(' ') 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /app/decorators/user_decorator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UserDecorator < Draper::Decorator 4 | delegate_all 5 | 6 | decorates_association :authentications 7 | 8 | # Define presentation-specific methods here. Helpers are accessed through 9 | # `helpers` (aka `h`). You can override attributes, for example: 10 | # 11 | # def created_at 12 | # helpers.content_tag :span, class: 'time' do 13 | # object.created_at.strftime("%a %m/%d/%y") 14 | # end 15 | # end 16 | 17 | def bio 18 | markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(autolink: true, filter_html: true, hard_wrap: true)) 19 | markdown.render(object.bio || '').html_safe 20 | end 21 | 22 | def link_to_website 23 | if object.website? 24 | h.link_to object.website, object.website, target: :_blank, rel: :noopener 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | def render_editor? 5 | controller.controller_name == 'events' && !%w[index show].include?(controller.action_name) 6 | end 7 | 8 | def logo_class 9 | return 'user' if current_user&.member? 10 | return 'root' if current_user&.admin? 11 | 12 | '' 13 | end 14 | 15 | def meta_t(key) 16 | I18n.t("meta.#{controller_name}.#{action_name}.#{key}") 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/helpers/events_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module EventsHelper 4 | def admin_event_icon_class(event) 5 | if event.published? 6 | 'fa-eye' 7 | else 8 | 'fa-eye-slash' 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/javascript/packs/application.ts: -------------------------------------------------------------------------------- 1 | import * as Turbolinks from 'turbolinks'; 2 | import railsUjs from '@rails/ujs'; 3 | 4 | import { ForeignLinkSwitcher } from './helpers/foreign-link-switcher'; 5 | import { MdcInit } from './mdc/mdc-init'; 6 | import { YandexInit } from './yandex/yandex-init'; 7 | 8 | Turbolinks.start(); 9 | railsUjs.start(); 10 | 11 | function init(): void { 12 | const foreignLinkCheckbox = document.getElementById('has_foreign_link'); 13 | if (foreignLinkCheckbox) ForeignLinkSwitcher.init(); 14 | MdcInit.init(); 15 | YandexInit.init(); 16 | 17 | let uuid = null; 18 | const uuidEl = document.getElementById('uuid'); 19 | if (uuidEl) uuid = uuidEl.dataset.userId; 20 | if (typeof ga === 'function') { 21 | ga('set', '&uid', uuid); 22 | ga('set', 'location', location.href); 23 | ga('send', 'pageview'); 24 | } 25 | } 26 | 27 | document.addEventListener('turbolinks:load', init); 28 | init(); 29 | -------------------------------------------------------------------------------- /app/javascript/packs/editor.ts: -------------------------------------------------------------------------------- 1 | import * as SimpleMDE from 'simplemde'; 2 | import flatpickr from 'flatpickr'; 3 | import { Russian } from 'flatpickr/dist/l10n/ru'; 4 | 5 | function hasEditor(): boolean { 6 | return document.querySelectorAll('.editor-toolbar').length > 0; 7 | } 8 | 9 | function init(event?: Event): void { 10 | flatpickr('#event_started_at', { 11 | enableTime: true, 12 | minuteIncrement: 15, 13 | time_24hr: true, 14 | defaultHour: 19, 15 | dateFormat: 'd.m.Y H:i', 16 | minDate: 'today', 17 | locale: Russian, 18 | }); 19 | 20 | const simplemdeElements = document.querySelectorAll('.mde-textarea'); 21 | if (simplemdeElements.length > 0 && !hasEditor()) { 22 | simplemdeElements.forEach((el) => { 23 | new SimpleMDE({ 24 | element: el, 25 | indentWithTabs: false, 26 | promptURLs: true, 27 | spellChecker: false, 28 | hideIcons: ['image'], 29 | }); 30 | }); 31 | } 32 | } 33 | 34 | document.addEventListener('turbolinks:load', init); 35 | init(); 36 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/mailers/.keep -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/models/.keep -------------------------------------------------------------------------------- /app/models/ability.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Ability 4 | include CanCan::Ability 5 | 6 | def initialize(user) 7 | user ||= User.new 8 | 9 | can :read, Event, published: true 10 | can :manage, User, id: user.id 11 | can :read, Startup 12 | 13 | if user.member? 14 | can :read, Startup 15 | can :create, Startup 16 | can :manage, Startup, author_id: user.id 17 | 18 | can :create, Event 19 | can :read, Event, organizer_id: user.id 20 | can :update, Event, organizer_id: user.id 21 | can :download_participants, Event, organizer_id: user.id 22 | can :destroy, Event, organizer_id: user.id 23 | cannot :publish, Event 24 | 25 | can :create, EventParticipation 26 | can :destroy, EventParticipation, user_id: user.id 27 | end 28 | 29 | if user.admin? 30 | can :manage, Startup 31 | can :manage, Event 32 | can :publish, Event 33 | can :manage, EventParticipation 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationRecord < ActiveRecord::Base 4 | self.abstract_class = true 5 | 6 | delegate :url_helpers, to: 'Rails.application.routes' 7 | end 8 | -------------------------------------------------------------------------------- /app/models/authentication.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: authentications 6 | # 7 | # id :integer not null, primary key 8 | # user_id :integer not null 9 | # provider :string(255) not null 10 | # uid :string(255) not null 11 | # created_at :datetime 12 | # updated_at :datetime 13 | # link :string(255) 14 | # token :string(255) 15 | # token_expires :datetime 16 | # 17 | 18 | class Authentication < ApplicationRecord 19 | validates :uid, uniqueness: { scope: :provider }, presence: true 20 | validates :provider, presence: true 21 | 22 | belongs_to :user, touch: true 23 | 24 | def set_attributes_from_omniauth(auth) 25 | urls = auth['info']['urls'] 26 | if urls.present? 27 | self.link = urls['GitHub'] || urls['Twitter'] || urls['Facebook'] || urls['Vkontakte'] || urls['Google'] 28 | end 29 | self.link ||= auth['extra']['raw_info']['link'] 30 | self.token = auth['credentials']['token'] 31 | self.token_expires = auth['credentials']['expires_at'] 32 | self 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /app/models/calendar.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Calendar 4 | DOMAIN = ENV.fetch('mailing_host') { 'mailing_host' } 5 | DEFAULTS = { 6 | prodid: "-//#{DOMAIN}//IT events calendar//RU", 7 | url: Rails.application.routes.url_helpers.events_url(host: DOMAIN), 8 | source: Rails.application.routes.url_helpers.events_url(host: DOMAIN, format: :ics), 9 | name: 'IT events calendar', 10 | description: 'All IT events in 52 region' 11 | }.with_indifferent_access 12 | 13 | attr_reader :ical, :events 14 | 15 | def initialize(events) 16 | @events = events 17 | @ical = Icalendar::Calendar.new 18 | @ical.prodid = DEFAULTS[:prodid] 19 | @ical.timezone do |t| 20 | t.tzid = Rails.configuration.time_zone 21 | end 22 | if events.respond_to?(:each) 23 | @events.each { |event| @ical.add_event(event.to_ics) } 24 | else 25 | @ical.add_event(events.to_ics) 26 | end 27 | @ical.publish 28 | end 29 | 30 | def to_ical 31 | lines = @ical.to_ical.lines 32 | injection = %i[url source name description].map do |key| 33 | [key.to_s.upcase, DEFAULTS[key]].join(':') 34 | end.join("\r\n") 35 | injection << "\r\nREFRESH-INTERVAL;VALUE=DURATION:PT12H\r\n" 36 | injection << "X-PUBLISHED-TTL:PT12H\r\n" 37 | lines.insert(4, injection).join 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/event_participation.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: event_participations 6 | # 7 | # id :integer not null, primary key 8 | # user_id :integer 9 | # event_id :integer 10 | # created_at :datetime 11 | # updated_at :datetime 12 | # 13 | 14 | class EventParticipation < ApplicationRecord 15 | belongs_to :user 16 | belongs_to :event 17 | 18 | validates :user_id, uniqueness: { scope: :event_id } 19 | end 20 | -------------------------------------------------------------------------------- /app/models/telegram.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Telegram 4 | API_KEY = ENV.fetch('telegram_bot_token') { 'telegram_bot_token' } 5 | CHAT_ID = ENV.fetch('telegram_chat_id') { 'telegram_chat_id' } 6 | BASE_URI = 'https://api.telegram.org' 7 | 8 | class ParseError < StandardError; end 9 | class LongMessageError < StandardError; end 10 | class Error < StandardError; end 11 | end 12 | -------------------------------------------------------------------------------- /app/models/telegram/botan.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Telegram 4 | module Botan 5 | require 'net/http' 6 | require 'net/https' 7 | require 'json' 8 | 9 | URI_TEMPLATE = 'https://api.botan.io/track?token=%{token}&uid=%{uid}&name=%{name}' 10 | 11 | def self.track(token, uid, message, name = 'Message') 12 | uri = URI(format(URI_TEMPLATE, token: token, uid: uid, name: name)) 13 | puts uri 14 | http = Net::HTTP.new(uri.host, uri.port) 15 | http.use_ssl = true 16 | http.verify_mode = OpenSSL::SSL::VERIFY_NONE 17 | body = JSON.dump(message) 18 | 19 | req = Net::HTTP::Post.new(uri) 20 | req.add_field 'Content-type', 'application/json' 21 | req.body = body 22 | # Fetch Request 23 | res = http.request(req) 24 | JSON.parse(res.body) 25 | rescue StandardError => e 26 | puts "HTTP Request failed (#{e.message})" 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /app/models/telegram/channel.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Telegram 4 | class Channel 5 | def self.groups 6 | @groups ||= YAML.load_file(Rails.root.join('config', 'telegram_channels.yml')).deep_symbolize_keys[:groups] 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/serializers/authentication_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: authentications 6 | # 7 | # id :integer not null, primary key 8 | # user_id :integer not null 9 | # provider :string(255) not null 10 | # uid :string(255) not null 11 | # created_at :datetime 12 | # updated_at :datetime 13 | # link :string(255) 14 | # token :string(255) 15 | # token_expires :datetime 16 | # 17 | 18 | class AuthenticationSerializer < ActiveModel::Serializer 19 | cache key: 'authentication', expires_in: 3.hours 20 | attributes :id, :provider, :link 21 | end 22 | -------------------------------------------------------------------------------- /app/serializers/event_brief_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class EventBriefSerializer < ActiveModel::Serializer 4 | cache key: 'event', expires_in: 3.hours 5 | 6 | attributes :id, :title, :description, :image_url, :place, :started_at, :started_at_js, :location, :tag_list 7 | 8 | def image_url 9 | object.title_image.square_500.url 10 | end 11 | 12 | def started_at_js 13 | object.started_at.to_f * 1000 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/serializers/event_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: events 6 | # 7 | # id :integer not null, primary key 8 | # title :string(255) not null 9 | # created_at :datetime 10 | # updated_at :datetime 11 | # organizer_id :integer 12 | # published :boolean default(FALSE) 13 | # description :text 14 | # started_at :datetime 15 | # title_image :string(255) 16 | # place :string(255) 17 | # published_at :datetime 18 | # slug :string(255) 19 | # location :point 20 | # foreign_link :string 21 | # pageviews :integer default(0) 22 | # kind :integer default("event") 23 | # address_id :bigint 24 | # address_comment :string 25 | # 26 | 27 | class EventSerializer < ActiveModel::Serializer 28 | cache key: 'event', expires_in: 3.hours 29 | attributes :id, :title, :description, :image_url, :place, :started_at, :started_at_js, :url, :location, :organizer, :tag_list 30 | 31 | has_many :participants, each_serializer: UserSerializer 32 | belongs_to :organizer 33 | 34 | def image_url 35 | object.title_image.square_500.url 36 | end 37 | 38 | def started_at_js 39 | object.started_at.to_f * 1000 40 | end 41 | 42 | def url 43 | Rails.application.routes.url_helpers.event_url(object, host: ENV.fetch('mailing_host') { 'mailing_host' }) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /app/serializers/startup_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class StartupSerializer < ActiveModel::Serializer 4 | attributes :id, :name, :url, :logo, :description, :contacts 5 | end 6 | -------------------------------------------------------------------------------- /app/serializers/v2/event_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module V2 4 | class EventSerializer 5 | include FastJsonapi::ObjectSerializer 6 | 7 | cache_options enabled: true, cache_length: 1.day 8 | set_key_transform :camel_lower 9 | 10 | attributes :title, :created_at, :updated_at, :started_at, :published, :description, :title_image, :place, :slug, :foreign_link, :pageviews, :kind, :tag_list 11 | 12 | attribute :participants_count 13 | 14 | belongs_to :organizer, record_type: :user, serializer: :user 15 | has_many :participants, record_type: :user, 16 | serializer: :user, 17 | if: proc { |_record, params| params[:action] != 'index' } 18 | 19 | link :url do |object| 20 | Rails.application.routes.url_helpers.event_url(object, host: ENV.fetch('mailing_host') { 'it52.info' }) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/serializers/v2/tag_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module V2 4 | class TagSerializer 5 | include FastJsonapi::ObjectSerializer 6 | 7 | set_key_transform :camel_lower 8 | 9 | attributes :name, :taggings_count 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/serializers/v2/user_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module V2 4 | class UserSerializer 5 | include FastJsonapi::ObjectSerializer 6 | 7 | cache_options enabled: true, cache_length: 1.day 8 | set_key_transform :camel_lower 9 | 10 | attributes :created_at, :updated_at, :nickname, :role, :first_name, :last_name, :bio, :avatar_image, :slug, :website, :subscription, :employment 11 | 12 | link :url do |object| 13 | Rails.application.routes.url_helpers.user_url(object, host: ENV.fetch('mailing_host') { 'it52.info' }) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/services/extract_event_address_service.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ExtractEventAddressService 4 | def initialize(event) 5 | @event = event 6 | end 7 | 8 | def call 9 | suggestions = DaData::Request.suggest_address(@event.place) 10 | fias_id = suggestions['suggestions'][0]['data']['fias_id'] 11 | data = DaData::Request.find_by(id: fias_id) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/services/render_ar_collection_to_csv.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'csv' 4 | 5 | class RenderArCollectionToCsv 6 | def self.perform(collection, column_names = nil, options = {}) 7 | column_names ||= collection.table_name.singularize.capitalize.constantize.column_names 8 | 9 | CSV.generate(**options) do |csv| 10 | csv << column_names 11 | collection.each do |collection_item| 12 | csv << column_names.map { |method_name| collection_item.send(method_name) } 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/uploaders/concerns/uploader_concern.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module UploaderConcern 4 | extend ActiveSupport::Concern 5 | 6 | included do 7 | include CarrierWave::Vips 8 | 9 | process :optimize 10 | process :strip 11 | end 12 | 13 | def optimize 14 | manipulate! do |image| 15 | image.thumbnail_image(image.width) 16 | end 17 | end 18 | 19 | # Override the directory where uploaded files will be stored. 20 | # This is a sensible default for uploaders that are meant to be mounted: 21 | def store_dir 22 | "uploads/#{Rails.env}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 23 | end 24 | 25 | # Add a white list of extensions which are allowed to be uploaded. 26 | # For images you might use something like this: 27 | def extension_white_list 28 | %w[jpg jpeg png] 29 | end 30 | 31 | def content_type_whitelist 32 | %r{image/} 33 | end 34 | 35 | # Override the filename of the uploaded files: 36 | # Avoid using model.id or version_name here, see uploader/store.rb for details. 37 | def filename 38 | "#{secure_token(10)}.#{file.extension}" if original_filename.present? 39 | end 40 | 41 | protected 42 | 43 | def secure_token(length = 16) 44 | var = :"@#{mounted_as}_secure_token" 45 | model.instance_variable_get(var) || model.instance_variable_set(var, SecureRandom.hex(length / 2)) 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /app/uploaders/event_title_image_uploader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class EventTitleImageUploader < CarrierWave::Uploader::Base 4 | include UploaderConcern 5 | 6 | def default_url 7 | ActionController::Base.helpers.asset_path('events_fallback/' + [version_name, 'default.png'].compact.join('_')) 8 | end 9 | 10 | version :square_500 do 11 | process resize_to_fit: [500, 500] 12 | end 13 | 14 | version :fb_1200 do 15 | process resize_to_fill: [1200, 630] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/uploaders/startup_logo_uploader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class StartupLogoUploader < CarrierWave::Uploader::Base 4 | include UploaderConcern 5 | 6 | def default_url 7 | ActionController::Base.helpers.asset_path('avatars_fallback/' + [version_name, 'default.png'].compact.join('_')) 8 | end 9 | 10 | version :big do 11 | process resize_to_fit: [512, 512] 12 | end 13 | 14 | version :medium do 15 | process resize_to_fit: [256, 256] 16 | end 17 | 18 | version :small do 19 | process resize_to_fit: [32, 32] 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/uploaders/user_avatar_uploader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UserAvatarUploader < CarrierWave::Uploader::Base 4 | include UploaderConcern 5 | 6 | def default_url 7 | ActionController::Base.helpers.asset_path('avatars_fallback/' + [version_name, 'default.png'].compact.join('_')) 8 | end 9 | 10 | version :square_25 do 11 | process resize_to_fill: [25, 25] 12 | end 13 | 14 | version :square_50 do 15 | process resize_to_fill: [50, 50] 16 | end 17 | 18 | version :square_150 do 19 | process resize_to_fill: [150, 150] 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/views/authentications/_authentication.html.slim: -------------------------------------------------------------------------------- 1 | li = link_to authentication.link_to_social 2 | -------------------------------------------------------------------------------- /app/views/authentications/_unlinked.html.slim: -------------------------------------------------------------------------------- 1 | - icon = t("social.#{provider}.icon") 2 | 3 | li = link_to omniauth_authorize_path(:user, provider), class: %(btn btn-#{icon} btn-social), :"data-turbolinks" => false do 4 | i.fab> class="fa-#{icon}" 5 | span< = t("social.#{provider}.name") 6 | -------------------------------------------------------------------------------- /app/views/devise/confirmations/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post } do |f| 5 | - if f.error(:confirmation_token).present? 6 | .alert.alert-danger: p = f.error(:confirmation_token) 7 | = f.input :email, autofocus: true 8 | = f.button :submit, t('.send'), class: 'btn-success' 9 | hr 10 | = render "devise/shared/links" 11 | -------------------------------------------------------------------------------- /app/views/devise/mailer/confirmation_instructions.html.slim: -------------------------------------------------------------------------------- 1 | h4 Добро пожаловать! 2 | p 3 | = "Вы собираетесь зарегистрироваться (или изменить email) на сайте #{ENV.fetch('mailing_host') {'mailing_host'}} с адресом" 4 | strong< = @resource.email 5 | p Пожалуйста, подтвердите свой email, кликнув на ссылку ниже. 6 | p == link_to 'Да, это моя почта', confirmation_url(@resource, confirmation_token: @token) 7 | p Если вы не регистрировались на указанном сайте, просто проигнорируйте это сообщение. 8 | 9 | == "--" 10 | br/ 11 | == t('devise.emails.signature') 12 | -------------------------------------------------------------------------------- /app/views/devise/mailer/reset_password_instructions.html.slim: -------------------------------------------------------------------------------- 1 | p 2 | - if @resource.to_s.present? 3 | = t('devise.emails.reset_password.greetings.named', name: @resource.to_s||@resource.email) 4 | - else 5 | = t('devise.emails.reset_password.greetings.anon') 6 | 7 | p == t('devise.emails.reset_password.body')[0] 8 | p = link_to t('devise.emails.reset_password.reset_link'), edit_password_url(@resource, reset_password_token: @token) 9 | p = t('devise.emails.reset_password.body')[1] 10 | 11 | '-- 12 | br 13 | == t('devise.emails.signature') 14 | -------------------------------------------------------------------------------- /app/views/devise/mailer/unlock_instructions.html.slim: -------------------------------------------------------------------------------- 1 | p = "Привет, #{@resource.email}!" 2 | p Ваш аккаунт был заблокирован из-за нескольких попыток неправильного вводе пароля. 3 | p Пройдите по ссылке ниже, чтобы снять блокировку: 4 | p = link_to 'Разблокировать мой аккаунт', unlock_url(@resource, unlock_token: @token) 5 | -------------------------------------------------------------------------------- /app/views/devise/passwords/edit.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| 5 | = f.input :reset_password_token, as: :hidden 6 | = f.full_error :reset_password_token 7 | = f.input :password, autofocus: true 8 | = f.input :password_confirmation 9 | 10 | = f.button :submit, t('.submit') 11 | hr 12 | = render "devise/shared/links" 13 | -------------------------------------------------------------------------------- /app/views/devise/passwords/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| 5 | = f.input :email, autofocus: true 6 | = f.button :submit, t('.send'), class: 'btn-success' 7 | hr 8 | = render "devise/shared/links" 9 | -------------------------------------------------------------------------------- /app/views/devise/registrations/edit.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-6 4 | = simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| 5 | - if current_user.email.present? 6 | = f.input :email, required: true, autofocus: true, disabled: true 7 | - else 8 | = f.input :email, required: true, autofocus: true 9 | - if devise_mapping.confirmable? && resource.pending_reconfirmation? 10 | .alert.alert-warning: p 11 | 'Ждём подтверждения адреса 12 | strong = resource.unconfirmed_email 13 | '. 14 | = f.input :password, autocomplete: "off" 15 | = f.input :password_confirmation 16 | = f.input :current_password 17 | = f.button :submit, t('.submit'), class: "btn-primary" 18 | -------------------------------------------------------------------------------- /app/views/devise/registrations/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for resource, as: resource_name, url: registration_path(resource_name) do |f| 5 | = f.input :email, autofocus: true, required: true 6 | = f.input :password, required: true 7 | = f.input :password_confirmation, required: true 8 | 9 | = f.button :submit, t('.sign_up'), class: 'btn-success' 10 | 11 | hr 12 | 13 | = render "devise/shared/links" 14 | -------------------------------------------------------------------------------- /app/views/devise/sessions/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row data-no-turbolink=true 4 | - if devise_mapping.omniauthable? 5 | .col-sm-6 6 | h2 = t('.social_login') 7 | .row: .col-sm-8 8 | ul.list-unstyled.social-login 9 | = render partial: 'authentications/unlinked', collection: resource_class.omniauth_providers, as: :provider 10 | 11 | .col-sm-5.col-sm-offset-1 12 | h2 = t('.log_in') 13 | = simple_form_for resource, as: resource_name, url: session_path(resource_name) do |f| 14 | = f.input :email, autofocus: true, required: true 15 | = f.input :password, required: true 16 | = f.input :remember_me, as: :boolean, wrapper: :vertical_boolean if devise_mapping.rememberable? 17 | = f.button :submit, t('.log_in'), class: 'btn-success' 18 | 19 | hr 20 | 21 | = render "devise/shared/links" 22 | -------------------------------------------------------------------------------- /app/views/devise/shared/_links.slim: -------------------------------------------------------------------------------- 1 | - if controller_name != 'sessions' 2 | = link_to t("devise.shared_links.log_in"), new_session_path(resource_name) 3 | br/ 4 | - if devise_mapping.registerable? && controller_name != 'registrations' 5 | = link_to t("devise.shared_links.sign_up"), new_registration_path(resource_name) 6 | br/ 7 | - if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' 8 | = link_to t("devise.shared_links.forgot_passord"), new_password_path(resource_name) 9 | br/ 10 | - if devise_mapping.confirmable? && controller_name != 'confirmations' 11 | = link_to t("devise.shared_links.resend_confirmation_instructions"), new_confirmation_path(resource_name) 12 | br/ 13 | - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' 14 | = link_to t("devise.shared_links.resend_unlock_instructions"), new_unlock_path(resource_name) 15 | br/ 16 | -------------------------------------------------------------------------------- /app/views/devise/unlocks/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | 5 | = simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| 6 | = f.error_notification 7 | = f.full_error :unlock_token 8 | = f.input :email, required: true, autofocus: true 9 | 10 | = f.button :submit, "Resend unlock instructions" 11 | 12 | hr 13 | 14 | = render "devise/shared/links" 15 | -------------------------------------------------------------------------------- /app/views/errors/error_404.html.slim: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title Страницы, которую вы запрашиваете не существует (404) 5 | meta[name="viewport" content="width=device-width,initial-scale=1"] 6 | style 7 | | body { background-color: #FFF; text-align: center; font-family: arial, sans-serif; margin: 0; } .logo { margin-top: 100px; } .message { width: 95%; max-width: 33em; margin: 7em auto 0; } 8 | body 9 | .logo = image_tag 'it52_logo_white_clean.svg', alt: 'it52' 10 | .message 11 | h1 Ой! 12 | h3 Такой страницы у нас нет. 13 | p 14 | = link_to 'Вернуться на главную страницу', root_path 15 | |. 16 | -------------------------------------------------------------------------------- /app/views/events/_admin_info.html.slim: -------------------------------------------------------------------------------- 1 | .admin-info 2 | i.fas [class="#{admin_event_icon_class(event)}" 3 | data-title="#{Event.human_attribute_name :published}: #{t(event.published.to_s)}" 4 | data-toggle="tooltip" data-placement="bottom"] 5 | 6 | -------------------------------------------------------------------------------- /app/views/events/_event-item.rss.slim: -------------------------------------------------------------------------------- 1 | header 2 | h1 = event.title 3 | figure = image_tag event.title_image.square_500.url 4 | h2 = [l(event.started_at, format: :date_time_full), event.place].join(' | ') 5 | 6 | = event.rendered_description 7 | 8 | button formaction=event_url(event) data={'background-color' => '#333333', color: '#FEFEFE', turbo: 'false', primary: 'true'} Зарегистрироваться 9 | 10 | div data={ block: 'share', network: 'telegram, vkontakte, twitter, facebook, google'} 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/views/events/_form.html.slim: -------------------------------------------------------------------------------- 1 | - content_for :dynamic_javascripts 2 | = javascript_pack_tag 'editor', 'data-turbolinks-track': true, defer: true 3 | 4 | = simple_form_for @event do |f| 5 | = f.input :title 6 | .row 7 | .col-sm-6 8 | .well 9 | - if @event.title_image.present? 10 | .title-image.image-container 11 | = image_tag @event.title_image.square_500.url 12 | = f.input :title_image, wrapper: :vertical_file_input 13 | = f.input :title_image_cache, as: :hidden 14 | = f.input :kind, as: :select, collection: Event.humanized_kinds_map, allow_blank: false, selected: @event.kind 15 | - started_at_string = l(f.object.started_at || 1.month.from_now, format: :date_time_short) 16 | = f.input :started_at, as: :string, input_html: { value: started_at_string, data: { default_date: started_at_string }} 17 | = f.input :tag_list, input_html: { value: @event.tag_list.to_s, maxlength: 100 } 18 | .col-sm-6 19 | = f.input :place 20 | = f.input :address_comment, as: :text 21 | = f.input :location, as: :hidden 22 | = check_box_tag :has_foreign_link, !@event.foreign_link.blank?, !@event.foreign_link.blank? 23 | = label_tag :has_foreign_link, t("my.events.has_foreign_link"), style: "padding-left: 10px;" 24 | div#event_foreign_link_box.hidden 25 | = f.input :foreign_link, as: :string, input_html: { type: :url } 26 | 27 | .row: .col-sm-12 28 | = f.input :description, input_html: { rows: 10, class: 'mde-textarea' } 29 | = f.submit class: 'btn btn-primary' 30 | -------------------------------------------------------------------------------- /app/views/events/_participants_block.html.slim: -------------------------------------------------------------------------------- 1 | - if event.participants.any? 2 | ul.list-unstyled 3 | - event.participants.sample(24).each do |p| 4 | li.participant 5 | = link_to p, data: { toggle: 'tooltip', placement: 'bottom', title: p.full_name }, class: 'participant-link' do 6 | .avatar = image_tag p.avatar_image.square_50.url, alt: p.to_s 7 | - else 8 | p.lead = t('.no_participants') 9 | -------------------------------------------------------------------------------- /app/views/events/_participate_block.html.slim: -------------------------------------------------------------------------------- 1 | .line 2 | - if event.user_participated? current_user 3 | = form_tag cancel_participation_path(id: event.participation_for(current_user)), method: :delete do 4 | button.mdc-button.mdc-button--wide.mdc-button--outlined type='submit' 5 | span.mdc-button__label = event.cancel_participation_submit_title 6 | - if event.foreign_link.present? 7 | p.foreign-link-disclaimer Используется сторонняя регистрация. Свяжитесь с организатором, чтобы отказаться от участия. 8 | - else 9 | = form_tag participate_in_event_path do 10 | = hidden_field_tag 'event_participation[event_id]', event.id 11 | button.mdc-button.mdc-button--wide.mdc-button--success type='submit' 12 | span.mdc-button__label = event.participate_submit_title 13 | - if event.foreign_link.present? 14 | p.foreign-link-disclaimer Используется сторонняя регистрация. После клика вы будете перенаправлены на другой сайт, не пугайтесь. 15 | -------------------------------------------------------------------------------- /app/views/events/edit.html.slim: -------------------------------------------------------------------------------- 1 | .page-header 2 | h1 = t '.title' 3 | 4 | = render 'form' -------------------------------------------------------------------------------- /app/views/events/index.rss.builder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | cache [:rss, @rss_events] do 4 | xml.instruct! :xml, version: '1.0' 5 | xml.rss version: '2.0', 6 | 'xmlns:yandex' => 'http://news.yandex.ru', 7 | 'xmlns:media' => 'http://search.yahoo.com/mrss/', 8 | 'xmlns:turbo' => 'http://turbo.yandex.ru' do 9 | xml.channel do 10 | xml.title ['it52', t(:app_name)].join(' | ') 11 | xml.link root_url 12 | xml.description t :app_description 13 | xml.language 'ru' 14 | xml.turbo(:analytics, id: '50290294', type: 'Yandex') 15 | xml.turbo(:analytics, id: 'UA-54446007-1', type: 'Google') 16 | 17 | @rss_events.each do |event| 18 | html = render partial: 'event-item', locals: { event: event } 19 | xml.item(turbo: 'true') do |item| 20 | item.link event_url(event) 21 | item.pubDate event.published_at.rfc2822 22 | item.author event.organizer.to_s 23 | item.turbo(:content) do |content| 24 | content.cdata! html 25 | end 26 | end 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /app/views/events/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header 2 | h1 = t '.title' 3 | 4 | = render 'form' -------------------------------------------------------------------------------- /app/views/my/authentications/_authentication.html.slim: -------------------------------------------------------------------------------- 1 | - icon = t("social.#{authentication.provider}.icon") 2 | 3 | li: .btn-group 4 | = authentication.link_to_social 5 | = authentication.link_to_destroy 6 | -------------------------------------------------------------------------------- /app/views/my/users/edit.html.slim: -------------------------------------------------------------------------------- 1 | - content_for :dynamic_javascripts 2 | = javascript_pack_tag 'editor', 'data-turbolinks-track': true, defer: true 3 | 4 | .page-header 5 | h1 = t('.title') 6 | 7 | = simple_form_for @user, url: my_profile_path do |f| 8 | .row 9 | .col-sm-3 10 | - if @user.avatar_image.present? 11 | .title-image 12 | .avatar = image_tag @user.avatar_image.square_150.url 13 | 14 | = f.input :avatar_image, wrapper: :vertical_file_input 15 | = f.input :avatar_image_cache, as: :hidden 16 | 17 | .col-sm-7.col-sm-offset-1 18 | = f.input :first_name 19 | = f.input :last_name 20 | = f.input :nickname 21 | = f.input :employment 22 | = f.input :website 23 | 24 | = f.input :bio, input_html: { rows: 7, class: 'mde-textarea' } 25 | 26 | - if current_user.email.present? 27 | = f.input :subscription, wrapper: :vertical_boolean 28 | - else 29 | = f.input :subscription, wrapper: :vertical_boolean, disabled: true, hint: false 30 | .alert.alert-warning 31 | p 32 | 'Пожалуйста, 33 | a.alert-link href=edit_user_registration_path укажите вашу почту 34 | |, чтобы подписаться на уведомления. 35 | 36 | 37 | = f.submit class: 'btn btn-primary' 38 | '   39 | = link_to t(:cancel), my_profile_path, class: 'btn btn-default' 40 | 41 | -------------------------------------------------------------------------------- /app/views/my/users/show.html.slim: -------------------------------------------------------------------------------- 1 | .row 2 | .col-sm-3 3 | .avatar.image-container = image_tag @user.avatar_image.square_150.url 4 | = link_to edit_my_profile_path, class: 'btn btn-warning btn-block' do 5 | i.fas.fa-pen> 6 | = t('.edit') 7 | br 8 | = link_to destroy_user_session_path, method: :delete, class: 'btn btn-danger btn-block' do 9 | i.fas.fa-power-off> 10 | = t('shared.sidebar.logout') 11 | br 12 | .text-center = link_to t('.edit_registration'), edit_user_registration_path, class: 'text-danger' 13 | 14 | .col-sm-9 15 | .page-header 16 | h1 17 | = @user 18 | small< = @user.nickname 19 | 20 | - if @user.employment.present? 21 | h4 #{ t('activerecord.attributes.user.employment') }: #{ @user.employment } 22 | 23 | = @user.link_to_website 24 | 25 | - if @user.bio? 26 | = @user.bio 27 | hr 28 | 29 | - if @user.authentications.present? 30 | section 31 | h5.subheader = t('.linked_accounts') 32 | ul.list-inline 33 | = render @user.authentications 34 | hr 35 | 36 | - if @user.unlinked_providers.present? 37 | section 38 | h5.subheader = t('.unlinked_accounts') 39 | ul.list-inline 40 | = render partial: 'authentications/unlinked', collection: @user.unlinked_providers, as: :provider 41 | 42 | = render partial: 'users/user-events', locals: { user: @user } 43 | -------------------------------------------------------------------------------- /app/views/pages/communities.html.slim: -------------------------------------------------------------------------------- 1 | h1 IT-сообщества Нижнего Новгорода 2 | 3 | - Telegram::Channel.groups.values.each do |group| 4 | h3 = group[:name] 5 | ul.chevron-bullets 6 | - group[:channels].each_pair do |id, description| 7 | li #{link_to "@#{id}", "tg://resolve/?domain=#{id}"} — #{description} 8 | -------------------------------------------------------------------------------- /app/views/pages/manifesto.ru.html.slim: -------------------------------------------------------------------------------- 1 | .page-header 2 | h1 Нижегородское IT-сообщество 3 | 4 | p it52 — это некоммерческое сообщество энтузиастов, которые думают, что могут сделать жизнь нижегородского айтишника немного лучше. Мы помогаем организовывать профильные мероприятия, ведём афишу событий, курируем несколько чатиков в телеграме и групп в соцсетях, и кажется, что у нас получается. 5 | 6 | h2 Манифест 7 | 8 | ul 9 | li Мы выступаем за открытое распространение знаний для всех и каждого. 10 | li Мы выступаем за общество, которое продвигает вежливость в общении, уважение к человеческому достоинству и право на свободу мысли. 11 | li Мы выступаем за общество, которое поддерживает критическое мышление, аргументированные дискуссии, распространение знаний и достоверность фактов. 12 | li Мы выступаем за взаимодействие, которое способствует сотрудничеству между различными сообществами ради общего блага. 13 | 14 | h2 Наши принципы 15 | 16 | ol 17 | li Взаимодействие - это неотъемлемая часть современной жизни, ключевой компонент в образовании, общении, сотрудничестве, бизнесе, развлечении и структуре общества в целом. 18 | li Сообщества должны быть общественными ресурсами, которые должны оставаться открытыми и доступными. 19 | li Люди должны иметь возможность формировать сообщества и свое пребывание в них. 20 | li Прозрачные процессы способствуют сотрудничеству, повышают ответственность и доверие. 21 | li Коммерческое участие в развитии сообществ дает большую выгоду; при этом важно соблюдать баланс между коммерческим доходом и общественной пользой 22 | -------------------------------------------------------------------------------- /app/views/pages/thankyou.html.slim: -------------------------------------------------------------------------------- 1 | h1 Спасибо 2 | p Ваши пожертвования пойдут на доброе дело. 3 | -------------------------------------------------------------------------------- /app/views/shared/_oauth_login_block.html.slim: -------------------------------------------------------------------------------- 1 | h2 = t('.social_providers') 2 | - t(:social).each_key do |provider| 3 | = link_to auth_at_provider_path(provider: provider), class: "btn btn-default btn-lg btn-#{provider}" do 4 | i.fas.fa-fw> class="fa-#{provider}" 5 | = t(:name, scope: "social.#{provider}") 6 | -------------------------------------------------------------------------------- /app/views/shared/_small_screens_footer.html.slim: -------------------------------------------------------------------------------- 1 | .row: .visible-xs.visible-sm.col-sm-12 2 | hr 3 | h2 = t(:app_name) 4 | h3 = t('.social_links') 5 | ul#social-links.nav.nav-pills 6 | li = link_to 'https://twitter.com/it_rostov', target: '_blank' do 7 | i.fas.fa-fw.fa-twitter' 8 | span.gray 9 | ' / 10 | ' it_rostov 11 | li = link_to 'https://vk.com/it_61', target: '_blank' do 12 | i.fas.fa-fw.fa-vk' 13 | span.gray 14 | ' / 15 | ' it_61 16 | li = link_to 'https://www.facebook.com/it61.info', target: '_blank' do 17 | i.fas.fa-fw.fa-facebook' 18 | span.gray 19 | ' / 20 | ' it61.info 21 | hr 22 | h4 = t('.hashtag') 23 | -------------------------------------------------------------------------------- /app/views/sitemaps/index.xml.slim: -------------------------------------------------------------------------------- 1 | = cache [@pages, @events, @startups] do 2 | | 3 | urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" 4 | - [root_url, startups_url, events_url].each do |index_url| 5 | url 6 | loc = index_url 7 | changefreq hourly 8 | priority 1 9 | 10 | - @pages.each do |page| 11 | url 12 | loc = page_url(page) 13 | changefreq daily 14 | priority 0.4 15 | 16 | - @events.each do |event| 17 | url 18 | loc = event_url(event) 19 | changefreq daily 20 | lastmod = l event.updated_at, format: :sitemap 21 | priority 0.9 22 | 23 | - @startups.each do |startup| 24 | url 25 | loc = startup_url(startup) 26 | changefreq daily 27 | lastmod = l startup.updated_at, format: :sitemap 28 | priority 0.9 29 | -------------------------------------------------------------------------------- /app/views/startups/_form.html.slim: -------------------------------------------------------------------------------- 1 | - content_for :dynamic_javascripts 2 | = javascript_pack_tag 'editor', 'data-turbolinks-track': true, defer: true 3 | 4 | = simple_form_for(@startup) do |f| 5 | .row 6 | .col-sm-5 7 | = f.input :title 8 | = f.input :url 9 | - if f.object.logo.present? 10 | = image_tag f.object.logo.small.url, alt: f.object.title 11 | = f.input :logo 12 | = f.input :intro 13 | = f.simple_fields_for :contacts, OpenStruct.new(@startup.contacts) do |c| 14 | = f.label :contacts 15 | .row 16 | .col-xs-6 = c.input :name, label: false 17 | .col-xs-6 = c.input :email, label: false 18 | .col-sm-7 19 | = f.input :description, input_html: { rows: 8, class: 'mde-textarea' } 20 | 21 | .form-actions 22 | = f.submit meta_t(:title), class: 'mdc-button mdc-button--success' 23 | '  24 | = link_to 'Отмена', startups_path, class: 'mdc-button mdc-button--outline' 25 | -------------------------------------------------------------------------------- /app/views/startups/_startup.html.slim: -------------------------------------------------------------------------------- 1 | .grid__cell--startup 2 | .mdc-card.mdc-card--startup.mdc-card--outlined 3 | a.mdc-card__primary-action tabindex="0" href=startup_path(startup) title=startup.title 4 | .mdc-card__media.mdc-card__media--square[style="background-image: url(#{asset_url(startup.logo.big.url)});"] 5 | 6 | .mdc-card__primary 7 | h2.mdc-card__title = startup.title 8 | p.mdc-card__subtitle = startup.intro 9 | 10 | - if can? :edit, startup 11 | .mdc-card__actions 12 | .mdc-card__action-icons 13 | a.mdc-icon-button.mdc-card__action.mdc-card__action--icon--unbounded title="Изменить" href=edit_startup_path(startup) 14 | i.material-icons.mdc-icon-button__icon edit 15 | = link_to startup_path(startup), class: 'mdc-icon-button mdc-card__action mdc-card__action--icon--unbounded', method: :delete, title: "Удалить", data: { confirm: 'Удалить стартап?' } do 16 | i.material-icons.mdc-icon-button__icon delete 17 | -------------------------------------------------------------------------------- /app/views/startups/edit.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=startups_path title='Все стартапы' list 3 | 4 | h1 = @startup.title 5 | 6 | == render 'form' 7 | -------------------------------------------------------------------------------- /app/views/startups/index.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=new_startup_path title=t('meta.startups.new.title') add 3 | 4 | h1 Стартапы в Нижнем Новгороде 5 | br 6 | .grid 7 | .grid__inner 8 | = render @startups 9 | -------------------------------------------------------------------------------- /app/views/startups/new.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=startups_path title='Все стартапы' list 3 | 4 | h1 = t('meta.startups.new.title') 5 | 6 | == render 'form' 7 | -------------------------------------------------------------------------------- /app/views/startups/show.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=startups_path title='Все стартапы' list 3 | - if can? :edit, @startup 4 | a.material-icons.mdc-top-app-bar__action-item href=edit_startup_path(@startup) title='Изменить' edit 5 | 6 | h1 = @startup.title 7 | h3 = @startup.intro 8 | 9 | .grid 10 | .grid__inner 11 | .grid__cell--startup-meta 12 | = image_tag @startup.logo.big.url, alt: @startup, class: 'startup-image' 13 | p.startup-url = link_to @startup.url, @startup.url 14 | p.startup-contacts = @startup.contacts.values.join(': ') 15 | .grid__cell--startup-description = @startup.rendered_description 16 | -------------------------------------------------------------------------------- /app/views/turbo/events/_event.rss.builder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | html = render partial: 'events/event-item', locals: { event: event } 4 | 5 | xml.item(turbo: 'true') do |item| 6 | item.link event_url(event) 7 | item.pubDate event.published_at.rfc2822 8 | item.author event.organizer.to_s 9 | item.turbo(:content) do |content| 10 | content.cdata! html 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/views/turbo/events/index.rss.builder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | cache [:turbo, @events] do 4 | xml.instruct! :xml, version: '1.0' 5 | xml.rss version: '2.0', 6 | 'xmlns:yandex' => 'http://news.yandex.ru', 7 | 'xmlns:media' => 'http://search.yahoo.com/mrss/', 8 | 'xmlns:turbo' => 'http://turbo.yandex.ru' do 9 | xml.channel do 10 | xml.title ['it52', t(:app_name)].join(' | ') 11 | xml.link root_url 12 | xml.description t :app_description 13 | xml.language 'ru' 14 | xml.turbo(:analytics, id: '50290294', type: 'Yandex') 15 | xml.turbo(:analytics, id: 'UA-54446007-1', type: 'Google') 16 | 17 | @events.each do |event| 18 | html = render partial: 'events/event-item', locals: { event: event } 19 | 20 | xml.item(turbo: 'true') do |item| 21 | item.link event_url(event) 22 | item.pubDate event.published_at.rfc2822 23 | item.author event.organizer.to_s 24 | item.turbo(:content) do |content| 25 | content.cdata! html 26 | end 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /app/views/users/_user-events.html.slim: -------------------------------------------------------------------------------- 1 | .user-profile-page 2 | .row 3 | .col-sm-9.col-md-12 4 | 5 | - if user.owner_of_events.any? 6 | - year = 0 7 | .owner-of-events 8 | h2 = t('.organizer_block_title') 9 | ul.date-list 10 | - user.owner_of_events.each do |event| 11 | - next if cannot? :read, event 12 | - if event.started_at.year != year 13 | li.no-date: h3.text-muted = year = event.started_at.year 14 | li date=l(event.started_at, format: :date_without_year) 15 | = link_to event.title, event_path(event) 16 | 17 | - if user.member_in_events.any? 18 | - year = 0 19 | h2 = t('.member_block_title') 20 | ul.date-list 21 | - user.member_in_events.each do |event| 22 | - next if cannot? :read, event 23 | - if event.started_at.year != year 24 | li.no-date: h3.text-muted = year = event.started_at.year 25 | li date=l(event.started_at, format: :date_without_year) 26 | = link_to event.title, event_path(event) 27 | -------------------------------------------------------------------------------- /app/views/users/_user.html.slim: -------------------------------------------------------------------------------- 1 | .col-xs-12.col-sm-2 2 | .user-profile-preview = link_to user do 3 | .row 4 | .col-xs-2.col-sm-12 5 | .avatar = image_tag user.avatar_image.square_150.url 6 | .col-xs-10.col-sm-12 7 | = user.full_name 8 | -------------------------------------------------------------------------------- /app/views/users/index.html.slim: -------------------------------------------------------------------------------- 1 | = cache @users do 2 | .page-header 3 | h1 4 | = t('.title') 5 | small< = t('.counter', count: User.count) 6 | 7 | - @users.each_slice(6) do |row_slice| 8 | .row = render row_slice 9 | 10 | .text-center 11 | == paginate @users 12 | -------------------------------------------------------------------------------- /app/views/users/show.html.slim: -------------------------------------------------------------------------------- 1 | .row 2 | .col-sm-3: .avatar.image-container = image_tag @user.avatar_image.square_150.url 3 | 4 | .col-sm-9 5 | .page-header 6 | h1 7 | = @user 8 | small< = @user.nickname 9 | = @user.link_to_website 10 | 11 | - unless @user.employment.blank? 12 | h4 #{ t('activerecord.attributes.user.employment') }: #{ @user.employment } 13 | 14 | - if @user.bio? 15 | = @user.bio 16 | hr 17 | 18 | - if @user.authentications.present? 19 | section 20 | h5.subheader = t('.linked_accounts') 21 | ul.list-inline = render @user.authentications 22 | hr 23 | 24 | = render partial: 'users/user-events', locals: { user: @user } 25 | -------------------------------------------------------------------------------- /bin/annotate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'annotate' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('annotate', 'annotate') 30 | -------------------------------------------------------------------------------- /bin/byebug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'byebug' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('byebug', 'byebug') 30 | -------------------------------------------------------------------------------- /bin/cc-tddium-post-worker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'cc-tddium-post-worker' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('codeclimate-test-reporter', 'cc-tddium-post-worker') 30 | -------------------------------------------------------------------------------- /bin/codeclimate-test-reporter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'codeclimate-test-reporter' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('codeclimate-test-reporter', 'codeclimate-test-reporter') 30 | -------------------------------------------------------------------------------- /bin/coderay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'coderay' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('coderay', 'coderay') 30 | -------------------------------------------------------------------------------- /bin/figaro: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'figaro' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('figaro', 'figaro') 30 | -------------------------------------------------------------------------------- /bin/foreman: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'foreman' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('foreman', 'foreman') 30 | -------------------------------------------------------------------------------- /bin/htmldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'htmldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('diff-lcs', 'htmldiff') 30 | -------------------------------------------------------------------------------- /bin/launchy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'launchy' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('launchy', 'launchy') 30 | -------------------------------------------------------------------------------- /bin/ldiff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ldiff' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('diff-lcs', 'ldiff') 30 | -------------------------------------------------------------------------------- /bin/listen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'listen' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('listen', 'listen') 30 | -------------------------------------------------------------------------------- /bin/mongrel_rpm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'mongrel_rpm' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('newrelic_rpm', 'mongrel_rpm') 30 | -------------------------------------------------------------------------------- /bin/newrelic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'newrelic' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('newrelic_rpm', 'newrelic') 30 | -------------------------------------------------------------------------------- /bin/newrelic_cmd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'newrelic_cmd' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('newrelic_rpm', 'newrelic_cmd') 30 | -------------------------------------------------------------------------------- /bin/nokogiri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'nokogiri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('nokogiri', 'nokogiri') 30 | -------------------------------------------------------------------------------- /bin/nrdebug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'nrdebug' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('newrelic_rpm', 'nrdebug') 30 | -------------------------------------------------------------------------------- /bin/oauth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'oauth' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('oauth', 'oauth') 30 | -------------------------------------------------------------------------------- /bin/pry: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pry' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('pry', 'pry') 30 | -------------------------------------------------------------------------------- /bin/puma: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'puma' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('puma', 'puma') 30 | -------------------------------------------------------------------------------- /bin/pumactl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'pumactl' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('puma', 'pumactl') 30 | -------------------------------------------------------------------------------- /bin/rackup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # This file was generated by RubyGems. 4 | # 5 | # The application 'rack' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | require 'rubygems' 10 | 11 | version = ">= 0.a" 12 | 13 | str = ARGV.first 14 | if str 15 | str = str.b[/\A_(.*)_\z/, 1] 16 | if str and Gem::Version.correct?(str) 17 | version = str 18 | ARGV.shift 19 | end 20 | end 21 | 22 | if Gem.respond_to?(:activate_bin_path) 23 | load Gem.activate_bin_path('rack', 'rackup', version) 24 | else 25 | gem "rack", version 26 | load Gem.bin_path("rack", "rackup", version) 27 | end 28 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | APP_PATH = File.expand_path('../config/application', __dir__) 5 | require_relative '../config/boot' 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # This file was generated by RubyGems. 4 | # 5 | # The application 'rake' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | require 'rubygems' 10 | 11 | version = ">= 0.a" 12 | 13 | str = ARGV.first 14 | if str 15 | str = str.b[/\A_(.*)_\z/, 1] 16 | if str and Gem::Version.correct?(str) 17 | version = str 18 | ARGV.shift 19 | end 20 | end 21 | 22 | if Gem.respond_to?(:activate_bin_path) 23 | load Gem.activate_bin_path('rake', 'rake', version) 24 | else 25 | gem "rake", version 26 | load Gem.bin_path("rake", "rake", version) 27 | end 28 | -------------------------------------------------------------------------------- /bin/rdoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rdoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('rdoc', 'rdoc') 30 | -------------------------------------------------------------------------------- /bin/redcarpet: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'redcarpet' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('redcarpet', 'redcarpet') 30 | -------------------------------------------------------------------------------- /bin/restclient: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'restclient' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('rest-client', 'restclient') 30 | -------------------------------------------------------------------------------- /bin/ri: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ri' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('rdoc', 'ri') 30 | -------------------------------------------------------------------------------- /bin/rollbar-rails-runner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rollbar-rails-runner' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('rollbar', 'rollbar-rails-runner') 30 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rspec' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('rspec-core', 'rspec') 30 | -------------------------------------------------------------------------------- /bin/rubocop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rubocop' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('rubocop', 'rubocop') 30 | -------------------------------------------------------------------------------- /bin/ruby-parse: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-parse' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('parser', 'ruby-parse') 30 | -------------------------------------------------------------------------------- /bin/ruby-rewrite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'ruby-rewrite' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('parser', 'ruby-rewrite') 30 | -------------------------------------------------------------------------------- /bin/safe_yaml: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'safe_yaml' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('safe_yaml', 'safe_yaml') 30 | -------------------------------------------------------------------------------- /bin/sdoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sdoc' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('sdoc', 'sdoc') 30 | -------------------------------------------------------------------------------- /bin/sdoc-merge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sdoc-merge' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('sdoc', 'sdoc-merge') 30 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'fileutils' 5 | include FileUtils 6 | 7 | # path to your application root. 8 | APP_ROOT = File.expand_path('..', __dir__) 9 | 10 | def system!(*args) 11 | system(*args) || abort("\n== Command #{args} failed ==") 12 | end 13 | 14 | chdir APP_ROOT do 15 | # This script is a starting point to setup your application. 16 | # Add necessary setup steps to this file. 17 | 18 | puts '== Installing dependencies ==' 19 | system! 'gem install bundler --conservative' 20 | system('bundle check') || system!('bundle install') 21 | 22 | # Install JavaScript dependencies if using Yarn 23 | # system('bin/yarn') 24 | 25 | # puts "\n== Copying sample files ==" 26 | # unless File.exist?('config/database.yml') 27 | # cp 'config/database.yml.sample', 'config/database.yml' 28 | # end 29 | 30 | puts "\n== Preparing database ==" 31 | system! 'bin/rails db:setup' 32 | 33 | puts "\n== Removing old logs and tempfiles ==" 34 | system! 'bin/rails log:clear tmp:clear' 35 | 36 | puts "\n== Restarting application server ==" 37 | system! 'bin/rails restart' 38 | end 39 | -------------------------------------------------------------------------------- /bin/sidekiq: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sidekiq' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('sidekiq', 'sidekiq') 30 | -------------------------------------------------------------------------------- /bin/sidekiqctl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sidekiqctl' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('sidekiq', 'sidekiqctl') 30 | -------------------------------------------------------------------------------- /bin/slimrb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'slimrb' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('slim', 'slimrb') 30 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'spring' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('spring', 'spring') 30 | -------------------------------------------------------------------------------- /bin/sprockets: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'sprockets' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('sprockets', 'sprockets') 30 | -------------------------------------------------------------------------------- /bin/sync_db: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | heroku pg:backups:capture -a it52 3 | heroku pg:backups:download -a it52 4 | docker cp ./latest.dump $(docker-compose ps -q db):/tmp/latest.dump 5 | docker-compose exec db pg_restore --verbose --clean --no-acl --no-owner -U postgres -d it52_rails_dev /tmp/latest.dump 6 | docker-compose exec db rm /tmp/latest.dump 7 | rm ./latest.dump 8 | -------------------------------------------------------------------------------- /bin/thor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'thor' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('thor', 'thor') 30 | -------------------------------------------------------------------------------- /bin/tilt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'tilt' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require 'pathname' 12 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', 13 | Pathname.new(__FILE__).realpath) 14 | 15 | bundle_binstub = File.expand_path('bundle', __dir__) 16 | 17 | if File.file?(bundle_binstub) 18 | if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) 19 | load(bundle_binstub) 20 | else 21 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 22 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 23 | end 24 | end 25 | 26 | require 'rubygems' 27 | require 'bundler/setup' 28 | 29 | load Gem.bin_path('tilt', 'tilt') 30 | -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'fileutils' 5 | include FileUtils 6 | 7 | # path to your application root. 8 | APP_ROOT = File.expand_path('..', __dir__) 9 | 10 | def system!(*args) 11 | system(*args) || abort("\n== Command #{args} failed ==") 12 | end 13 | 14 | chdir APP_ROOT do 15 | # This script is a way to update your development environment automatically. 16 | # Add necessary update steps to this file. 17 | 18 | puts '== Installing dependencies ==' 19 | system! 'gem install bundler --conservative' 20 | system('bundle check') || system!('bundle install') 21 | 22 | # Install JavaScript dependencies if using Yarn 23 | # system('bin/yarn') 24 | 25 | puts "\n== Updating database ==" 26 | system! 'bin/rails db:migrate' 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! 'bin/rails log:clear tmp:clear' 30 | 31 | puts "\n== Restarting application server ==" 32 | system! 'bin/rails restart' 33 | end 34 | -------------------------------------------------------------------------------- /bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/webpack_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::WebpackRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/dev_server_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::DevServerRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | APP_ROOT = File.expand_path('..', __dir__) 5 | Dir.chdir(APP_ROOT) do 6 | exec 'yarnpkg', *ARGV 7 | rescue Errno::ENOENT 8 | warn 'Yarn executable was not detected in the system.' 9 | warn 'Download Yarn at https://yarnpkg.com/en/docs/install' 10 | exit 1 11 | end 12 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "yarn.lock" 3 | - "Gemfile.lock" 4 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require_relative 'config/environment' 6 | 7 | run Rails.application 8 | -------------------------------------------------------------------------------- /config/REFACTOR.md: -------------------------------------------------------------------------------- 1 | # Refactor it52.info 2 | 3 | ## Features 4 | 5 | 1. Календарь 6 | 2. Карта 7 | 3. Админка для устроителей 8 | 1. Список участников 9 | 2. Анкетирование 10 | -------------------------------------------------------------------------------- /config/application.yml: -------------------------------------------------------------------------------- 1 | # Add application configuration variables here, as shown below. 2 | # 3 | 4 | secret_key_base: 3ed5c557685115895b2bc54cc59dc56a2d86252a610280a533cc8646fdd7ad0570e9fb1d7d9ebf8b1545de342c992bccb4a9579ab0a470af0691a404286a633a 5 | devise_secret_key: ef6adebc88bd3a9976c602a98ec6581589afbecc900000afdef2702e97ef362ce5c576d67b9e9f1fd37ac931de6859919a3703f927df7193db13ba6c6556882b 6 | devise_pepper: 52fa43c0218b1eb1102f84dcf570376a0c6199de1555c9b3d90b2d6e976165622e65e9b972438301f7a88e46305018f1eab70f3a057fc5e71da97a1a232da28d 7 | mailchimp_hooks_token: 09d6ee395d3feecc85f5bbea7951e07e9eeb5ca401949d7ab7caeb6341af45c761544886c1bf50b36e2346678fcb009490120614405ecd83a96775ca8a10a23f 8 | mailing_host: localhost:3000 9 | telegram_domain: 't.me' 10 | 11 | github_id: 07a1486f0bf491a0c3a7 12 | github_secret: a661de5c80b6d648803b1e9c8564a280d06cad83 13 | github_callback_url: http://localhost:3000/oauth/github/callback 14 | 15 | facebook_callback_url: http://localhost:3000/oauth/facebook/callback 16 | facebook_secret: '47fc23b99842fce5948da63ca2320653' 17 | facebook_id: '711928915527342' 18 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 4 | 5 | require 'bundler/setup' # Set up gems listed in the Gemfile. 6 | 7 | begin 8 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 9 | rescue LoadError 10 | # bootsnap is an optional dependency, so if we don't have it it's fine 11 | # Do not load in production because file system (where cache would be written) is read-only 12 | nil 13 | end 14 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: async 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: it52_rails_production 11 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | default: &default 2 | adapter: postgresql 3 | encoding: unicode 4 | username: postgres 5 | password: postgres 6 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 7 | host: postgres 8 | timeout: 5000 9 | 10 | development: 11 | adapter: postgresql 12 | encoding: unicode 13 | username: postgres 14 | password: postgres 15 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 16 | host: localhost 17 | timeout: 5000 18 | database: it52_rails_dev 19 | 20 | test: 21 | adapter: postgresql 22 | encoding: unicode 23 | username: postgres 24 | password: postgres 25 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 26 | host: postgres 27 | timeout: 5000 28 | database: it52_rails_test 29 | 30 | production: 31 | adapter: postgresql 32 | encoding: unicode 33 | pool: <%= Integer(ENV.fetch('WEB_CONCURRENCY') { 2 }) * Integer(ENV.fetch('RAILS_MAX_THREADS') { 4 }) %> 34 | timeout: 5000 35 | url: <%= ENV.fetch('DATABASE_URL') { 'postgres://postgres:postgres@postgres:5432/it52' } %> 36 | -------------------------------------------------------------------------------- /config/deploy.rb: -------------------------------------------------------------------------------- 1 | # config valid for current version and patch releases of Capistrano 2 | lock '~> 3.11.2' 3 | 4 | set :application, 'it52' 5 | set :repo_url, 'git@example.com:me/my_repo.git' 6 | 7 | # Default branch is :master 8 | # ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp 9 | 10 | # Default deploy_to directory is /var/www/my_app_name 11 | # set :deploy_to, "/var/www/my_app_name" 12 | 13 | # Default value for :format is :airbrussh. 14 | # set :format, :airbrussh 15 | 16 | # You can configure the Airbrussh format using :format_options. 17 | # These are the defaults. 18 | # set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto 19 | 20 | # Default value for :pty is false 21 | # set :pty, true 22 | 23 | # Default value for :linked_files is [] 24 | # append :linked_files, "config/database.yml" 25 | 26 | # Default value for linked_dirs is [] 27 | # append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system" 28 | 29 | # Default value for default_env is {} 30 | # set :default_env, { path: "/opt/ruby/bin:$PATH" } 31 | 32 | # Default value for local_user is ENV['USER'] 33 | # set :local_user, -> { `git config user.name`.chomp } 34 | 35 | # Default value for keep_releases is 5 36 | # set :keep_releases, 5 37 | 38 | # Uncomment the following to require manually verifying the host key before first deploy. 39 | # set :ssh_options, verify_host_key: :secure 40 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load the Rails application. 4 | require_relative 'application' 5 | 6 | # Initialize the Rails application. 7 | Rails.application.initialize! 8 | -------------------------------------------------------------------------------- /config/environments/staging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Based on production defaults 4 | require Rails.root.join('config/environments/production') 5 | -------------------------------------------------------------------------------- /config/initializers/apipie.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Apipie.configure do |config| 4 | # config.app_name = "IT52" 5 | # config.api_base_url = "/api" 6 | # config.doc_base_url = "/apidoc" 7 | # # where is your API defined? 8 | # config.api_controllers_matcher = "#{Rails.root}/app/controllers/api/**/*.rb" 9 | # end 10 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # ActiveSupport::Reloader.to_prepare do 6 | # ApplicationController.renderer.defaults.merge!( 7 | # http_host: 'example.org', 8 | # https: false 9 | # ) 10 | # end 11 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Version of your assets, change this if you want to expire all your assets. 6 | Rails.application.config.assets.version = '1.0' 7 | 8 | # Add additional assets to the asset load path. 9 | 10 | Rails.application.config.assets.digest = true 11 | 12 | Rails.application.config.assets.compress = true 13 | 14 | # Rails.application.config.assets.paths << Emoji.images_path 15 | # Add Yarn node_modules folder to the asset load path. 16 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 17 | 18 | # Precompile additional assets. 19 | # application.js, application.css, and all non-JS/CSS in the app/assets 20 | # folder are already added. 21 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 22 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 6 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 7 | 8 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 9 | # Rails.backtrace_cleaner.remove_silencers! 10 | -------------------------------------------------------------------------------- /config/initializers/carrier_wave.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # require 'carrierwave/storage/abstract' 4 | if remote_storage = (Rails.env.production? || Rails.env.staging?) 5 | require 'carrierwave/storage/fog' 6 | else 7 | require 'carrierwave/storage/file' 8 | end 9 | 10 | CarrierWave.configure do |config| 11 | config.storage = remote_storage ? :fog : :file 12 | 13 | config.fog_credentials = { 14 | provider: 'AWS', 15 | aws_access_key_id: ENV.fetch('aws_access_key_id') { 'aws_access_key_id' }, 16 | aws_secret_access_key: ENV.fetch('aws_secret_access_key') { 'aws_secret_access_key' }, 17 | region: ENV.fetch('fog_region') { 'fog_region' }, 18 | host: ENV.fetch('fog_host') { 'fog_host' } 19 | } 20 | config.fog_use_ssl_for_aws = true 21 | config.fog_directory = ENV.fetch('aws_bucket') { 'aws_bucket' } 22 | config.fog_public = true 23 | config.fog_attributes = { 'Cache-Control' => "max-age=#{365.days.to_i}" } 24 | config.asset_host = ENV.fetch('aws_host') { nil } 25 | config.cache_dir = "#{Rails.root}/tmp/uploads" 26 | 27 | config.ignore_integrity_errors = false 28 | config.ignore_processing_errors = false 29 | config.ignore_download_errors = false 30 | end 31 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Specify a serializer for the signed and encrypted cookie jars. 6 | # Valid options are :json, :marshal, and :hybrid. 7 | Rails.application.config.action_dispatch.cookies_serializer = :json 8 | -------------------------------------------------------------------------------- /config/initializers/da_data.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | DaData.configure do |config| 4 | config.default_params = { locations_boost: [{ kladr_id: 5_200_000_100_000 }] }.freeze 5 | end 6 | -------------------------------------------------------------------------------- /config/initializers/draper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Draper::CollectionDecorator.delegate :current_page, :total_pages, :limit_value, :total_count 4 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Configure sensitive parameters which will be filtered from the log file. 6 | Rails.application.config.filter_parameters += %i[password token] 7 | -------------------------------------------------------------------------------- /config/initializers/high_voltage.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | HighVoltage.configure do |config| 4 | config.routes = false 5 | end 6 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new inflection rules using the following format. Inflections 6 | # are locale specific, and you may define rules for as many different 7 | # locales as you wish. All of these examples are active by default: 8 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 9 | # inflect.plural /^(ox)$/i, '\1en' 10 | # inflect.singular /^(ox)en/i, '\1' 11 | # inflect.irregular 'person', 'people' 12 | # inflect.uncountable %w( fish sheep ) 13 | # end 14 | 15 | # These inflection rules are supported but not enabled by default: 16 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 17 | # inflect.acronym 'RESTful' 18 | # end 19 | -------------------------------------------------------------------------------- /config/initializers/kaminari_config.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Kaminari.configure do |config| 4 | config.default_per_page = 30 5 | # config.max_per_page = nil 6 | # config.window = 4 7 | # config.outer_window = 0 8 | # config.left = 0 9 | # config.right = 0 10 | # config.page_method_name = :page 11 | # config.param_name = :page 12 | # config.params_on_first_page = false 13 | end 14 | -------------------------------------------------------------------------------- /config/initializers/meta_tags.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Use this setup block to configure all options available in MetaTags. 4 | MetaTags.configure do |config| 5 | # How many characters should the title meta tag have at most. Default is 70. 6 | # Set to nil or 0 to remove limits. 7 | # config.title_limit = 70 8 | 9 | # When true, site title will be truncated instead of title. Default is false. 10 | # config.truncate_site_title_first = false 11 | 12 | # Maximum length of the page description. Default is 300. 13 | # Set to nil or 0 to remove limits. 14 | # config.description_limit = 300 15 | 16 | # Maximum length of the keywords meta tag. Default is 255. 17 | # config.keywords_limit = 255 18 | 19 | # Default separator for keywords meta tag (used when an Array passed with 20 | # the list of keywords). Default is ", ". 21 | # config.keywords_separator = ', ' 22 | 23 | # When true, keywords will be converted to lowercase, otherwise they will 24 | # appear on the page as is. Default is true. 25 | # config.keywords_lowercase = true 26 | 27 | # When false, generated meta tags will be self-closing () instead 28 | # of open (``). Default is true. 29 | # config.open_meta_tags = true 30 | 31 | # List of additional meta tags that should use "property" attribute instead 32 | # of "name" attribute in tags. 33 | # config.property_tags.push( 34 | # 'x-hearthstone:deck', 35 | # ) 36 | end 37 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new mime types for use in respond_to blocks: 6 | # Mime::Type.register "text/richtext", :rtf 7 | -------------------------------------------------------------------------------- /config/initializers/pluralization.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # rubocop:disable Lint/SendWithMixinArgument 4 | require 'i18n/backend/pluralization' 5 | I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization) 6 | # rubocop:enable Lint/SendWithMixinArgument 7 | -------------------------------------------------------------------------------- /config/initializers/runtimeerror_notifier.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # if defined?(RuntimeerrorNotifier) 4 | # # Get your secret email address from RuntimeError.net and 5 | # # 1. Set it as environment variable RUNTIMEERROR_EMAIL (preferred method) 6 | # # 2. OR, change the value (legacy method) 7 | # RuntimeerrorNotifier.for ENV['RUNTIMEERROR_EMAIL'] 8 | 9 | # RuntimeerrorNotifier::Notifier::IGNORED_EXCEPTIONS.push(*%w[ 10 | # ActionController::RoutingError 11 | # ]) 12 | # end 13 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | Rails.application.config.session_store :cookie_store, key: '_it52_rails_session' 6 | -------------------------------------------------------------------------------- /config/initializers/sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | REDIS_OPTIONS = { url: ENV.fetch('REDIS_URL') { 'redis://redis:6379' }, 4 | db: 1 }.freeze 5 | 6 | Sidekiq.configure_server do |config| 7 | config.redis = REDIS_OPTIONS.dup 8 | end 9 | 10 | Sidekiq.configure_client do |config| 11 | config.redis = REDIS_OPTIONS.dup 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/silencer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if Rails.env.development? 4 | require 'silencer/logger' 5 | 6 | Rails.application.configure do 7 | config.middleware.swap( 8 | Rails::Rack::Logger, 9 | Silencer::Logger, 10 | config.log_tags, 11 | get: [%r{^/images/aws_host/uploads/}] 12 | ) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /config/initializers/string_to_url_extender.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class String 4 | def to_url 5 | parsed = Addressable::URI.heuristic_parse(self).to_s 6 | parsed if parsed&.match?(URI.regexp(%w[http https])) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /config/initializers/string_unicode_path.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class String 4 | def downcase 5 | if !frozen? 6 | Unicode.downcase(force_encoding('utf-8')) 7 | else 8 | Unicode.downcase(self) 9 | end 10 | end 11 | 12 | def downcase! 13 | replace(downcase) 14 | end 15 | 16 | def upcase 17 | if !frozen? 18 | Unicode.upcase(force_encoding('utf-8')) 19 | else 20 | Unicode.upcase(self) 21 | end 22 | end 23 | 24 | def upcase! 25 | replace upcase 26 | end 27 | 28 | def capitalize 29 | if !frozen? 30 | Unicode.capitalize(force_encoding('utf-8')) 31 | else 32 | Unicode.capitalize(self) 33 | end 34 | end 35 | 36 | def capitalize! 37 | replace capitalize 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /config/initializers/taggable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TagsParser < ActsAsTaggableOn::GenericParser 4 | def parse 5 | ActsAsTaggableOn::TagList.new.tap do |tag_list| 6 | tag_list.add @tag_list.split(%r{\,|\s|\||/|\;}) 7 | end 8 | end 9 | end 10 | 11 | ActsAsTaggableOn.default_parser = TagsParser 12 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # This file contains settings for ActionController::ParamsWrapper which 6 | # is enabled by default. 7 | 8 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 9 | ActiveSupport.on_load(:action_controller) do 10 | wrap_parameters format: [:json] 11 | end 12 | 13 | # To enable root element in JSON for ActiveRecord objects. 14 | # ActiveSupport.on_load(:active_record) do 15 | # self.include_root_in_json = true 16 | # end 17 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at http://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /config/locales/kaminari-ru.yml: -------------------------------------------------------------------------------- 1 | ru: 2 | views: 3 | pagination: 4 | first: "« Первая" 5 | last: "Последняя »" 6 | previous: "‹ Пред." 7 | next: "Следующая ›" 8 | truncate: "…" 9 | helpers: 10 | page_entries_info: 11 | one_page: 12 | display_entries: 13 | zero: "%{entry_name.capitalize} не найдено" 14 | one: "Отображение 1 %{entry_name}" 15 | other: "Отображение все %{count} %{entry_name}" 16 | more_pages: 17 | display_entries: "Отображение %{entry_name} %{first} - %{last} из %{total} всего" 18 | -------------------------------------------------------------------------------- /config/locales/plurals.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | { ru: 4 | { i18n: 5 | { plural: 6 | { keys: %i[zero one few many], 7 | rule: lambda { |n| 8 | if n == 0 9 | :zero 10 | elsif 11 | ((n % 10) == 1) && ((n % 100 != 11)) 12 | # 1, 21, 31, 41, 51, 61... 13 | :one 14 | elsif 15 | [2, 3, 4].include?(n % 10) \ 16 | && ![12, 13, 14].include?(n % 100) 17 | # 2-4, 22-24, 32-34... 18 | :few 19 | elsif (n % 10) == 0 || \ 20 | ![5, 6, 7, 8, 9].include?(n % 10) || \ 21 | ![11, 12, 13, 14].include?(n % 100) 22 | # 0, 5-20, 25-30, 35-40... 23 | :many 24 | end 25 | } } } } } 26 | -------------------------------------------------------------------------------- /config/locales/simple_form.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | simple_form: 3 | "yes": 'Yes' 4 | "no": 'No' 5 | required: 6 | # text: 'required' 7 | # mark: '*' 8 | # You can uncomment the line below if you need to overwrite the whole required html. 9 | # When using html, text and mark won't be used. 10 | html: '' 11 | error_notification: 12 | default_message: "Please review the problems below:" 13 | # Labels and hints examples 14 | # labels: 15 | # defaults: 16 | # password: 'Password' 17 | # user: 18 | # new: 19 | # email: 'E-mail to sign in.' 20 | # edit: 21 | # email: 'E-mail.' 22 | # hints: 23 | # defaults: 24 | # username: 'User name to sign in.' 25 | # password: 'No special characters, please.' 26 | 27 | -------------------------------------------------------------------------------- /config/locales/telegram.ru.yml: -------------------------------------------------------------------------------- 1 | ru: 2 | telegram: 3 | unknown_command: 'Мы таким командам не обучены. Вот только эти знаем: %{list}.' 4 | not_found: 'Мы не нашли событий, соответствующих вашему запросу.' 5 | help: > 6 | Бот позволяет получить информацию о событиях с сайта https://www.it52.info. 7 | Команды: 8 | - /get N – Получить полную справку о событии. N – номер мероприятия (цифра перед названием). По умолчанию выводит информацию о последнем зарегистрированном событии. 9 | - /previous N – Получить краткий список прошедших мероприятий. N может быть от 1 до 5. По умолчанию покажет последнее прошедшее. 10 | - /next N – Получить краткий список предстоящих мероприятий. N может быть от 1 до 5. По умолчанию покажет следующее. 11 | - /help – Помощь по командам 12 | 13 | Канал с анонсами событий @it52info. 14 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | workers Integer(ENV.fetch('WEB_CONCURRENCY') { 1 }) 4 | threads_count = Integer(ENV.fetch('RAILS_MAX_THREADS') { 4 }) 5 | threads 2, threads_count 6 | 7 | preload_app! 8 | 9 | rackup DefaultRackup if defined?(DefaultRackup) 10 | 11 | port Integer(ENV.fetch('PORT') { 3000 }) 12 | environment ENV.fetch('RACK_ENV') { 'development' } 13 | 14 | # stdout_redirect '/dev/stdout', '/dev/stderr', true 15 | 16 | on_worker_boot do 17 | # Worker specific setup for Rails 4.1+ 18 | # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot 19 | ActiveRecord::Base.establish_connection 20 | end 21 | -------------------------------------------------------------------------------- /config/sidekiq.yml: -------------------------------------------------------------------------------- 1 | --- 2 | :concurrency: 5 3 | staging: 4 | :concurrency: 10 5 | production: 6 | :concurrency: 2 7 | :queues: 8 | - critical 9 | - mailers 10 | - it52_active_job_development_mailers 11 | - it52_active_job_production_mailers 12 | - default 13 | - low 14 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.critical 15 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.mailers 16 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.default 17 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.low 18 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_critical 19 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_mailers 20 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_default 21 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_low 22 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | %w[ 4 | .ruby-version 5 | .rbenv-vars 6 | tmp/restart.txt 7 | tmp/caching-dev.txt 8 | ].each { |path| Spring.watch(path) } 9 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /config/unicorn/production.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | worker_processes 2 4 | preload_app true 5 | timeout 30 6 | 7 | before_fork do |_server, _worker| 8 | # Replace with MongoDB or whatever 9 | if defined?(ActiveRecord::Base) 10 | ActiveRecord::Base.connection.disconnect! 11 | # Rails.logger.info('Disconnected from ActiveRecord') 12 | end 13 | 14 | # If you are using Redis but not Resque, change this 15 | if defined?(Resque) 16 | Resque.redis.quit 17 | # Rails.logger.info('Disconnected from Redis') 18 | end 19 | 20 | sleep 1 21 | end 22 | 23 | after_fork do |_server, _worker| 24 | # Replace with MongoDB or whatever 25 | if defined?(ActiveRecord::Base) 26 | ActiveRecord::Base.establish_connection 27 | # Rails.logger.info('Connected to ActiveRecord') 28 | end 29 | 30 | # If you are using Redis but not Resque, change this 31 | if defined?(Resque) 32 | Resque.redis = ENV['REDIS_URI'] 33 | # Rails.logger.info('Connected to Redis') 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /config/webpack/development.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | const config = environment.toWebpackConfig(); 5 | config.output.filename = "js/[name]-[hash].js" 6 | 7 | module.exports = config 8 | -------------------------------------------------------------------------------- /config/webpack/environment.js: -------------------------------------------------------------------------------- 1 | const { environment } = require('@rails/webpacker') 2 | 3 | module.exports = environment 4 | -------------------------------------------------------------------------------- /config/webpack/production.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /config/webpack/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /db/migrate/20140430090217_sorcery_core.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryCore < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :users do |t| 6 | t.string :email, null: false 7 | t.string :crypted_password, null: false 8 | t.string :salt, null: false 9 | 10 | t.timestamps 11 | end 12 | 13 | add_index :users, :email, unique: true 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20140430090218_sorcery_remember_me.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryRememberMe < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :remember_me_token, :string, default: nil 6 | add_column :users, :remember_me_token_expires_at, :datetime, default: nil 7 | 8 | add_index :users, :remember_me_token 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20140430090219_sorcery_reset_password.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryResetPassword < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :reset_password_token, :string, default: nil 6 | add_column :users, :reset_password_token_expires_at, :datetime, default: nil 7 | add_column :users, :reset_password_email_sent_at, :datetime, default: nil 8 | 9 | add_index :users, :reset_password_token 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20140430090220_sorcery_external.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryExternal < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :authentications do |t| 6 | t.integer :user_id, null: false 7 | t.string :provider, :uid, null: false 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20140430090221_sorcery_activity_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryActivityLogging < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :last_login_at, :datetime, default: nil 6 | add_column :users, :last_logout_at, :datetime, default: nil 7 | add_column :users, :last_activity_at, :datetime, default: nil 8 | add_column :users, :last_login_from_ip_address, :string, default: nil 9 | 10 | add_index :users, %i[last_logout_at last_activity_at] 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20140430090944_add_name_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddNameToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :name, :string 6 | add_index :users, :name 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140430100247_create_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :events do |t| 6 | t.string :title, null: false 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20140507084053_add_role_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddRoleToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :role, :integer, index: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140507093209_add_organizer_referenses_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddOrganizerReferensesToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_reference :events, :organizer, index: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140507093336_add_published_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPublishedToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :published, :boolean, default: false 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140508095102_add_description_and_started_at_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddDescriptionAndStartedAtToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :description, :text 6 | add_column :events, :started_at, :datetime 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140508105348_create_event_participations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateEventParticipations < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :event_participations do |t| 6 | t.references :user, index: true 7 | t.references :event, index: true 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20140520095617_add_first_name_and_last_name_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddFirstNameAndLastNameToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :first_name, :string 6 | add_column :users, :last_name, :string 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140520095824_add_bio_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddBioToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :bio, :text 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140521054705_add_title_image_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddTitleImageToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :title_image, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140521062142_add_avatar_image_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddAvatarImageToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :avatar_image, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140521082751_nullable_sorcery_core.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class NullableSorceryCore < ActiveRecord::Migration[4.2] 4 | def change 5 | change_column_null(:users, :email, true) 6 | change_column_null(:users, :crypted_password, true) 7 | change_column_null(:users, :salt, true) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20140522134058_add_link_to_authentications.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddLinkToAuthentications < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :authentications, :link, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140602183636_add_place_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPlaceToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :place, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140901165216_add_token_to_authentications.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddTokenToAuthentications < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :authentications, :token, :string 6 | add_column :authentications, :token_expires, :datetime 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140902165236_rename_users_name_to_nickname.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RenameUsersNameToNickname < ActiveRecord::Migration[4.2] 4 | def change 5 | rename_column :users, :name, :nickname 6 | change_column :users, :nickname, :string, uniq: true, index: true, default: '' 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140902180100_create_friendly_id_slugs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateFriendlyIdSlugs < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :friendly_id_slugs do |t| 6 | t.string :slug, null: false 7 | t.integer :sluggable_id, null: false 8 | t.string :sluggable_type, limit: 50 9 | t.string :scope 10 | t.datetime :created_at 11 | end 12 | add_index :friendly_id_slugs, :sluggable_id 13 | add_index :friendly_id_slugs, %i[slug sluggable_type] 14 | add_index :friendly_id_slugs, %i[slug sluggable_type scope], unique: true 15 | add_index :friendly_id_slugs, :sluggable_type 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20140902181203_add_slug_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddSlugToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :slug, :string 6 | add_index :users, :slug, unique: true 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140902183616_add_website_to_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddWebsiteToUser < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :website, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20141111093102_drop_index_users_on_email.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DropIndexUsersOnEmail < ActiveRecord::Migration[4.2] 4 | def change 5 | remove_index :users, name: 'index_users_on_email' 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20141125211802_add_published_at_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPublishedAtToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :published_at, :datetime 6 | 7 | Event.published.each do |event| 8 | publish_time = event.past? ? event.created_at : Time.zone.now 9 | event.update(published_at: publish_time) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20141126154826_add_slug_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddSlugToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :slug, :string 6 | add_index :events, :slug, unique: true 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20141127113116_add_subscription_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddSubscriptionToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :subscription, :boolean 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20150516133610_add_point_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPointToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :location, :point, geographic: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20181010093500_add_employment_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddEmploymentToUsers < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :users, :employment, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20181011094902_add_foreign_link_to_event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddForeignLinkToEvent < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :events, :foreign_link, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20181119192414_add_pageviews_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPageviewsToEvents < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :events, :pageviews, :integer, default: 0 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20190301095130_add_kind_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddKindToEvents < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :events, :kind, :integer, default: 0 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20190301180740_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 1) 4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 5 | class ActsAsTaggableOnMigration < ActiveRecord::Migration[4.2]; end 6 | else 7 | class ActsAsTaggableOnMigration < ActiveRecord::Migration; end 8 | end 9 | ActsAsTaggableOnMigration.class_eval do 10 | def self.up 11 | create_table :tags do |t| 12 | t.string :name 13 | end 14 | 15 | create_table :taggings do |t| 16 | t.references :tag 17 | 18 | # You should make sure that the column created is 19 | # long enough to store the required class names. 20 | t.references :taggable, polymorphic: true 21 | t.references :tagger, polymorphic: true 22 | 23 | # Limit is created to prevent MySQL error on index 24 | # length for MyISAM table type: http://bit.ly/vgW2Ql 25 | t.string :context, limit: 128 26 | 27 | t.datetime :created_at 28 | end 29 | 30 | add_index :taggings, :tag_id 31 | add_index :taggings, %i[taggable_id taggable_type context] 32 | end 33 | 34 | def self.down 35 | drop_table :taggings 36 | drop_table :tags 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /db/migrate/20190301180741_add_missing_unique_indices.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 2) 4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 5 | class AddMissingUniqueIndices < ActiveRecord::Migration[4.2]; end 6 | else 7 | class AddMissingUniqueIndices < ActiveRecord::Migration; end 8 | end 9 | AddMissingUniqueIndices.class_eval do 10 | def self.up 11 | add_index :tags, :name, unique: true 12 | 13 | remove_index :taggings, :tag_id if index_exists?(:taggings, :tag_id) 14 | remove_index :taggings, %i[taggable_id taggable_type context] 15 | add_index :taggings, 16 | %i[tag_id taggable_id taggable_type context tagger_id tagger_type], 17 | unique: true, name: 'taggings_idx' 18 | end 19 | 20 | def self.down 21 | remove_index :tags, :name 22 | 23 | remove_index :taggings, name: 'taggings_idx' 24 | 25 | add_index :taggings, :tag_id unless index_exists?(:taggings, :tag_id) 26 | add_index :taggings, %i[taggable_id taggable_type context] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /db/migrate/20190301180742_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 3) 4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 5 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]; end 6 | else 7 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration; end 8 | end 9 | AddTaggingsCounterCacheToTags.class_eval do 10 | def self.up 11 | add_column :tags, :taggings_count, :integer, default: 0 12 | 13 | ActsAsTaggableOn::Tag.reset_column_information 14 | ActsAsTaggableOn::Tag.find_each do |tag| 15 | ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) 16 | end 17 | end 18 | 19 | def self.down 20 | remove_column :tags, :taggings_count 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/20190301180743_add_missing_taggable_index.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 4) 4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 5 | class AddMissingTaggableIndex < ActiveRecord::Migration[4.2]; end 6 | else 7 | class AddMissingTaggableIndex < ActiveRecord::Migration; end 8 | end 9 | AddMissingTaggableIndex.class_eval do 10 | def self.up 11 | add_index :taggings, %i[taggable_id taggable_type context] 12 | end 13 | 14 | def self.down 15 | remove_index :taggings, %i[taggable_id taggable_type context] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20190301180744_change_collation_for_tag_names.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 5) 4 | # This migration is added to circumvent issue #623 and have special characters 5 | # work properly 6 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 7 | class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]; end 8 | else 9 | class ChangeCollationForTagNames < ActiveRecord::Migration; end 10 | end 11 | ChangeCollationForTagNames.class_eval do 12 | def up 13 | if ActsAsTaggableOn::Utils.using_mysql? 14 | execute('ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;') 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20190301180745_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 6) 4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 5 | class AddMissingIndexesOnTaggings < ActiveRecord::Migration[4.2]; end 6 | else 7 | class AddMissingIndexesOnTaggings < ActiveRecord::Migration; end 8 | end 9 | AddMissingIndexesOnTaggings.class_eval do 10 | def change 11 | add_index :taggings, :tag_id unless index_exists? :taggings, :tag_id 12 | unless index_exists? :taggings, :taggable_id 13 | add_index :taggings, :taggable_id 14 | end 15 | unless index_exists? :taggings, :taggable_type 16 | add_index :taggings, :taggable_type 17 | end 18 | add_index :taggings, :tagger_id unless index_exists? :taggings, :tagger_id 19 | add_index :taggings, :context unless index_exists? :taggings, :context 20 | 21 | unless index_exists? :taggings, %i[tagger_id tagger_type] 22 | add_index :taggings, %i[tagger_id tagger_type] 23 | end 24 | 25 | unless index_exists? :taggings, %i[taggable_id taggable_type tagger_id context], name: 'taggings_idy' 26 | add_index :taggings, %i[taggable_id taggable_type tagger_id context], name: 'taggings_idy' 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /db/migrate/20190605125210_create_donations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateDonations < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :donations do |t| 6 | t.float :amount, null: false 7 | t.integer :kind, null: false 8 | t.float :amount_in_rub, null: false 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20190612020134_create_addresses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateAddresses < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :addresses do |t| 6 | t.string :unrestricted_value, null: false 7 | t.string :city, null: false 8 | t.string :street, null: false 9 | t.string :house, null: false 10 | t.string :kladr_id, null: false 11 | t.string :fias_id, null: false 12 | t.float :lat, null: false 13 | t.float :long, null: false 14 | 15 | t.timestamps 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20190612020440_add_address_id_to_event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddAddressIdToEvent < ActiveRecord::Migration[5.2] 4 | def change 5 | add_reference :events, :address, foreign_key: true 6 | add_column :events, :address_comment, :string 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20190624125250_create_startups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateStartups < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :startups do |t| 6 | t.string :title, null: false, index: true 7 | t.string :url 8 | t.string :slug, index: true 9 | t.string :logo 10 | t.string :intro 11 | t.text :description, null: false 12 | t.jsonb :contacts, default: { name: '', email: '' } 13 | t.references :author, null: false, index: true 14 | 15 | t.timestamps 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file should contain all the record creation needed to seed the database with its default values. 4 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 5 | # 6 | # Examples: 7 | # 8 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 9 | # Mayor.create(name: 'Emanuel', city: cities.first) 10 | 11 | email = 'admin@it52.info' 12 | pass = '12345678' 13 | 14 | admin_attrs = FactoryBot.attributes_for :admin, 15 | email: email, 16 | password: pass, 17 | password_confirmation: pass 18 | 19 | admin = User.where(email: email).first_or_create 20 | admin.update(admin_attrs) 21 | 22 | users = FactoryBot.create_list :user, 40 23 | 24 | (1..4).each do |i| 25 | event = FactoryBot.create :event, :published, :with_markdown, started_at: i.months.from_now 26 | event.participants << users.sample((10..40).to_a.sample) 27 | end 28 | -------------------------------------------------------------------------------- /deploy/systemd/it52.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=it52 service with docker-compose 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | WorkingDirectory=/opt/it52 9 | 10 | Environment="COMPOSE_PROJECT_NAME=it52" 11 | 12 | ExecStart=/usr/local/bin/docker-compose -f docker/docker-compose.production.yml up rails sidekiq 13 | ExecStop=/usr/local/bin/docker-compose -f docker/docker-compose.production.yml down rails sidekiq 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /deploy/systemd/metabase.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=it52 metabase service 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | WorkingDirectory=/opt/it52 9 | 10 | ExecStart=/usr/bin/docker run -p 3010:3000 --env-file /opt/it52/docker/.env.metabase --name metabase metabase/metabase 11 | ExecStop=/usr/bin/docker rm metabase 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /docker/docker-compose.production.yml: -------------------------------------------------------------------------------- 1 | version: '3.2' 2 | services: 3 | redis: 4 | image: redis:alpine 5 | volumes: 6 | - 'redis:/data' 7 | 8 | rails: 9 | image: ${COMPOSE_PROJECT_NAME}/rails:production 10 | tmpfs: 11 | - /tmp 12 | stdin_open: true 13 | tty: true 14 | env_file: 15 | - '/opt/${COMPOSE_PROJECT_NAME}/docker/.env' 16 | command: bin/rails s -b 0.0.0.0 -p 3000 17 | depends_on: 18 | - redis 19 | ports: 20 | - '3000:3000' 21 | volumes: 22 | - log:/${COMPOSE_PROJECT_NAME}/log 23 | - rails_cache:/${COMPOSE_PROJECT_NAME}/tmp/cache 24 | - tmp_uploads:/${COMPOSE_PROJECT_NAME}/tmp/uploads 25 | - /opt/${COMPOSE_PROJECT_NAME}/public:/${COMPOSE_PROJECT_NAME}/public:delegated 26 | 27 | sidekiq: 28 | image: ${COMPOSE_PROJECT_NAME}/rails:production 29 | tmpfs: 30 | - /tmp 31 | stdin_open: true 32 | tty: true 33 | env_file: 34 | - '/opt/${COMPOSE_PROJECT_NAME}/docker/.env' 35 | command: bundle exec sidekiq -C config/sidekiq.yml 36 | depends_on: 37 | - redis 38 | 39 | volumes: 40 | redis: 41 | log: 42 | rails_cache: 43 | tmp_uploads: 44 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/lib/assets/.keep -------------------------------------------------------------------------------- /lib/da_data.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'da_data/configuration' 4 | require 'da_data/request' 5 | 6 | module DaData 7 | class << self 8 | attr_accessor :configuration 9 | end 10 | 11 | def self.configuration 12 | @configuration ||= Configuration.new 13 | end 14 | 15 | def self.reset 16 | @configuration = Configuration.new 17 | end 18 | 19 | def self.configure 20 | yield(configuration) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/da_data/configuration.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DaData 4 | class Configuration 5 | attr_accessor :auth_token, :auth_secret, :default_params 6 | 7 | def initialize 8 | @auth_token = ENV.fetch('DADATA_AUTH_TOKEN') { nil } 9 | @auth_secret = ENV.fetch('DADATA_AUTH_SECRET') { nil } 10 | @default_params = {} 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/rails/sub_test_task.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Draper workaround for Rails 5 4 | require 'rake/testtask' 5 | 6 | class Rails::SubTestTask < Rake::TestTask 7 | end -------------------------------------------------------------------------------- /lib/tasks/events.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | namespace :events do 4 | desc 'Update events pageviews from Google Analytics' 5 | task update_pageviews: :environment do 6 | UpdateEventPageviews.perform 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/templates/slim/scaffold/_form.html.slim: -------------------------------------------------------------------------------- 1 | = simple_form_for(@<%= singular_table_name %>) do |f| 2 | = f.error_notification 3 | 4 | .form-inputs 5 | <%- attributes.each do |attribute| -%> 6 | = f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> 7 | <%- end -%> 8 | 9 | .form-actions 10 | = f.button :submit 11 | -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/log/.keep -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Страницы, которую вы запрашиваете не существует (404) 5 | 6 | 22 | 23 | 24 | 25 | 28 | 29 |
30 |

Ой!

31 |

Такой страницы у нас нет.

32 |

33 | Вернуться на главную страницу. 34 |

35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Кажется, что-то пошло не так (500) 5 | 6 | 22 | 23 | 24 | 25 | 28 | 29 |
30 |

Кажется, что-то пошло не так.

31 |

32 | Мы уже знаем об этом и исправим проблему в ближайшее время. 33 | Попробуйте повторить запрос позднее. 34 |

35 | 36 |

37 | Вернуться на главную страницу. 38 |

39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /public/ads.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/public/ads.txt -------------------------------------------------------------------------------- /public/app-ads.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/public/app-ads.txt -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/public/favicon.ico -------------------------------------------------------------------------------- /public/logo-it52-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/public/logo-it52-96x96.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | User-agent: * 5 | Allow: / 6 | Host: https://www.it52.info 7 | Crawl-delay: 2 8 | Sitemap: https://www.it52.info/sitemap.xml 9 | -------------------------------------------------------------------------------- /public/yandex_637a660a79fbb6d1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Verification: 637a660a79fbb6d1 6 | 7 | -------------------------------------------------------------------------------- /spec/controllers/mailchimp_hooks_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe MailchimpHooksController do 4 | describe 'POST #update_subscription' do 5 | let!(:subscribed_user) { FactoryBot.create(:user, :subscribed) } 6 | let!(:unsubscribed_user) { FactoryBot.create(:user, :unsubscribed) } 7 | 8 | let(:subscription_params) do 9 | { token: ENV.fetch('mailchimp_hooks_token') { 'mailchimp_hooks_token' }, 10 | type: 'unsubscribe', 11 | fired_at: '2014-12-08 18:20:30', 12 | data: { 13 | action: 'unsub', 14 | reason: 'manual', 15 | id: '27b600e23a', 16 | email: subscribed_user.email, 17 | email_type: 'html', 18 | ip_opt: '54.78.87.176', 19 | web_id: '125886081', 20 | list_id: '51957c4f07' 21 | } } 22 | end 23 | 24 | let(:unsubscription_params) do 25 | subscription_params.deep_merge( 26 | type: 'subscribe', 27 | data: { email: unsubscribed_user.email } 28 | ) 29 | end 30 | 31 | it 'Mailchimp hook should unsubscribe user' do 32 | post :update_subscription, params: subscription_params 33 | subscribed_user.reload 34 | expect(subscribed_user.subscription).to eq false 35 | end 36 | 37 | it 'Mailchimp hook should subscribe user' do 38 | post :update_subscription, params: unsubscription_params 39 | unsubscribed_user.reload 40 | expect(subscribed_user.subscription).to eq true 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /spec/controllers/sitemaps_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe SitemapsController do 4 | render_views 5 | 6 | describe 'GET index' do 7 | before do 8 | FactoryBot.create(:event, :published) 9 | get :index, format: :xml 10 | end 11 | 12 | it { expect(response).to have_http_status(:ok) } 13 | it { expect(response).to be_ok } 14 | it { expect(response.content_type).to eq 'application/xml' } 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/controllers/turbo/events_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe Turbo::EventsController do 4 | render_views 5 | 6 | describe 'GET index' do 7 | before do 8 | create(:event, :published) 9 | create(:event) 10 | get :index, format: :rss 11 | end 12 | 13 | it 'returns valid response' do 14 | expect(response).to have_http_status(:ok) 15 | expect(response.content_type).to eq 'application/rss+xml' 16 | expect(Nokogiri::XML(response.body).css('channel item').count).to eq 1 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/factories/addresses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: addresses 6 | # 7 | # id :bigint not null, primary key 8 | # city :string not null 9 | # street :string not null 10 | # house :string not null 11 | # kladr_id :string not null 12 | # fias_id :string not null 13 | # lat :float not null 14 | # long :float not null 15 | # created_at :datetime not null 16 | # updated_at :datetime not null 17 | # 18 | 19 | FactoryBot.define do 20 | factory :address do 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/factories/event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | FactoryBot.define do 4 | factory :event do 5 | title { FFaker::Lorem.words(4).join(' ') } 6 | description { FFaker::Lorem.paragraphs(3).join("\n\n") } 7 | place { FFaker::Address.street_address } 8 | started_at { 1.month.from_now } 9 | tag_list { FFaker::Lorem.words(2) } 10 | organizer { create(:user) } 11 | 12 | trait :with_markdown do 13 | description { %(I'm **description** with _markdown_.) } 14 | end 15 | 16 | trait :published do 17 | published_at { Time.current } 18 | published { true } 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/factories/startups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | FactoryBot.define do 4 | factory :startup do 5 | title { FFaker::Company.name } 6 | url { FFaker::Internet.http_url } 7 | logo { Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/logo.png'), 'image/png') } 8 | intro { FFaker::Company.catch_phrase } 9 | description { FFaker::LoremRU.paragraphs(5).join("\n\n") } 10 | contacts { { contacts: [{ name: FFaker::Name.name, email: FFaker::Internet.email }] } } 11 | author { create(:user) } 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | pass = Devise.friendly_token 4 | 5 | FactoryBot.define do 6 | factory :user do 7 | email { FFaker::Internet.email } 8 | first_name { FFaker::Name.first_name } 9 | last_name { FFaker::Name.last_name } 10 | password { pass } 11 | password_confirmation { pass } 12 | remember_me { false } 13 | confirmed_at { Time.zone.now } 14 | 15 | factory :admin do 16 | role { :admin } 17 | end 18 | 19 | factory :unconfirmed_user do 20 | confirmed_at { nil } 21 | end 22 | 23 | trait :subscribed do 24 | subscription { true } 25 | end 26 | 27 | trait :unsubscribed do 28 | subscription { false } 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/fixtures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/spec/fixtures/logo.png -------------------------------------------------------------------------------- /spec/lib/da_data/request_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe DaData::Request do 4 | subject { described_class.new(:suggest_address) } 5 | 6 | before { allow(subject.client).to receive(:post).and_return('{"a": 1}') } 7 | 8 | describe '.new' do 9 | it { expect(subject.content_type).to eq 'application/json' } 10 | 11 | it { 12 | expect(subject.client.default_options.headers.to_h) 13 | .to include('Content-Type' => 'application/json', 'Accept' => 'application/json') 14 | } 15 | end 16 | 17 | describe '#query' do 18 | it { expect(subject.query('')).to eq('a' => 1) } 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /spec/models/event_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: events 6 | # 7 | # id :integer not null, primary key 8 | # title :string(255) not null 9 | # created_at :datetime 10 | # updated_at :datetime 11 | # organizer_id :integer 12 | # published :boolean default(FALSE) 13 | # description :text 14 | # started_at :datetime 15 | # title_image :string(255) 16 | # place :string(255) 17 | # published_at :datetime 18 | # slug :string(255) 19 | # location :point 20 | # foreign_link :string 21 | # pageviews :integer default(0) 22 | # kind :integer default("event") 23 | # address_id :bigint 24 | # address_comment :string 25 | # 26 | 27 | require 'rails_helper' 28 | 29 | describe Event do 30 | describe 'should validate title' do 31 | let(:event) { FactoryBot.build :event, title: '' } 32 | 33 | it { expect(event).not_to be_valid } 34 | end 35 | 36 | describe 'should validate place' do 37 | let(:event) { FactoryBot.build :event, place: '' } 38 | 39 | it { expect(event).not_to be_valid } 40 | end 41 | 42 | describe 'should validate organizer' do 43 | let(:event) { FactoryBot.build :event, organizer: nil } 44 | 45 | it { expect(event).not_to be_valid } 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/support/codecov.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if ENV['CI'] == 'true' 4 | require 'simplecov' 5 | SimpleCov.start 'rails' 6 | 7 | require 'codecov' 8 | SimpleCov.formatter = SimpleCov::Formatter::Codecov 9 | end 10 | -------------------------------------------------------------------------------- /spec/support/database_cleaner.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'database_cleaner' 4 | 5 | DatabaseCleaner.allow_remote_database_url = true 6 | DatabaseCleaner.strategy = :transaction 7 | 8 | RSpec.configure do |config| 9 | config.before(:suite) do 10 | DatabaseCleaner.clean_with(:truncation) 11 | end 12 | 13 | config.around do |example| 14 | DatabaseCleaner.cleaning do 15 | example.run 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/support/factory_bot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |config| 4 | config.include FactoryBot::Syntax::Methods 5 | end 6 | -------------------------------------------------------------------------------- /spec/support/helpers/response.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Helpers 4 | module Response 5 | def response_body 6 | JSON.parse(response.body) 7 | rescue JSON::ParserError 8 | response.body 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/support/webmock.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'webmock/rspec' 4 | 5 | WebMock.disable_net_connect!(allow_localhost: true) 6 | -------------------------------------------------------------------------------- /start_server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker-compose -f docker/docker-compose.yml down 4 | [ -e tmp/pids/server.pid ] && rm tmp/pids/server.pid 5 | rm -fr public/packs/* 6 | docker-compose -f docker/docker-compose.yml up 7 | -------------------------------------------------------------------------------- /swagger.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/8a522cb622b0ac04107acf531eb635ee1fe84903/swagger.json -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": false, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "lib": ["es6", "dom"], 7 | "module": "es6", 8 | "moduleResolution": "node", 9 | "baseUrl": ".", 10 | "paths": { 11 | "*": ["node_modules/*", "app/javascript/*"] 12 | }, 13 | "sourceMap": true, 14 | "target": "es5", 15 | "noEmit": true 16 | }, 17 | "exclude": [ 18 | "**/*.spec.ts", 19 | "node_modules", 20 | "vendor", 21 | "public" 22 | ], 23 | "compileOnSave": false 24 | } 25 | --------------------------------------------------------------------------------