$ bundle
$ yarn
$ rails db:setup
$ rails generate devise:views
$ yarn remove react-router-dom
$ yarn add react-router-dom
$ yarn add react-bootstrap
Change class components into functional. Use rfc to speed up the process.
Change switch import to routes on App.js Change component to element and add </> around each component reference to make it a component call Change this.props to props
Change Header component to reflect functional component changes. Remove render Remove { Component } import
$ rails generate scaffold Apartment street:string city:string state:string manager:string email:string price:string bedrooms:integer bathrooms:integer pets:string image:text user_id:integer --api
$ rails db:migrate
Create associations between user and apartments model
/app/models/user.rb /app/models/apartment.rb Comment out code inside apartment controller methods for now. app/controllers/apartments_controller.rb
$ rails s
cmd + t
$ ./bin/webpack-dev-server
create the fetch request, unlike cat-tinder where we had to use localhost, this monolithic app lets us route using just /apartments in the fetch request.
The useEffect hook with an empty array to simulate componentDidMount()
import { Card, Button } from 'react-bootstrap'
function readApartments () {
fetch("/apartments")
.then(request => request.json())
.then(payload => setApartments({apartments: payload}))
.catch(err => console.log(err))
}
useEffect(() => {
readApartments()
},[])
unlike cat tinder, I wasn't able to pass down apartments like i did to the index page. It wouldn't let me use apartments={apartments} twice. I ended up doing a fetch request
let [apartment, setApartment] =useState([])
let { id } = useParams()
function showApartment (id) {
fetch(`/apartments/${id}`)
.then(request => request.json())
.then(payload => setApartment(payload))
.catch(err => console.log(err))
}
useEffect(() => {
showApartment(id)
},[])
make sure to cover validation testing
Tests should cover cases when user is signed in or logged out Header can conditionally render sign in, sign out, create buttons depending on login status. Using react-bootstrap, used Navbar and NavbarDropdown to allow for easy routing. NavBrand should route back to home
import { Container, Nav, Navbar, NavDropdown } from 'react-bootstrap'
This part fall under protected index - however, it will be incorporated into the header to create better functionality for the user.
The header also holds a lot of user data so we can use it to create conditional renders with off canvas listings.
This app has been created for you to mimic the feeling of entering into a developer role where there is established code that you have not created. This Apartment application has a few features that have been created for you and some key items that have been left totally untouched. Part of your job as a developer is to be able to pick up code that has already been created, understand what is going on with it, and continue the development of that code.
$ rails new apartment-app -d postgresql -T
$ cd apartment-app
$ rails db:create
$ bundle add rspec-rails
$ rails generate rspec:install
$ bundle add webpacker
$ bundle add react-rails
$ rails webpacker:install
$ rails webpacker:install:react
$ yarn add @babel/preset-react
$ yarn add @rails/activestorage
$ yarn add @rails/ujs
$ rails generate react:install
$ rails generate react:component App
$ bundle add devise
$ rails generate devise:install
$ rails generate devise User
$ rails db:migrate
$ rails generate controller Home
config/environments/development.rb
This line added:
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config/initializers/devise.rb
# This line replaced:
config.sign_out_via = :delete
# With this line:
config.sign_out_via = :get
File added in app/views/home called index.html.erb app/views/home/index.html.erb
<%= react_component 'App', {
logged_in: user_signed_in?,
current_user: current_user,
new_user_route: new_user_registration_path,
sign_in_route: new_user_session_path,
sign_out_route: destroy_user_session_path
} %>
app/views/layouts/application.html.erb
# This line replaced:
<%= javascript_importmap_tags %>
# With this line:
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
config/routes.rb
# These lines added:
get '*path', to: 'home#index', constraints: ->(request){ request.format.html? }
root 'home#index'
yarn add [email protected]
app/javascript/components/App.js
import {
BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom'
bundle add bootstrap
mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
yarn add reactstrap
app/assets/stylesheets/application.scss
@import 'bootstrap';
Once you're able to clone the repository, within the root of the project directory, run:
$ bundle
$ yarn
$ rails db:setup
$ rails s
cmd + t
$ ./bin/webpack-dev-server
$ yarn remove react-router-dom
$ yarn add react-router-dom
$ yarn add react-bootstrap
rails s
See what is available already in the application.
- What can a USER do?
- What views (pages, components) are available?
The Devise User model is going to have an association with the Apartment model. In this situation, the User will have many apartments and the Apartments will belong to a User.
rails generate scaffold Apartment street:string city:string state:string manager:string email:string price:string bedrooms:integer bathrooms:integer pets:string image:text user_id:integer --api
rails db:migrate
The Apartments will belong to a User and a User will have many apartments.
app/models/apartment.rb
class Apartment < ApplicationRecord
belongs_to :user
end
app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :apartments
end
To run the existing testing suite, run:
yarn jest
rspec spec/
Part of your responsibility will be to build out robust tests both for models and for requests. Tests you will need are:
REQUEST:
- to ensure a user can see all apartments
- to ensure a user can see all apartments that belong to them
- to ensure a user can make a new apartment
- to ensure a user can update an apartment
- to ensure a user can remove an apartment
- to ensure a user cannot make a new apartment with nil values
- to ensure an error will be thrown if an unregistered user tried to make an apartment
- to ensure an error will be thrown if a user tries to edit an apartment that doesn't belong to them
- to ensure an error will be thrown if a user tries to delete an apartment that doesn't belong to them
MODELS:
- to ensure apartment is valid
- to ensure a user cannot make a new apartment with nil values
- to ensure a user cannot make a new apartment that already exists in the database
- to ensure a user cannot update an apartment with nil values
- to ensure a user cannot update another user's apartment
The following code is a mock and does not work but is here to get your started.
require 'rails_helper'
RSpec.describe "Apartments", type: :request do
describe "GET /index" do
it 'returns a list of apartments' do
user = User.where(email: '[email protected]').first_or_create(password: '12345678', password_confirmation: '12345678')
user.apartments.create(
street: string,
city: string,
state: string,
manager: string,
email: string,
price: string,
bedrooms: integer,
bathrooms: integer,
pets: string,
image: text
)
get '/apartments'
apartments = JSON.parse(response.body)
expect(response).to have_http_status(200)
expect(apartments.length).to eq(1)
end
end
end