13 |
14 | This project consist of building a mobile web app for an Events Scheduler using Rails API as backend, and ReactJS as frontend.
15 |
16 | [](https://www.youtube.com/watch?v=YYvNv9WAFgM)
17 |
18 | In this project, we will build a Web App with the following technologies:
19 | - API
20 | - Ruby on Rails
21 | - PostgreSQL
22 |
23 | - Frontend (Inside /client folder)
24 | - React
25 | - Redux
26 |
27 | ## Technologies used
28 |
29 | - Ruby on Rails
30 | - RSpec
31 | - PostgreSQL
32 | - ReactJS
33 | - Redux
34 | - Git
35 | - Bootstrap
36 | - HTML & CSS
37 | - Heroku
38 |
39 | ## Live Version
40 | [Events Scheduler Web App](https://rocky-reef-66767.herokuapp.com)
41 |
42 | ## Prerequisites
43 |
44 | - [Ruby](https://www.ruby-lang.org/en/): we recommend using
45 | [rbenv](https://github.com/rbenv/rbenv) to install the Ruby version listed on
46 | the badge.
47 | - [Yarn](https://yarnpkg.com/): please refer to their
48 | [installation guide](https://yarnpkg.com/en/docs/install).
49 | - [PostgreSQL](https://www.postgresql.org/) 11.5 or higher.
50 |
51 | ## Installation
52 | - To get started with the app, first clone the repo and `cd` into the directory:
53 |
54 | ```
55 | $ git clone https://github.com/AndresFMoya/react-rails_event_scheduler.git
56 | $ cd react-rails_event_scheduler
57 | ```
58 | - You need to install the gems:
59 | - You may need to first run `bundle install` if you have older gems in your environment from previous Rails work. If you get an error message like `Your Ruby version is 2.x.x, but your Gemfile specified 2.4.4` then you need to install the ruby version 2.6.4 using `rvm` or `rbenv`.
60 | - Using **rvm**: `rvm install 2.6.4` followed by `rvm use 2.6.4`
61 | - Using **rbenv**: `rbenv install 2.6.4` followed by `rbenv local 2.6.4`
62 | - Install gems with `bundle install --without production` from the rails root folder, to install the gems you'll need, excluding those needed only in production.
63 | - Run `rails db:create` followed by `rails db:migrate` to set up the database
64 | - Install static assets (like external javascript libraries, fonts) with `yarn install`
65 | - To launch the app locally run: `heroku local -f Procfile.dev`.
66 |
67 | ## 🤝 Contributing
68 |
69 | Contributions, issues and feature requests are welcome! Feel free to check [issues page](https://github.com/AndresFMoya/react-rails_event_scheduler/issues).
70 |
71 | 1. Fork it (https://github.com/AndresFMoya/react-rails_event_scheduler/fork)
72 | 2. Create your working branch (git checkout -b [choose-a-name])
73 | 3. Commit your changes (git commit -am 'what this commit will fix/add/improve')
74 | 4. Push to the branch (git push origin [chosen-name])
75 | 5. Create a new pull request
76 |
77 |
78 | ## Contributors
79 |
80 | Andrés Moya - [GitHub](https://github.com/andresfmoya)
81 |
82 | ## Show your support
83 |
84 | Give a ⭐️ if you like this project!
85 |
86 | ## License
87 |
88 | This project is [MIT](https://github.com/AndresFMoya/react-rails_event_scheduler/blob/develop/LICENSE) licensed.
89 |
90 | ## 📞 Get in Touch!
91 | I will love to hear about you at one of the following places! :heart:
92 |
93 | - [LinkedIn](https://www.linkedin.com/in/andres-f-moya/)
94 | - [Twitter](https://www.twitter.com/andmedev/)
95 | - .
96 |
97 |
82 | );
83 | };
84 |
85 | SignUp.propTypes = {
86 | signUp: PropTypes.func.isRequired,
87 | history: PropTypes.oneOfType([PropTypes.object]).isRequired,
88 | };
89 |
90 |
91 | export default connect(null, { signUp })(SignUp);
92 |
--------------------------------------------------------------------------------
/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import { PersistGate } from 'redux-persist/integration/react';
5 | import App from './App';
6 | import { store, persistor } from './redux/store';
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 |
13 | ,
14 | document.getElementById('root'),
15 | );
16 |
--------------------------------------------------------------------------------
/client/src/redux/actions/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const LOAD_EVENTS = 'LOAD_EVENTS';
2 | export const LOAD_EVENTS_FOLLOWED = 'LOAD_EVENTS_FOLLOWED';
3 |
4 | export const AUTHENTICATION_REQUEST = 'AUTHENTICATION_REQUEST';
5 | export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS';
6 | export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE';
7 | export const LOGOUT = 'LOGOUT';
8 |
9 | export const ADD_EVENT_FOLLOWER = 'ADD_EVENT_FOLLOWER';
10 | export const LOAD_EVENT_FOLLOWERS = 'LOAD_EVENT_FOLLOWERS';
11 | export const DELETE_EVENT_FOLLOWER = 'DELETE_EVENT_FOLLOWER';
12 |
13 | export const RESET = 'RESET';
14 |
--------------------------------------------------------------------------------
/client/src/redux/actions/authActions.js:
--------------------------------------------------------------------------------
1 | import * as types from './actionTypes';
2 |
3 | const authRequest = () => ({
4 | type: types.AUTHENTICATION_REQUEST,
5 | });
6 |
7 | const authSuccess = (user, token) => ({
8 | type: types.AUTHENTICATION_SUCCESS,
9 | user,
10 | token,
11 | });
12 |
13 | const authFailure = (errors) => ({
14 | type: types.AUTHENTICATION_FAILURE,
15 | errors,
16 | });
17 |
18 | const resetAction = () => ({
19 | type: types.RESET,
20 | });
21 |
22 | export const logout = () => dispatch => {
23 | localStorage.clear();
24 | dispatch(resetAction());
25 | return dispatch({
26 | type: types.LOGOUT,
27 | });
28 | };
29 |
30 | export const getUser = (credentials) => {
31 | const request = new Request('/find_user', {
32 | method: 'POST',
33 | headers: new Headers({
34 | 'Content-Type': 'application/json',
35 | Authorization: `Bearer ${localStorage.token}`,
36 | }),
37 | body: JSON.stringify({ user: credentials }),
38 | });
39 | return fetch(request)
40 | .then(response => response.json())
41 | .then(userJson => userJson)
42 | .catch(error => error);
43 | };
44 |
45 | export const authenticate = (credentials) => dispatch => {
46 | dispatch(authRequest());
47 | return fetch('/login', {
48 | method: 'POST',
49 | headers: {
50 | 'Content-Type': 'application/json',
51 | },
52 | body: JSON.stringify({ auth: credentials }),
53 | })
54 | .then(res => res.json())
55 | .then((response) => {
56 | const token = response.jwt;
57 | localStorage.setItem('token', token);
58 | return getUser(credentials);
59 | })
60 | .then((user) => {
61 | dispatch(authSuccess(user, localStorage.token));
62 | })
63 | .catch((errors) => {
64 | dispatch(authFailure(errors));
65 | localStorage.clear();
66 | });
67 | };
68 |
69 | export const signUp = (user) => {
70 | const newUser = user;
71 | return dispatch => fetch('/sign_up', {
72 | method: 'POST',
73 | headers: {
74 | Accept: 'application/json',
75 | 'Content-Type': 'application/json',
76 | },
77 | body: JSON.stringify({ user }),
78 | })
79 | .then(response => response.json())
80 | .then(() => {
81 | dispatch(authenticate({
82 | username: newUser.username,
83 | email: newUser.email,
84 | password: newUser.password,
85 | }));
86 | })
87 | .catch((errors) => {
88 | dispatch(authFailure(errors));
89 | });
90 | };
91 |
--------------------------------------------------------------------------------
/client/src/redux/actions/eventActions.js:
--------------------------------------------------------------------------------
1 | import * as types from './actionTypes';
2 |
3 | const loadEvents = (events) => ({
4 | type: types.LOAD_EVENTS,
5 | events,
6 | });
7 |
8 | export default loadEvents;
9 |
--------------------------------------------------------------------------------
/client/src/redux/actions/followActions.js:
--------------------------------------------------------------------------------
1 | import * as types from './actionTypes';
2 |
3 | const addEventFollower = event => ({
4 | type: types.ADD_EVENT_FOLLOWER,
5 | event,
6 | });
7 |
8 | const destroyEventFollower = event => ({
9 | type: types.DELETE_EVENT_FOLLOWER,
10 | event,
11 | });
12 |
13 | const loadEventsFollow = (events) => ({
14 | type: types.LOAD_EVENTS_FOLLOWED,
15 | events,
16 | });
17 |
18 | export const loadEventsFollowed = (credentials) => dispatch => {
19 | const request = new Request('/find_user_events', {
20 | method: 'POST',
21 | headers: new Headers({
22 | 'Content-Type': 'application/json',
23 | Authorization: `Bearer ${localStorage.token}`,
24 | }),
25 | body: JSON.stringify({ user: credentials }),
26 | });
27 | return fetch(request)
28 | .then(response => response.json())
29 | .then(response => dispatch(loadEventsFollow(response)))
30 | .catch(error => error);
31 | };
32 |
33 | export const createEventFollower = eventId => (dispatch) => fetch('/api/v1/event_followers', {
34 | method: 'POST',
35 | headers: {
36 | Authorization: `Bearer ${localStorage.token}`,
37 | 'Content-Type': 'application/json',
38 | },
39 | body: JSON.stringify({ event_id: eventId }),
40 | })
41 | .then(response => response.json())
42 | .then(event => {
43 | dispatch(addEventFollower(event));
44 | })
45 | .catch(error => (error));
46 |
47 | export const deleteEventFollower = eventId => (dispatch) => fetch('/api/v1/event_followers', {
48 | method: 'DELETE',
49 | headers: {
50 | Authorization: `Bearer ${localStorage.token}`,
51 | Accept: 'application/json',
52 | 'Content-Type': 'application/json',
53 | },
54 | body: JSON.stringify({ event_id: eventId }),
55 | })
56 | .then(response => response.json())
57 | .then(event => {
58 | dispatch(destroyEventFollower(event));
59 | })
60 | .catch(error => (error));
61 |
--------------------------------------------------------------------------------
/client/src/redux/reducers/authReducer.js:
--------------------------------------------------------------------------------
1 | import * as types from '../actions/actionTypes';
2 |
3 | const initialState = {
4 | isAuthenticated: false,
5 | isAuthenticating: false,
6 | currentUser: {},
7 | token: null,
8 | errors: [],
9 | };
10 |
11 | export default (state = initialState, action) => {
12 | switch (action.type) {
13 | case types.AUTHENTICATION_REQUEST:
14 | return {
15 | ...state,
16 | isAuthenticating: true,
17 | };
18 |
19 | case types.AUTHENTICATION_SUCCESS:
20 | return {
21 | ...state,
22 | isAuthenticated: true,
23 | isAuthenticating: false,
24 | currentUser: action.user,
25 | token: action.token,
26 | };
27 |
28 | case types.AUTHENTICATION_FAILURE:
29 | return {
30 | isAuthenticated: false,
31 | isAuthenticating: false,
32 | currentUser: {},
33 | token: null,
34 | errors: action.errors || [],
35 | };
36 |
37 | case types.LOGOUT:
38 | return {
39 | ...state,
40 | isAuthenticated: false,
41 | isAuthenticating: false,
42 | currentUser: {},
43 | token: null,
44 | };
45 |
46 | default:
47 | return state;
48 | }
49 | };
50 |
--------------------------------------------------------------------------------
/client/src/redux/reducers/eventsReducer.js:
--------------------------------------------------------------------------------
1 | import * as types from '../actions/actionTypes';
2 |
3 | export default (state = [], action) => {
4 | switch (action.type) {
5 | case types.LOAD_EVENTS:
6 | return action.events;
7 | default:
8 | return state;
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/client/src/redux/reducers/followReducer.js:
--------------------------------------------------------------------------------
1 | import * as types from '../actions/actionTypes';
2 |
3 | const initialState = [];
4 |
5 | export default (state = initialState, action) => {
6 | switch (action.type) {
7 | case types.LOAD_EVENTS_FOLLOWED:
8 | return action.events;
9 | case types.ADD_EVENT_FOLLOWER:
10 | return [...state, action.event];
11 | case types.DELETE_EVENT_FOLLOWER:
12 | return state.filter(data => data.event_id !== action.event.event_id);
13 | case 'RESET':
14 | return initialState;
15 | default:
16 | return state;
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/client/src/redux/reducers/rootReducer.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import eventsReducer from './eventsReducer';
3 | import authReducer from './authReducer';
4 | import followReducer from './followReducer';
5 |
6 | const rootReducer = combineReducers({
7 | events: eventsReducer,
8 | auth: authReducer,
9 | followed_events: followReducer,
10 | });
11 |
12 | export default rootReducer;
13 |
--------------------------------------------------------------------------------
/client/src/redux/store.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose } from 'redux';
2 | import thunk from 'redux-thunk';
3 | import { persistStore, persistReducer } from 'redux-persist';
4 | import storage from 'redux-persist/lib/storage';
5 | import rootReducer from './reducers/rootReducer';
6 |
7 | const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
8 |
9 | const persistConfig = {
10 | key: 'root',
11 | storage,
12 | };
13 |
14 | const persistedReducer = persistReducer(persistConfig, rootReducer);
15 |
16 | const store = createStore(
17 | persistedReducer, composeEnhancers(
18 | applyMiddleware(thunk),
19 | ),
20 | );
21 |
22 | const persistor = persistStore(store);
23 |
24 | export {
25 | store,
26 | persistor,
27 | };
28 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative 'config/environment'
4 |
5 | run Rails.application
6 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative 'boot'
2 |
3 | require 'rails'
4 | # Pick the frameworks you want:
5 | require 'active_model/railtie'
6 | require 'active_job/railtie'
7 | require 'active_record/railtie'
8 | require 'active_storage/engine'
9 | require 'action_controller/railtie'
10 | require 'action_mailer/railtie'
11 | require 'action_mailbox/engine'
12 | require 'action_text/engine'
13 | require 'action_view/railtie'
14 | require 'action_cable/engine'
15 | # require 'sprockets/railtie'
16 | # require 'rails/test_unit/railtie'
17 |
18 | # Require the gems listed in Gemfile, including any gems
19 | # you've limited to :test, :development, or :production.
20 | Bundler.require(*Rails.groups)
21 |
22 | module ReactRailsEventScheduler
23 | class Application < Rails::Application
24 | # Initialize configuration defaults for originally generated Rails version.
25 | config.load_defaults 6.0 and config.autoloader = :classic # Settings in config/environments/* take precedence over those specified here.
26 | # Application configuration can go into files in config/initializers
27 | # -- all .rb files in that directory are automatically loaded after loading
28 | # the framework and any gems in your application.
29 |
30 | # Only loads a smaller set of middleware suitable for API only apps.
31 | # Middleware like session, flash, cookies can be added back manually.
32 | # Skip views, helpers and assets when generating a new resource.
33 | config.api_only = true
34 |
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/config/application.yml:
--------------------------------------------------------------------------------
1 | # Add configuration values here, as shown below.
2 | #
3 | # pusher_app_id: "2954"
4 | # pusher_key: 7381a978f7dd7f9a1117
5 | # pusher_secret: abdc3b896a0ffb85d373
6 | # stripe_api_key: sk_test_2J0l093xOyW72XUYJHE4Dv2r
7 | # stripe_publishable_key: pk_test_ro9jV5SNwGb1yYlQfzG17LHK
8 | #
9 | # production:
10 | # stripe_api_key: sk_live_EeHnL644i6zo4Iyq4v1KdV9H
11 | # stripe_publishable_key: pk_live_9lcthxpSIHbGwmdO941O1XVU
12 |
13 | AUTH_SECRET: ee8c2c8ff7f440345c8c1a1c5e312bc55eb385925e843ff72d478f0e381629970ef70ad7aa1d76d8b4451d3a0f1f008f5008dbf0797649a2287f3c167f919e4b
14 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2 |
3 | require 'bundler/setup' # Set up gems listed in the Gemfile.
4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
5 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: async
3 |
4 | test:
5 | adapter: test
6 |
7 | production:
8 | adapter: redis
9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
10 | channel_prefix: react_rails_event_scheduler_production
11 |
--------------------------------------------------------------------------------
/config/credentials.yml.enc:
--------------------------------------------------------------------------------
1 | XZDKdO9BH4/tEOr77bBKYDWi+elFrBaDYcyQeoRGGA1p70YPUyyMTmtATY7T1iluwYx23Y6oUuZ1fpQfeCbe1/F/i8TvZTjtOtH8O6bc9a6t/rHNwXK2CRwmqQANivY+5mhRO+EbLXUlUQQZ6gHnf0atU5SVMmP9z8LIbSQD4azg8idhbkKJNRPGETzIY6eNPAq05z4Jmhg3RRnV45sxUWhQG7sDzwYpkLsQqj+0GYRb4gNyiGHf0SQexkdK1BUupaEMSvDxERb/EY+LgniT5LWze5oeSLlPaML3kW9s7w6NgHssp2nFWRFS0s1gGwQB315JeQKNF8+AqqglTvMUy3DNWuuu+tmy1/vn0txVDNFhr5Qz5zUl1nnCBwgGxnoCDurIF0u94GDkFX0mGehMgsl8QvoarqKPfYZ+--omlnrUUH/RVDl26k--ko7+gAWOmwbi/SmMx8Jphw==
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | # PostgreSQL. Versions 9.3 and up are supported.
2 | #
3 | # Install the pg driver:
4 | # gem install pg
5 | # On macOS with Homebrew:
6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config
7 | # On macOS with MacPorts:
8 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
9 | # On Windows:
10 | # gem install pg
11 | # Choose the win32 build.
12 | # Install PostgreSQL and put its /bin directory on your path.
13 | #
14 | # Configure Using Gemfile
15 | # gem 'pg'
16 | #
17 | default: &default
18 | adapter: postgresql
19 | encoding: unicode
20 | # For details on connection pooling, see Rails configuration guide
21 | # https://guides.rubyonrails.org/configuring.html#database-pooling
22 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
23 |
24 | development:
25 | <<: *default
26 | database: react_rails_event_scheduler_development
27 |
28 | # The specified database role being used to connect to postgres.
29 | # To create additional roles in postgres see `$ createuser --help`.
30 | # When left blank, postgres will use the default role. This is
31 | # the same name as the operating system user that initialized the database.
32 | #username: react_rails_event_scheduler
33 |
34 | # The password associated with the postgres role (username).
35 | #password:
36 |
37 | # Connect on a TCP socket. Omitted by default since the client uses a
38 | # domain socket that doesn't need configuration. Windows does not have
39 | # domain sockets, so uncomment these lines.
40 | #host: localhost
41 |
42 | # The TCP port the server listens on. Defaults to 5432.
43 | # If your server runs on a different port number, change accordingly.
44 | #port: 5432
45 |
46 | # Schema search path. The server defaults to $user,public
47 | #schema_search_path: myapp,sharedapp,public
48 |
49 | # Minimum log levels, in increasing order:
50 | # debug5, debug4, debug3, debug2, debug1,
51 | # log, notice, warning, error, fatal, and panic
52 | # Defaults to warning.
53 | #min_messages: notice
54 |
55 | # Warning: The database defined as "test" will be erased and
56 | # re-generated from your development database when you run "rake".
57 | # Do not set this db to the same as development or production.
58 | test:
59 | <<: *default
60 | database: react_rails_event_scheduler_test
61 |
62 | # As with config/credentials.yml, you never want to store sensitive information,
63 | # like your database password, in your source code. If your source code is
64 | # ever seen by anyone, they now have access to your database.
65 | #
66 | # Instead, provide the password as a unix environment variable when you boot
67 | # the app. Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
68 | # for a full rundown on how to provide these environment variables in a
69 | # production deployment.
70 | #
71 | # On Heroku and other platform providers, you may have a full connection URL
72 | # available as an environment variable. For example:
73 | #
74 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
75 | #
76 | # You can use this database configuration with:
77 | #
78 | # production:
79 | # url: <%= ENV['DATABASE_URL'] %>
80 | #
81 | production:
82 | <<: *default
83 | database: react_rails_event_scheduler_production
84 | username: react_rails_event_scheduler
85 | password: <%= ENV['REACT_RAILS_EVENT_SCHEDULER_DATABASE_PASSWORD'] %>
86 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative 'application'
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports.
13 | config.consider_all_requests_local = true
14 |
15 | # Enable/disable caching. By default caching is disabled.
16 | # Run rails dev:cache to toggle caching.
17 | if Rails.root.join('tmp', 'caching-dev.txt').exist?
18 | config.cache_store = :memory_store
19 | config.public_file_server.headers = {
20 | 'Cache-Control' => "public, max-age=#{2.days.to_i}"
21 | }
22 | else
23 | config.action_controller.perform_caching = false
24 |
25 | config.cache_store = :null_store
26 | end
27 |
28 | # Store uploaded files on the local file system (see config/storage.yml for options).
29 | config.active_storage.service = :local
30 |
31 | # Don't care if the mailer can't send.
32 | config.action_mailer.raise_delivery_errors = false
33 |
34 | config.action_mailer.perform_caching = false
35 |
36 | # Print deprecation notices to the Rails logger.
37 | config.active_support.deprecation = :log
38 |
39 | # Raise an error on page load if there are pending migrations.
40 | config.active_record.migration_error = :page_load
41 |
42 | # Highlight code that triggered database queries in logs.
43 | config.active_record.verbose_query_logs = true
44 |
45 | # Raises error for missing translations.
46 | # config.action_view.raise_on_missing_translations = true
47 |
48 | # Use an evented file watcher to asynchronously detect changes in source code,
49 | # routes, locales, etc. This feature depends on the listen gem.
50 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker
51 | end
52 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # Code is not reloaded between requests.
5 | config.cache_classes = true
6 |
7 | # Eager load code on boot. This eager loads most of Rails and
8 | # your application in memory, allowing both threaded web servers
9 | # and those relying on copy on write to perform better.
10 | # Rake tasks automatically ignore this option for performance.
11 | config.eager_load = true
12 |
13 | # Full error reports are disabled and caching is turned on.
14 | config.consider_all_requests_local = false
15 |
16 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
17 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
18 | # config.require_master_key = true
19 |
20 | # Disable serving static files from the `/public` folder by default since
21 | # Apache or NGINX already handles this.
22 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
23 |
24 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
25 | # config.action_controller.asset_host = 'http://assets.example.com'
26 |
27 | # Specifies the header that your server uses for sending files.
28 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
29 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
30 |
31 | # Store uploaded files on the local file system (see config/storage.yml for options).
32 | config.active_storage.service = :local
33 |
34 | # Mount Action Cable outside main process or domain.
35 | # config.action_cable.mount_path = nil
36 | # config.action_cable.url = 'wss://example.com/cable'
37 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
38 |
39 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
40 | config.force_ssl = true
41 |
42 | # Use the lowest log level to ensure availability of diagnostic information
43 | # when problems arise.
44 | config.log_level = :debug
45 |
46 | # Prepend all log lines with the following tags.
47 | config.log_tags = [:request_id]
48 |
49 | # Use a different cache store in production.
50 | # config.cache_store = :mem_cache_store
51 |
52 | # Use a real queuing backend for Active Job (and separate queues per environment).
53 | # config.active_job.queue_adapter = :resque
54 | # config.active_job.queue_name_prefix = "react_rails_event_scheduler_production"
55 |
56 | config.action_mailer.perform_caching = false
57 |
58 | # Ignore bad email addresses and do not raise email delivery errors.
59 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
60 | # config.action_mailer.raise_delivery_errors = false
61 |
62 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
63 | # the I18n.default_locale when a translation cannot be found).
64 | config.i18n.fallbacks = true
65 |
66 | # Send deprecation notices to registered listeners.
67 | config.active_support.deprecation = :notify
68 |
69 | # Use default logging formatter so that PID and timestamp are not suppressed.
70 | config.log_formatter = ::Logger::Formatter.new
71 |
72 | # Use a different logger for distributed setups.
73 | # require 'syslog/logger'
74 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
75 |
76 | if ENV['RAILS_LOG_TO_STDOUT'].present?
77 | logger = ActiveSupport::Logger.new(STDOUT)
78 | logger.formatter = config.log_formatter
79 | config.logger = ActiveSupport::TaggedLogging.new(logger)
80 | end
81 |
82 | # Do not dump schema after migrations.
83 | config.active_record.dump_schema_after_migration = false
84 |
85 | # Inserts middleware to perform automatic connection switching.
86 | # The `database_selector` hash is used to pass options to the DatabaseSelector
87 | # middleware. The `delay` is used to determine how long to wait after a write
88 | # to send a subsequent read to the primary.
89 | #
90 | # The `database_resolver` class is used by the middleware to determine which
91 | # database is appropriate to use based on the time delay.
92 | #
93 | # The `database_resolver_context` class is used by the middleware to set
94 | # timestamps for the last write to the primary. The resolver uses the context
95 | # class timestamps to determine how long to wait before reading from the
96 | # replica.
97 | #
98 | # By default Rails will store a last write timestamp in the session. The
99 | # DatabaseSelector middleware is designed as such you can define your own
100 | # strategy for connection switching and pass that into the middleware through
101 | # these configuration options.
102 | # config.active_record.database_selector = { delay: 2.seconds }
103 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
104 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
105 | end
106 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | # The test environment is used exclusively to run your application's
2 | # test suite. You never need to work with it otherwise. Remember that
3 | # your test database is "scratch space" for the test suite and is wiped
4 | # and recreated between test runs. Don't rely on the data there!
5 |
6 | Rails.application.configure do
7 | # Settings specified here will take precedence over those in config/application.rb.
8 |
9 | config.cache_classes = false
10 |
11 | # Do not eager load code on boot. This avoids loading your whole application
12 | # just for the purpose of running a single test. If you are using a tool that
13 | # preloads Rails for running tests, you may have to set it to true.
14 | config.eager_load = false
15 |
16 | # Configure public file server for tests with Cache-Control for performance.
17 | config.public_file_server.enabled = true
18 | config.public_file_server.headers = {
19 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
20 | }
21 |
22 | # Show full error reports and disable caching.
23 | config.consider_all_requests_local = true
24 | config.action_controller.perform_caching = false
25 | config.cache_store = :null_store
26 |
27 | # Raise exceptions instead of rendering exception templates.
28 | config.action_dispatch.show_exceptions = false
29 |
30 | # Disable request forgery protection in test environment.
31 | config.action_controller.allow_forgery_protection = false
32 |
33 | # Store uploaded files on the local file system in a temporary directory.
34 | config.active_storage.service = :test
35 |
36 | config.action_mailer.perform_caching = false
37 |
38 | # Tell Action Mailer not to deliver emails to the real world.
39 | # The :test delivery method accumulates sent emails in the
40 | # ActionMailer::Base.deliveries array.
41 | config.action_mailer.delivery_method = :test
42 |
43 | # Print deprecation notices to the stderr.
44 | config.active_support.deprecation = :stderr
45 |
46 | # Raises error for missing translations.
47 | # config.action_view.raise_on_missing_translations = true
48 | end
49 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ActiveSupport::Reloader.to_prepare do
4 | # ApplicationController.renderer.defaults.merge!(
5 | # http_host: 'example.org',
6 | # https: false
7 | # )
8 | # end
9 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/config/initializers/cors.rb:
--------------------------------------------------------------------------------
1 | Rails.application.config.middleware.insert_before 0, Rack::Cors do
2 | allow do
3 | origins 'localhost:3001', 'https://rocky-reef-66767.herokuapp.com'
4 |
5 | resource '*',
6 | headers: :any,
7 | methods: [:get, :post, :put, :patch, :delete, :options, :head]
8 | end
9 | end
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [:password]
5 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/knock.rb:
--------------------------------------------------------------------------------
1 | Knock.setup do |config|
2 |
3 | ## Expiration claim
4 | ## ----------------
5 | ##
6 | ## How long before a token is expired. If nil is provided, token will
7 | ## last forever.
8 | ##
9 | ## Default:
10 | config.token_lifetime = 1.day
11 |
12 |
13 | ## Audience claim
14 | ## --------------
15 | ##
16 | ## Configure the audience claim to identify the recipients that the token
17 | ## is intended for.
18 | ##
19 | ## Default:
20 | # config.token_audience = nil
21 |
22 | ## If using Auth0, uncomment the line below
23 | # config.token_audience = -> { Rails.application.secrets.auth0_client_id }
24 |
25 | ## Signature algorithm
26 | ## -------------------
27 | ##
28 | ## Configure the algorithm used to encode the token
29 | ##
30 | ## Default:
31 | config.token_signature_algorithm = 'HS256'
32 |
33 | ## Signature key
34 | ## -------------
35 | ##
36 | ## Configure the key used to sign tokens.
37 | ##
38 | ## Default:
39 | config.token_secret_signature_key = -> { Rails.application.credentials.read }
40 |
41 | ## If using Auth0, uncomment the line below
42 | # config.token_secret_signature_key = -> { JWT.base64url_decode Rails.application.secrets.auth0_client_secret }
43 |
44 | ## Public key
45 | ## ----------
46 | ##
47 | ## Configure the public key used to decode tokens, if required.
48 | ##
49 | ## Default:
50 | # config.token_public_key = nil
51 |
52 | ## Exception Class
53 | ## ---------------
54 | ##
55 | ## Configure the exception to be used when user cannot be found.
56 | ##
57 | ## Default:
58 | # config.not_found_exception_class_name = 'ActiveRecord::RecordNotFound'
59 | end
60 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/config/initializers/time_as_json.rb:
--------------------------------------------------------------------------------
1 | module ActiveSupport
2 | class TimeWithZone
3 | def as_json(options = nil)
4 | if ActiveSupport::JSON::Encoding.use_standard_json_time_format
5 | xmlschema
6 | else
7 | %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
8 | end
9 | end
10 | end
11 | end
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/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 https://guides.rubyonrails.org/i18n.html.
31 |
32 | en:
33 | hello: "Hello world"
34 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers: a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum; this matches the default thread size of Active Record.
6 | #
7 | max_threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }
8 | min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
9 | threads min_threads_count, max_threads_count
10 |
11 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
12 | #
13 | port ENV.fetch('PORT') { 3001 }
14 |
15 | # Specifies the `environment` that Puma will run in.
16 | #
17 | environment ENV.fetch('RAILS_ENV') { 'development' }
18 |
19 | # Specifies the `pidfile` that Puma will use.
20 | pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' }
21 |
22 | # Specifies the number of `workers` to boot in clustered mode.
23 | # Workers are forked web server processes. If using threads and workers together
24 | # the concurrency of the application would be max `threads` * `workers`.
25 | # Workers do not work on JRuby or Windows (both of which do not support
26 | # processes).
27 | #
28 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
29 |
30 | # Use the `preload_app!` method when specifying a `workers` number.
31 | # This directive tells Puma to first boot the application and load code
32 | # before forking the application. This takes advantage of Copy On Write
33 | # process behavior so workers use less memory.
34 | #
35 | # preload_app!
36 |
37 | # Allow puma to be restarted by `rails restart` command.
38 | plugin :tmp_restart
39 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 | namespace :api, defaults: { format: :json } do
3 | namespace :v1 do
4 | resources :events
5 | resources :event_followers
6 | delete '/event_followers', to: 'event_followers#destroy'
7 | end
8 | end
9 |
10 | delete '/logout', to: 'sessions#destroy'
11 |
12 | post '/login', to: 'user_token#create'
13 | post '/sign_up', to: 'users#create'
14 | post '/find_user' => 'users#find'
15 | post '/find_user_events', to: 'users#find_events'
16 |
17 |
18 | get '*path', to: "application#fallback_index_html", constraints: ->(request) do
19 | !request.xhr? && request.format.html?
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | Spring.watch(
2 | '.ruby-version',
3 | '.rbenv-vars',
4 | 'tmp/restart.txt',
5 | 'tmp/caching-dev.txt'
6 | )
7 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/db/migrate/20200120200544_create_users.rb:
--------------------------------------------------------------------------------
1 | class CreateUsers < ActiveRecord::Migration[6.0]
2 | def change
3 | create_table :users do |t|
4 | t.string :username
5 | t.timestamps
6 | end
7 | add_index :users, :username, unique: true
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20200120200904_create_events.rb:
--------------------------------------------------------------------------------
1 | class CreateEvents < ActiveRecord::Migration[6.0]
2 | def change
3 | create_table :events do |t|
4 | t.string :title
5 | t.string :topic
6 | t.datetime :date_start
7 | t.datetime :date_end
8 | t.text :description
9 | t.string :location
10 | t.string :city
11 | t.string :country
12 | t.string :status
13 | t.timestamps
14 | end
15 | add_index :events, [:title, :description, :city, :date_start, :date_end], unique: true, :name => 'event_index'
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/db/migrate/20200120203113_create_event_followers.rb:
--------------------------------------------------------------------------------
1 | class CreateEventFollowers < ActiveRecord::Migration[6.0]
2 | def change
3 | create_table :event_followers do |t|
4 | t.integer :user_id
5 | t.integer :event_id
6 | t.timestamps
7 | end
8 | add_index :event_followers, [:user_id, :event_id], unique: true
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20200126201844_add_password_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddPasswordToUser < ActiveRecord::Migration[6.0]
2 | def change
3 | add_column :users, :password_digest, :string
4 | add_column :users, :email, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # This file is auto-generated from the current state of the database. Instead
2 | # of editing this file, please use the migrations feature of Active Record to
3 | # incrementally modify your database, and then regenerate this schema definition.
4 | #
5 | # This file is the source Rails uses to define your schema when running `rails
6 | # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
7 | # be faster and is potentially less error prone than running all of your
8 | # migrations from scratch. Old migrations may fail to apply correctly if those
9 | # migrations use external dependencies or application code.
10 | #
11 | # It's strongly recommended that you check this file into your version control system.
12 |
13 | ActiveRecord::Schema.define(version: 2020_01_26_201844) do
14 |
15 | # These are extensions that must be enabled in order to support this database
16 | enable_extension "plpgsql"
17 |
18 | create_table "event_followers", force: :cascade do |t|
19 | t.integer "user_id"
20 | t.integer "event_id"
21 | t.datetime "created_at", precision: 6, null: false
22 | t.datetime "updated_at", precision: 6, null: false
23 | t.index ["user_id", "event_id"], name: "index_event_followers_on_user_id_and_event_id", unique: true
24 | end
25 |
26 | create_table "events", force: :cascade do |t|
27 | t.string "title"
28 | t.string "topic"
29 | t.datetime "date_start"
30 | t.datetime "date_end"
31 | t.text "description"
32 | t.string "location"
33 | t.string "city"
34 | t.string "country"
35 | t.string "status"
36 | t.datetime "created_at", precision: 6, null: false
37 | t.datetime "updated_at", precision: 6, null: false
38 | t.index ["title", "description", "city", "date_start", "date_end"], name: "event_index", unique: true
39 | end
40 |
41 | create_table "users", force: :cascade do |t|
42 | t.string "username"
43 | t.datetime "created_at", precision: 6, null: false
44 | t.datetime "updated_at", precision: 6, null: false
45 | t.string "password_digest"
46 | t.string "email"
47 | t.index ["username"], name: "index_users_on_username", unique: true
48 | end
49 |
50 | end
51 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7 | # Character.create(name: 'Luke', movie: movies.first)
8 |
9 | user = User.create!(username: 'admin', email: 'admin@example.com', password: 'password')
10 |
11 | event1 = Event.create!(title: 'Strata Data & AI Conferences',
12 | date_start: 'Mar 15 2020 07:00',
13 | date_end: 'Mar 18 2020 22:00',
14 | description: 'A 4-day immersion in the most challenging problems, intriguing use cases, and enticing opportunities in data today.',
15 | location: 'TBD',
16 | city: 'San Francisco, CA',
17 | country: 'USA',
18 | topic: 'Tech',
19 | status: 'Pending')
20 |
21 | event2 = Event.create!(title: 'Deep Learning Summit',
22 | date_start: 'Jan 30 2020 07:00',
23 | date_end: 'Jan 31 2020 22:00',
24 | description: 'Their aim is to bridge the gap between the latest technological research advancements and real-world applications in business and society.',
25 | location: 'Hotel Niko, 222 Mason St',
26 | city: 'San Francisco, CA',
27 | country: 'USA',
28 | topic: 'Tech',
29 | status: 'Pending')
30 |
31 | event3 = Event.create!(title: 'Reinforce AI Conference',
32 | date_start: 'Apr 06 2020 07:00',
33 | date_end: 'Apr 07 2020 22:00',
34 | description: 'See how AI is shaping the world and how your company can use it to fix real-world problems.',
35 | location: 'TBD',
36 | city: 'Budapest',
37 | country: 'Hungary',
38 | topic: 'Tech',
39 | status: 'Pending')
40 |
41 | event4 = Event.create!(title: 'Applied Machine Learning Conference',
42 | date_start: 'Apr 15 2020 07:00',
43 | date_end: 'Apr 16 2020 22:00',
44 | description: 'A unique machine learning conference in its fourth year.',
45 | location: 'TBD',
46 | city: 'Charlottesville, VA',
47 | country: 'USA',
48 | topic: 'Tech',
49 | status: 'Pending')
50 |
51 | EventFollower.create!(user_id: user.id, event_id: event1.id)
52 |
--------------------------------------------------------------------------------
/lib/Events_Scheduler_Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndresFMoya/react-rails_event_scheduler/a4be1b2b04d3295179acae0426fc65e80fee23ba/lib/Events_Scheduler_Screenshot.png
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndresFMoya/react-rails_event_scheduler/a4be1b2b04d3295179acae0426fc65e80fee23ba/lib/tasks/.keep
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndresFMoya/react-rails_event_scheduler/a4be1b2b04d3295179acae0426fc65e80fee23ba/log/.keep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-rails_event_scheduler",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "repository": "git@github.com:AndresFMoya/react-rails_event_scheduler.git",
6 | "author": "AndresFMoya ",
7 | "license": "MIT",
8 | "engines": {
9 | "node": "10.16.3",
10 | "yarn": "1.19.1"
11 | },
12 | "scripts": {
13 | "build": "yarn --cwd client install && yarn --cwd client build",
14 | "deploy": "cp -a client/build/. public/",
15 | "heroku-postbuild": "yarn build && yarn deploy"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 |
--------------------------------------------------------------------------------
/spec/controllers/api/v1/event_followers_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Api::V1::EventFollowersController, type: :controller do
4 | end
5 |
--------------------------------------------------------------------------------
/spec/controllers/api/v1/events_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Api::V1::EventsController, type: :controller do
4 | describe 'GET #index' do
5 | it 'returns http success' do
6 | get :index
7 | expect(response).to have_http_status(:success)
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/controllers/users_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe UsersController, type: :controller do
4 | end
5 |
--------------------------------------------------------------------------------
/spec/factories/event_followers.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :event_follower do
3 | user
4 | event
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/events.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :event do
3 | title { 'SuperBowl LIV' }
4 | topic { 'Sport' }
5 | date_start { 'Feb 2 2020 18:30' }
6 | date_end { 'Feb 2 2020 22:00' }
7 | description do
8 | 'The Super Bowl is the annual championship game of the National Football League (NFL).
9 | The game is the culmination of a regular season that begins in the late summer of the previous year.'
10 | end
11 | location { 'Hard Rock Stadium' }
12 | city { 'Miami, FL' }
13 | country { 'USA' }
14 | status { 'Pending' }
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/spec/factories/users.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :user do
3 | username { 'admin' }
4 | email { 'admin@example.com' }
5 | password { 'password' }
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/models/event_follower_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe EventFollower, type: :model do
4 | let(:event_follower) { FactoryBot.create(:event_follower) }
5 |
6 | it 'must have a user and an event present' do
7 | expect(event_follower).to be_valid
8 | end
9 |
10 | it 'must have a user present' do
11 | event_follower = FactoryBot.build(:event_follower, user_id: nil)
12 | expect(event_follower).to_not be_valid
13 | end
14 |
15 | it 'must have a event present' do
16 | event_follower = FactoryBot.build(:event_follower, event_id: nil)
17 | expect(event_follower).to_not be_valid
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/models/event_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Event, type: :model do
4 | let(:event) { FactoryBot.create(:event) }
5 |
6 | it 'must have title, description, start date, end date, and status present' do
7 | expect(event).to be_valid
8 | end
9 |
10 | it 'must have a title present' do
11 | event = FactoryBot.build(:event, title: nil)
12 | expect(event).to_not be_valid
13 | end
14 |
15 | it 'must have a description present' do
16 | event = FactoryBot.build(:event, description: nil)
17 | expect(event).to_not be_valid
18 | end
19 |
20 | it 'must have a city present' do
21 | event = FactoryBot.build(:event, city: nil)
22 | expect(event).to_not be_valid
23 | end
24 |
25 | it 'must have a start date' do
26 | event = FactoryBot.build(:event, date_start: nil)
27 | expect(event).to_not be_valid
28 | end
29 |
30 | it 'must have a end date' do
31 | event = FactoryBot.build(:event, date_end: nil)
32 | expect(event).to_not be_valid
33 | end
34 |
35 | it 'must have a status' do
36 | event = FactoryBot.build(:event, status: nil)
37 | expect(event).to_not be_valid
38 | end
39 |
40 | it 'could have many followers' do
41 | event = Event.reflect_on_association(:event_followers)
42 | expect(event.macro).to eq(:has_many)
43 | end
44 |
45 | it 'must be unique' do
46 | FactoryBot.create(:event)
47 | event = FactoryBot.build(:event)
48 | expect(event).to_not be_valid
49 | expect(event.errors[:title]).to include('has already been taken')
50 | end
51 |
52 | it 'destroys dependent events of event followers table' do
53 | event = FactoryBot.create(:event, title: 'Concert')
54 | FactoryBot.create(:event_follower, event: event)
55 | expect { event.destroy }.to change { EventFollower.count }.by(-1)
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/spec/models/user_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe User, type: :model do
4 | let(:user) { FactoryBot.create(:user) }
5 |
6 | it 'must have a username present' do
7 | expect(user).to be_valid
8 | end
9 |
10 | it 'must not have a too short username' do
11 | user = FactoryBot.build(:user, username: 'adm')
12 | expect(user).to_not be_valid
13 | end
14 |
15 | it 'must be unique' do
16 | FactoryBot.create(:user)
17 | user = FactoryBot.build(:user)
18 | expect(user).to_not be_valid
19 | expect(user.errors[:username]).to include('has already been taken')
20 | end
21 |
22 | it 'must not have a too long username' do
23 | user = FactoryBot.build(:user, username: 'admin' * 20)
24 | expect(user).to_not be_valid
25 | end
26 |
27 | it 'must have a name present' do
28 | user = FactoryBot.build(:user, username: nil)
29 | expect(user).to_not be_valid
30 | end
31 |
32 | it 'could follow many events' do
33 | follower = User.reflect_on_association(:event_followers)
34 | expect(follower.macro).to eq(:has_many)
35 | end
36 |
37 | it 'destroys dependent followers of events' do
38 | user1 = FactoryBot.create(:user, username: 'user')
39 | FactoryBot.create(:event_follower, user: user1)
40 | expect { user1.destroy }.to change { EventFollower.count }.by(-1)
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/spec/rails_helper.rb:
--------------------------------------------------------------------------------
1 | # This file is copied to spec/ when you run 'rails generate rspec:install'
2 | require 'spec_helper'
3 | ENV['RAILS_ENV'] ||= 'test'
4 |
5 | require File.expand_path('../config/environment', __dir__)
6 |
7 | # Prevent database truncation if the environment is production
8 | abort('The Rails environment is running in production mode!') if Rails.env.production?
9 | require 'rspec/rails'
10 | # Add additional requires below this line. Rails is not loaded until this point!
11 |
12 | # Requires supporting ruby files with custom matchers and macros, etc, in
13 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
14 | # run as spec files by default. This means that files in spec/support that end
15 | # in _spec.rb will both be required and run as specs, causing the specs to be
16 | # run twice. It is recommended that you do not name files matching this glob to
17 | # end with _spec.rb. You can configure this pattern with the --pattern
18 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
19 | #
20 | # The following line is provided for convenience purposes. It has the downside
21 | # of increasing the boot-up time by auto-requiring all files in the support
22 | # directory. Alternatively, in the individual `*_spec.rb` files, manually
23 | # require only the support files necessary.
24 | #
25 | # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
26 |
27 | # Checks for pending migrations and applies them before tests are run.
28 | # If you are not using ActiveRecord, you can remove these lines.
29 | begin
30 | ActiveRecord::Migration.maintain_test_schema!
31 | rescue ActiveRecord::PendingMigrationError => e
32 | puts e.to_s.strip
33 | exit 1
34 | end
35 | RSpec.configure do |config|
36 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
37 | config.fixture_path = "#{::Rails.root}/spec/fixtures"
38 |
39 | # If you're not using ActiveRecord, or you'd prefer not to run each of your
40 | # examples within a transaction, remove the following line or assign false
41 | # instead of true.
42 | config.use_transactional_fixtures = true
43 |
44 | # RSpec Rails can automatically mix in different behaviours to your tests
45 | # based on their file location, for example enabling you to call `get` and
46 | # `post` in specs under `spec/controllers`.
47 | #
48 | # You can disable this behaviour by removing the line below, and instead
49 | # explicitly tag your specs with their type, e.g.:
50 | #
51 | # RSpec.describe UsersController, :type => :controller do
52 | # # ...
53 | # end
54 | #
55 | # The different available types are documented in the features, such as in
56 | # https://relishapp.com/rspec/rspec-rails/docs
57 | config.infer_spec_type_from_file_location!
58 |
59 | # Filter lines from Rails gems in backtraces.
60 | config.filter_rails_from_backtrace!
61 | # arbitrary gems may also be filtered via:
62 | # config.filter_gems_from_backtrace("gem name")
63 | end
64 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # This file was generated by the `rails generate rspec:install` command. Conventionally, all
2 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3 | # The generated `.rspec` file contains `--require spec_helper` which will cause
4 | # this file to always be loaded, without a need to explicitly require it in any
5 | # files.
6 | #
7 | # Given that it is always loaded, you are encouraged to keep this file as
8 | # light-weight as possible. Requiring heavyweight dependencies from this file
9 | # will add to the boot time of your test suite on EVERY test run, even for an
10 | # individual file that may not need all of that loaded. Instead, consider making
11 | # a separate helper file that requires the additional dependencies and performs
12 | # the additional setup, and require it from the spec files that actually need
13 | # it.
14 | #
15 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16 | RSpec.configure do |config|
17 | # rspec-expectations config goes here. You can use an alternate
18 | # assertion/expectation library such as wrong or the stdlib/minitest
19 | # assertions if you prefer.
20 | config.expect_with :rspec do |expectations|
21 | # This option will default to `true` in RSpec 4. It makes the `description`
22 | # and `failure_message` of custom matchers include text for helper methods
23 | # defined using `chain`, e.g.:
24 | # be_bigger_than(2).and_smaller_than(4).description
25 | # # => "be bigger than 2 and smaller than 4"
26 | # ...rather than:
27 | # # => "be bigger than 2"
28 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true
29 | end
30 |
31 | # rspec-mocks config goes here. You can use an alternate test double
32 | # library (such as bogus or mocha) by changing the `mock_with` option here.
33 | config.mock_with :rspec do |mocks|
34 | # Prevents you from mocking or stubbing a method that does not exist on
35 | # a real object. This is generally recommended, and will default to
36 | # `true` in RSpec 4.
37 | mocks.verify_partial_doubles = true
38 | end
39 |
40 | # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
41 | # have no way to turn it off -- the option exists only for backwards
42 | # compatibility in RSpec 3). It causes shared context metadata to be
43 | # inherited by the metadata hash of host groups and examples, rather than
44 | # triggering implicit auto-inclusion in groups with matching metadata.
45 | config.shared_context_metadata_behavior = :apply_to_host_groups
46 |
47 | # The settings below are suggested to provide a good initial experience
48 | # with RSpec, but feel free to customize to your heart's content.
49 | # This allows you to limit a spec run to individual examples or groups
50 | # you care about by tagging them with `:focus` metadata. When nothing
51 | # is tagged with `:focus`, all examples get run. RSpec also provides
52 | # aliases for `it`, `describe`, and `context` that include `:focus`
53 | # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
54 | # config.filter_run_when_matching :focus
55 |
56 | # Allows RSpec to persist some state between runs in order to support
57 | # the `--only-failures` and `--next-failure` CLI options. We recommend
58 | # you configure your source control system to ignore this file.
59 | # config.example_status_persistence_file_path = "spec/examples.txt"
60 |
61 | # Limits the available syntax to the non-monkey patched syntax that is
62 | # recommended. For more details, see:
63 | # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
64 | # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
65 | # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
66 | # config.disable_monkey_patching!
67 |
68 | # Many RSpec users commonly either run the entire suite or an individual
69 | # file, and it's useful to allow more verbose output when running an
70 | # individual spec file.
71 | # if config.files_to_run.one?
72 | # Use the documentation formatter for detailed output,
73 | # unless a formatter has already been configured
74 | # (e.g. via a command-line flag).
75 | # config.default_formatter = "doc"
76 |
77 | # Print the 10 slowest examples and example groups at the
78 | # end of the spec run, to help surface which specs are running
79 | # particularly slow.
80 | # config.profile_examples = 10
81 |
82 | # Run specs in random order to surface order dependencies. If you find an
83 | # order dependency and want to debug it, you can fix the order by providing
84 | # the seed, which is printed after each run.
85 | # --seed 1234
86 | # config.order = :random
87 |
88 | # Seed global randomization in this process using the `--seed` CLI option.
89 | # Setting this allows you to use `--seed` to deterministically reproduce
90 | # test failures related to randomization by passing the same `--seed` value
91 | # as the one that triggered the failure.
92 | # Kernel.srand config.seed
93 | end
94 |
--------------------------------------------------------------------------------
/storage/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndresFMoya/react-rails_event_scheduler/a4be1b2b04d3295179acae0426fc65e80fee23ba/storage/.keep
--------------------------------------------------------------------------------
/tmp/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndresFMoya/react-rails_event_scheduler/a4be1b2b04d3295179acae0426fc65e80fee23ba/tmp/.keep
--------------------------------------------------------------------------------
/vendor/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AndresFMoya/react-rails_event_scheduler/a4be1b2b04d3295179acae0426fc65e80fee23ba/vendor/.keep
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | encoding@^0.1.11:
6 | version "0.1.12"
7 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
8 | integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
9 | dependencies:
10 | iconv-lite "~0.4.13"
11 |
12 | iconv-lite@~0.4.13:
13 | version "0.4.24"
14 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
15 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
16 | dependencies:
17 | safer-buffer ">= 2.1.2 < 3"
18 |
19 | is-stream@^1.0.1:
20 | version "1.1.0"
21 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
22 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
23 |
24 | isomorphic-fetch@^2.2.1:
25 | version "2.2.1"
26 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
27 | integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
28 | dependencies:
29 | node-fetch "^1.0.1"
30 | whatwg-fetch ">=0.10.0"
31 |
32 | node-fetch@^1.0.1:
33 | version "1.7.3"
34 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
35 | integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==
36 | dependencies:
37 | encoding "^0.1.11"
38 | is-stream "^1.0.1"
39 |
40 | "safer-buffer@>= 2.1.2 < 3":
41 | version "2.1.2"
42 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
43 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
44 |
45 | whatwg-fetch@>=0.10.0:
46 | version "3.0.0"
47 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
48 | integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
49 |
--------------------------------------------------------------------------------