# :gem: Ruby Quick Note
> As usual, this is a quick, unorganized, messy note.
:::spoiler Click to open Table of Content
[TOC]
:::
## :ballot_box_with_check: TODO:
- [ ] what exactly is "Symbol"
- [ ] rails async io ?
- [ ] how ruby mange "block"
- [ ] meta-programming: do it pre-compile like C? or after AST or ???
- [ ] how method evaluation and reference (how to passing lambda around)
- > hint: sth called `proc` object. `lambda` is a `proc` object with special attributes
- > hint^2: block can be encapsulate in `proc`
## :chicken: Common mistakes
:::warning
### :bug: `validate` and `validates` are different :exclamation:
`validate` points to a method that contains **custom** validation logic
`validates` applies to **pre-built** validators
:::
:::warning
### :bug: Plural in Rails
be careful of model's plural...
> I run into some oopsie doopsie error because of this.
> I'm so stupid :(
```ruby
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through :user_roles # <- has **many** **roles**
end
class UserRole < ApplicationRecord
belongs_to :user
belongs_to :role # <- belongs to **A** role
end
```
```shell
# each raw reference to A user, A role
$ rails g migration CreateUserRoles user:references role:references
```
:::info
:pencil:
And Yes, even irregular plural noun like 'people' and 'child' do this
`ActiveSupport::Inflector` will handle these English special cases
for example:
```ruby
class Person < ApplicationRecord
...
class Role < ApplicationRecord
has_many :person_roles
has_many :people, through: :person_roles
```
> starts to feel a little bit hilarious at this point...
:::
:::warning
### ERB: `<%= %>` and `<% %>` are different
- `<% %>` embedded ruby code
- `<%= %>` embedded ruby AND return/write value to the content
#### Haml
- `- if xxx` evaluate ruby code
- `= link_to xxx` return the value of the ruby code
:::
:::warning
### Gem pg cannot found `libpq-fe.h`
if installed `libpq` via `brew`, we needs to add the libpq to PATH
```zsh
# ~/.zshrc or ~/.zprofile
export PATH="/opt/homebrew/opt/libpq/bin:$PATH"
```
:) easy task
:::
# Notes:
## functional collection processing
```ruby
# These are equivalent:
users.map { |user| user.confirmed? }
users.map(&:confirmed?)
user.map do |user|
user.confirmed?
end
# also can be view as different way of handling "block"
```
`.map` and `.collect` are the same
> why ruby why :face_palm:
- `.each` only iterate the item
- `.map` will also return the result as array
- `.map!` will modify the object to result
### chain the operation in rails
```ruby
# from all user select whom is activated but not admin then get an array of their email
User.all.select(&:active?).reject(&:admin?).map(&:email)
```
## Gems
:::info
### Sidekiq
#### Naming
`work` is the old term. `Job` is the new term.
`Sidekiq::Work` -> `Sidekiq::Job`
#### Active_job
Rails has a default buildin job queue frame work called Active_job. But we could set config to override the default active job to `sidekiq` (for more functionality?)
:::
:::info
### Devise
https://github.com/heartcombo/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style#after
:::
:::info
### Factory_bot
- factory can have child and inherits from parent
```ruby
factory :user do
name { 'name' }
factory :admin do
admin {true}
end
end
create :admin
```
```ruby
factory :user do
name {'name'}
trait :admin do
admin {true}
end
end
create :user, traits: [:admin]
```
:::
:::info
### cancancan
How it works:
`can(action, subject, *conditions, *block)` will trigger `add_rules`
Each class will associate with multiple rules.
> Note: cancan will handle the inheritance relationship
> e.g.:
> ```ruby
> can :show, Animal
> can? :show, Cat # -> true
> ```
when calling `can?` it will:
```
- for every related rules
- evaluate code blocks if has blocks
- evaluate condition if has condition
- return true if passing in `Class` object (no evaluation needed)
- if no matching rules -> return false
```
#### controller integration
`load_and_authorize_resource` add `before_action`: `can #method, @resource`
it will try to auto-match the action_name with method_name:
:::
## DB
- quick-reminder
- migrate: setup table schema (and change)
- seed: init default data
## controller
instance variable in `.erb`'s(_view_) instance refer to the controller
> Rails renders the view in context of the conroller instance
erb can also access some variable from helper function?
:::info
#### :book: How controller and rendering process works
Gems like `devise` and `cancancan` will mixin their helper function to `ActionController`,
and then before _rails_ do the rendering it will do require everything needed from `ActionController`
hence, we cloud access to all the helper function and controller instance variables in the `view.erb` files
> note: _rails_ will init a instance for every request call.
> note: rails use `Zeitwerk` to implement dependency injection so that ActionController would able to access all the "beans" it needed
> ==TODO==: I feel something wrong here... I needs to go more investigation
:::
## Meta programming
### example
`devise/controllers/helpers.rb`
```ruby
def self.define_helpers(mapping) #:nodoc:
mapping = mapping.name
class_eval <<-METHODS, __FILE__, __LINE__ + 1
def #{mapping}_signed_in?
!!current_#{mapping}
end
# create `customer_signed_in?` method when use `Customer` as resource
# create `user_signed_in?` method when use `User` as resource
```
> reminds me of C, the good old `#define`
# RUBY :gem: :gem: :gem:
:::info
Object:
top level methods belongs to `main` object
:::
## Cool vid
- [rubyconf dont' @ me](https://www.youtube.com/watch?v=R0oxlyVUpDw)
- [rubyconf phaser](https://www.youtube.com/watch?v=n3h2uPDZ2LY)
## something deeper


:::info
## Ruby Object
### Struct
```graphviz
digraph {
node [shape="record"]
g [ label="{\<Ruby Object Struct\> | flags | klass | *iv_tbl }"]
}
```
> **klass** means class. using klass to avoid conflict with the keyword `class`
> **iv** stands for instance variable
Ruby will store first few variable directly inside of Ruby Object. After the forth instance variable been added to the object, it will crate a separated table to store the all the iv.
```graphviz
digraph {
node [shape="record"]
rankdir=LR;
g [ label="\<Ruby Object Struct\> | flags | klass | foo | bar | <iv> *iv_tbl"]
tbl [ label=" <top> 123 | 'string'"]
g:iv -> tbl:top
}
```
[:page_facing_up: **ruby doc**](https://ruby-hacking-guide.github.io/object.html)

### caching
ruby use Object Shape to cache the instance variable index.
:::
### Fun Facts
#### No Boolean Class
```ruby
> true.class
=> TrueClass
> TrueClass.superclass
=> Object
> false.class
=> FalseClass
> FalseClass.superclass
=> Object
```
`TrueClass` and `FalseClass` are direct child of `Object`, **NO** BooleanClass.
> https://www.rubytapas.com/2019/01/08/boolean/