You'll find that this project has two Active Record "models" (classes):
- Store
- Employee
This means that there is a stores
table and an employees
table in the database that it is using. Since we are using an ORM, we just use the two ruby classes and their instances to manage (CRUD) that data.
We'll be modifying this database via Active Record only. The setup.rb
file already defines the database structure so you don't need to create anything in the database using SQL manually.
That said, feel free to connect to your Postgres database using psql
or pgAdmin so that you can see what's in the database.
If you have an Apple M1 machine, please follow those instructions before completing the setup part of the instructions, do not do them if you're not on an M1 machine!
- Confirm that you are running version 2.6.6 of ruby (ruby -v)
- Remove the Gemfile.lock file
- In Gemfile, change the version of ActiveRecord from
4.2.6
to4.2.11
- In Gemfile, change the
gem 'pg'
line togem 'pg', '~> 0.21.0'
- Create a new Postgres database. Use
psql postgres
to connect to the database server. Usecreate database ar_exercises;
to create the database. - Take a look at the
establish_connection
method call insetup.rb
. This will allow Active Record to connect to your Postgres database. If you are using vagrant, you should not need to make any changes here. - Run
bundle install
to install the gems. - Run the first exercise file to make sure the database connection is working:
bundle exec ruby exercises/exercise_1.rb
. It should just output "Exercise 1" at the end, since you don't yet have any code in there.
- Running without
bundle exec
may run the wrong version of ruby or it may use the correct version of ruby but with incorrect gem versions. - Using
bundle exec
for ruby scripts/apps is fairly common in the Ruby community.
Complete the exercises by modifying the appropriate exercises/exercise_*.rb
file and run the exercise using the ruby
command.
Example:
bundle exec ruby exercises/exercise_1.rb
Follow the instructions to work on the exercises within the exercises
folder. Each exercise is to be completed in it's appropriate file.
IMPORTANT:
- Remember to
git commit
(andgit push
) at logical steps, like at the end of every exercise. - You do not need to / should not comment out your code in each exercise as you move on to the next one. The exercises in this assignment are meant to build on and continue from the previous ones. That's why you see them requiring the previous ones.
- The setup ruby script actually drops and recreates the db tables with every run of the exercise. This is of course not practical in most real apps, because the data is usually meant to stay long term.
You can work with the models with irb by running
irb -r './setup.rb'
- Use Active Record's
create
class method multiple times to create 3 stores in the database:
- Burnaby (annual_revenue of 300000, carries men's and women's apparel)
- Richmond (annual_revenue of 1260000 carries women's apparel only)
- Gastown (annual_revenue of 190000 carries men's apparel only)
- Output (
puts
) the number of the stores using ActiveRecord'scount
method, to ensure that there are three stores in the database.
- Load the first store (with
id = 1
) from the database and assign it to an instance variable@store1
. - Load the second store from the database and assign it to
@store2
. - Update the first store (
@store1
) instance in the database. (Change its name or something.)
- Load the third store (into
@store3
) as you did the other two before. - Using Active Record's
destroy
method, delete the store from the database. - Verify that the store has been deleted by again outputting (
puts
ing) thecount
(as you did in Exercise 1.)
- Borrowing and modifying the code from Exercise one, create 3 more stores:
- Surrey (annual_revenue of 224000, carries women's apparel only)
- Whistler (annual_revenue of 1900000 carries men's apparel only)
- Yaletown (annual_revenue of 430000 carries men's and women's apparel)
- Using the
where
class method from Active Record, fetch (a collection of) only those stores that carry men's apparel. Assign the results to a variable@mens_stores
. - Loop through each of these stores and output their name and annual revenue on each line.
- Do another fetch but this time load stores that carry women's apparel and are generating less than $1M in annual revenue.
- Output the total revenue for the entire company (all stores), using Active Record's
.sum
calculation method. - On the next line, also output the average annual revenue for all stores.
- Output the number of stores that are generating $1M or more in annual sales. Hint: Chain together
where
andsize
(orcount
) Active Record methods.
We haven't used the Employee class (and employees table) at all yet. If you look at this table's column structure, you'll find that it has a store_id
(integer) column. This is a column that identifies which store each employee belongs to. It points to the id
(integer) column of their store.
Let's tell Active Record that these two tables are in fact related via the store_id
column.
- Add the following code directly inside the Store model (class):
has_many :employees
- Add the following code directly inside the Employee model (class):
belongs_to :store
- Add some data into employees. Here's an example of one (note how it differs from how you create stores):
@store1.employees.create(first_name: "Khurram", last_name: "Virani", hourly_rate: 60)
- Go ahead and create some more employees using the create method. You can do this by making multiple calls to create (like you have before.) No need to assign the employees to variables though. Create them through the
@store#
instance variables that you defined in previous exercises. Create a bunch under@store1
(Burnaby) and@store2
(Richmond). Eg:@store1.employees.create(...)
.
- Add validations to two models to enforce the following business rules:
- Employees must always have a first name present
- Employees must always have a last name present
- Employees have a hourly_rate that is a number (integer) between 40 and 200
- Employees must always have a store that they belong to (can't have an employee that is not assigned a store)
- Stores must always have a name that is a minimum of 3 characters
- Stores have an annual_revenue that is a number (integer) that must be 0 or more
- BONUS: Stores must carry at least one of the men's or women's apparel (hint: use a custom validation method - don't use a
Validator
class)
- Ask the user for a store name (store it in a variable)
- Attempt to create a store with the inputted name but leave out the other fields (annual_revenue, mens_apparel, and womens_apparel)
- Display the error messages provided back from ActiveRecord to the user (one on each line) after you attempt to save/create the record