Ruby Tutorial – end of 5,
- Setting up our Links
- Testing for routes: convert things like:
visit '/static_pages/help'
tovisit help_path
- eliminate duplication with the
before { stuff to do }
statement at the beginning of adescribe
block - if your specs are written so well that descriptions are redundant, and that many
it
blocks examine the same method or element, you can begin a block with thesubject { victim_variable_or_method_here }
statement, and then put eachshould
statement in the curly braces – this is thanks to the help of Capybara - Rspec will also automatically look in the
spec/support
directory, so adding in ruby files there with useful methods and referencing them from files in the spec/requests/ directory works fine… i.e. the name of the file is not important- you can safely
include
the name of a module that appears elsewhere, like inapp/helpers/
, if it is required for the methods being run in the spec
- you can safely
- eliminate duplication with the
- Checking that links go to the correct place (rather than just testing the routing with
visit
)click_link
to load a page, and then run some identification test on that page
- Testing for routes: convert things like:
- Reducing redundancy with
shared examples
- using a
shared_examples_for "template name"
block, you can template tests, using some variables in the template, which are then called withit_should_behave_like "template name"
, for which variables are instantiated before the call with:let(:variable1) { 'text that variable represents' }
- using a
- Defining routes: in the
config/routes.rb
file, converting things likeget "static_pages/home"
tomatch '/help' , to: 'static_pages#help'
- arranges for a valid page at
/help
- and a named route called
help_path
match
is interchangable withget
here, but it is more conventional as is- the
to:
signifies that all matches ofabout
will be routed to theStaticPages
controllerabout_path => '/about'
is createdabout_url => 'http://localhost:3000/about'
is created
- arranges for a valid page at
- A new controller
rails generate controller Users new --no-test-framework
- generates a Users controller with a
new
action --no-test-framework
because we are using RSpec- right after, we do:
rails generate integration_test user_pages
- right after, we do:
- familiar match statements fo into the
routes.rb
file, but aget 'users/new'
is still required
- generates a Users controller with a
- Data in Rails
- model = default data structure
- using
attar_accessor
within a model ensures that only the variables specified are made available to users
- using
- Migrations – a feature to allow data definitions to be written in Ruby, and no SQL data definition language
- incrementally alter database
change
method, change that will be made to the database- Case
- table name is plural
- singular for model
- plural for controller
db:migrate
is “migrating up”db:rollback
is “migrating down”- for tests to work, the test database needs to be updated too:
bundle exec rake db:test:prepare
- model = default data structure
- The Annotate gem
- adds comments containing the data model to the model file! nice visualization!
rails console --sandbox
results in all changes being rolled back when the console is quit- RSpec boolean convention – Ruby boolean values can be used in RSpec if the question marks are dropped off
Rails for Zombies 2 – Level 1
- Level 1
- Bundler
- installs dependencies as specified by
Gemfile
- configuration in config/database.yml
rails g scaffold zombie name:string
(has the format:column_name:type
)- availible types: string, text, integer, boolean, decimal, float, binary, date, time, datetime
- Migrations (Rails Guide) – keeping track of changes
- in
db/migrate/
contains a primary key called id; represented by the|t|
(t for table)- creates a table, via
create_table
, with certain fields as specified in the scaffold command - makes a t.timestamps, creating and updating a datetime
- to update the table manually:
add_column :table_name, :field, :type, option_name: option
- instead of
add_column,
can also do additional commands:rename_column, rename_table, drop_table, change_column, change_column_defaut, remove_column
- for Example:
rename_column
takes 3 args, name of table, name of column to rename, new name of column
- for Example:
- instead of
- to update the table via commandline:
rails g migration AddEmailAndRottingToZombies email:string rotting:boolean
- adds two columns to our database
- adding column options: default, limit, (cant be) null, positio, unique
- still need to run
rake db:migrate
- creates a table, via
- in
- need to run a migration to include something in the database
rake db:migrate
rake db:rollback
undoes at the database levelrake db:shema:dump
(dumps current db state)- run by default when you
db:migrate
- will show
db/schema.rb
which contains current db contents - related to:
rake db:setup
which creates the db, loads schema and runs seed data- this is what should be run after you implement someone’s old, heavily used db, to get the last state
- run by default when you
- removing something from the database
rails g migration RemoveAgeFromZombies age:integer
- separate up and down methods for migrating forward and backward
- Level 2
- Named scope – returning particular items in the db
scope :name, method_on_db(args)
under models (where it is a method used often), will allow a method calledname
to be called on the db in the controller:Table.name
scope :recent, order("created_at desc").limit(4)
- works fine with chaining
- Callbacks
- Put logic, like conditional statements and actions that are reused, into a model
- model methods: using self, not instance variables
- then call this logic with key phrases like:
before_save :method1
, orafter_update
, orbefore_destroy
… - careful of return values, model will halt at false
- Put logic, like conditional statements and actions that are reused, into a model
- Relationships
- have two tables,
Zombie
andBrain
, linked together withbelongs_to
andhas_one ,
to make sure that when one is destroyed the other linked table entry is too, dodependent: :destroy
right after the relationship that points to the model that you want to effect- similar options:
foreign_key:, primary_key:, validate: true
(check two table’s validation rules before saving)
- similar options:
- N+1 query – list each entry in a db with an attribute’s value (one entry loading after another in series)
- instead,
Table.includes(:attribute).all
will be much more efficient (in some controller method)
- instead,
- has_many: through
- when you need to have multiple roles/attributes for one category for an item in a table –
belongs_to
only works with one value for an attribute - Instead, have an
intermediate
table, where thefirst
andthird
table both has_manyAssignments
, andassignments belongs_to
bothfirst
andthird
, and thenfirst has_many thirds, through: :intermediate
, and vice versa - singular tense with belongs_to!
- can then add multiple
third
attributes to first, or one, like appending an array onto the ownerz.roles << Role.find_by_title("Captain")
- when you need to have multiple roles/attributes for one category for an item in a table –
- have two tables,
- Named scope – returning particular items in the db
Advertisements