Rails Project Crib Notes
New Rails Project
rails new <name> --database=<db> OR
rails new <name> -d <db>
Using postgresql (Apr 7, 2020)
rake db:create to ensure you have your db connections working
Add Addtl Tools to Gemfile
gemfile - best practice is to set specific versions only
group :development do
  gem 'better_errors'
  gem 'binding_of_caller'
  gem 'pry-rails'
end
group :development, :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end
group :test do
  gem 'faker'
  gem 'guard-rspec'
  gem 'launchy'
end
bundle install to update the gemfile lock
Tour the App Structure
/app
model is the class that represents the table of the db
controller handles the data coming, accesing the models, and then the views to provide a response
view is a template for the data to be presented for return
/config
database.yml
specifies which db and how it connects
routes.rb
defines what http routes are avail and which controllers to create and trigger actions on
/db
seeds.rb
holds the test data
/features
holds cucumber bdd feature files and their steps
- 
    
A cucumber file is named
<feature_desc>.featureand lives at the top level /features/step_definitionsholds the steps to be tested/features/supportholds support files like the env
/lib
holds any classes/files made internally
/public
404 pages
custom html stuff
/spec
testing files go here
- ‘/spec/factories’ Factory Bot files
 - ‘/spec/models’ RSpec model tests
 - ‘/spec/controllers’ RSpec controller tests
 
/vendor
js files and libraries from external sources
Migrations
Rails writes our sql tables for us record of the changes of the db
rails generate migration CreateObjectTable - somewhat semantic what you did, to read it, but isn’t critical, ruby will try to read it though
creates a .rb file with a timestamp, snakecased def change
create_table :objectplural do |t| t.string :name, null: false t.timestamps end end
then:
rake db:migrate, which executes any code in the change method
to check the state the db is in, need to check the schema schema.rb
rails g migration CreateToys
to rollback the last
rake db:rollback - should work on standard things, but usually you need the on down methods within the migration to handle it more finely
don’t rollback in production, only forward edits, like git has to
to add a column, within the change code of a migration:
add_column :cats, :color, :string
Using Models to interact with the db
Models as object oriented ways to interact cat.rb to model the cats table
class Cat (class and file name should be same, but different case) class Cat < ApplicationRecord
end
rails c
able to call the cat class c = Cat.new makes a local instance in the rails console without saving to db until you ask for save c.name = “Sarah” c.save
read cat from the db Cat.first
annotate gem
add to development group gem ‘annotate’
then bundle install
then, as long as your model files exist with the class skels
bundle exec annotate --models
Write basic macros for associations
instead of writing out queries, belongs_to and has_many and others are boilerplate ensure functions and checks
belongs_to :model, { primary_key: :id, foreign_key: :other_id, class_name: ‘Class’ }
Complex Asociations
double
has_many :things
  through: 
has_one :thing
  through: 
Basic Validations
It is important to make sure that any entries saved to the db are complete and will not throw any kind of errors when it does try to save. A db level exception will throw a 500 level error up to the user experience, no bueno.
Instead, by ensuring there is a validation set on every piece of information in a meaningful way, errors can be created and sent to ensure the user is able to correct her entry accordingly.
Anything with a null:false on the migration should have a presence:true
Same for anything that gets a unique: true via indexing should validate uniqueness: true
| Validation | Database Constraint | Model Validation | 
|---|---|---|
| Present | null: false | presence: true | 
| All Unique | add_index :tbl, :col, unique: true | uniqueness: true | 
| Scoped Unique | add_index :tbl, [:scoped_to_col, :col], unique: true | uniqueness: { scope: :scoped_to_col } | 
Also:
format- Tests whether a string matches a given regular expression
 
length- Tests whether a string or array has an appropriate length. Has
options for 
minimumandmaximum. 
- Tests whether a string or array has an appropriate length. Has
options for 
 numericality; options include:greater_than/greater_than_or_equal_toless_than/less_than_or_equal_to
inclusioninoption lets you specify an array of possible values. All other values are invalid.
Caveat!
Rails 5 automatically validates the presence of belongs_to associations.
Use optional: true to the association initialization to remove presence requirement.
Don’t double up with an extra validates presence at the top either, leads to confusing messages.
Custom Vals
It is super easy to write a custom method for validation:
class Invoice < ApplicationRecord
  # validate tells the class to run these methods at validation time.
  validate :method_that_checks_something
  private
  def method_that_checks_something
    if something.false
      errors[:object] << 'semantic description of error goes here.'
    end
  end
end
Errors :base for when you have no other option:
def a_method_used_for_validation_purposes
  errors[:base] << 'This person is invalid because ...'
end
Testing in the Console
Create a new object, such as 
j = User.new
j.valid? Will return false if any error messages in the array, true if clean.
To get an array of the human readable messages (such as you made above), call <record>.errors.full_messages. Remember, it only fails if a message gets put in.