# chap 1

## attr\_\*

attr\_accessor :engine allows you to read AND write to the variable @engine.

attr\_reader :engine only allows you to read the value of @engine

```ruby
attr_writer :age
# up is equal to bottom.
def age=(value)
  @age = value
end
```

```ruby
attr_reader :age
# up is equal to bottom.
def age
  @age
end
```

```ruby
attr_accessor :age
# up is equal to bottom.
def age=(value)
  @age = value
end

def age
  @age
end
```

## virtual attribute/ setter / :method=

`:method=` assign attributes by `=`

`:method` assign attributes by `()`

```ruby
class Foo
  def foo=(x)
    puts "OK: x=#{x}"
  end

  def poo(y)
    puts "KO: y=#{y}"
  end
end
f = Foo.new
f.foo = 123 # => 123
# OK: x=123
f.poo(123)
# KO: y=123
```

## use `var` & `@var` in class

1. With `attr_reader` inside class, you can use both `element` & `@element`.
2. Without `attr_reader` inside class, you can use only `@element`.

```ruby
class Person
  attr_reader :element # make different
  def initialize(element)
    @element = element
  end

  def at
      puts @element
  end

  def woat
    puts element
  end
end

gina = Person.new("Gina")

gina.at   # Gina
gina.woat # Gina
```

```ruby
class People

  def initialize(element)
    @element = element
  end

  def at
      puts @element
  end

  def woat
    puts element
  end
end

jason = People.new("Jason")

jason.at   # Jason
jason.woat # rb:12 undefined local variable or method `element'
```

## &:symbol

block: `{...}` or `do ... end`

`Proc`: set block as a variable.

`&Proc`: return the original block.

```ruby
my_proc = Proc.new { puts "foo" }
# => #<Proc:0x0012345677(irb):99> 
my_method_call(&my_proc) # is identical to:
my_method_call { puts "foo" }
```

```ruby
# people.collect { |p| p.name }
people.collect(&:name)

# people.select { |p| p.manager? }.collect { |p| p.salary }
people.select(&:manager?).collect(&:salary)
```

Difference between `Proc` and `lambda`:\
1\. `lambda` checks **argument numbers**, and `Proc` not.\
2\. `return` in `lambda` means "leaving lambda"; `return` in `Proc` means "leaving the **method**.

## `define_method(*args)`

Defines an instance method for the receiver: args.

```ruby
class A
  def fred
    puts "In Fred"
  end
  def create_method(name, &block)
    self.class.send(:define_method, name, &block)
  end
  define_method(:wilma) { puts "Charge it!" }
end
class B < A
  define_method(:barney, instance_method(:fred))
end
a = B.new
a.barney
a.wilma
a.create_method(:betty) { p self }
a.betty
```

```ruby
In Fred
Charge it!
#<B:0x401b39e8>
```

## `constantize(str)`

tries to find a declared constant with the name specified in the string.

```
'Module'.constantize  # => Module
'Class'.constantize   # => Class
'blargle'.constantize # => NameError: wrong constant name blargle
```

## Inject and Reduce

`Inject` and `Reduce` are the same.

```ruby
# Sum some numbers
(5..10).reduce(:+)                            #=> 45
# Same using a block and inject
(5..10).inject {|sum, n| sum + n }            #=> 45
# Multiply some numbers
(5..10).reduce(1, :*)                         #=> 151200
# Same using a block
(5..10).inject(1) {|product, n| product * n } #=> 151200
# find the longest word
longest = %w{ cat sheep bear }.inject do |memo,word|
   memo.length > word.length ? memo : word
end
longest                                       #=> "sheep"
```

```ruby
(1..10).inject(:+) # 55
(1..10).reduce(:+) # 55

def sum(start = 0)
  inject(start, &:+)
end
(1..10).sum # 55
```

## File

```ruby
__FILE__ # the current source file name.
__LINE__ # the current line number in the source file.
```

```ruby
File.dirname(__FILE__) # "."
File.expand_path(File.dirname(__FILE__))
# /Users/jasonych99/workspace/ROR/RULER/rulers
File.join(File.dirname(__FILE__), "..", "lib") # "./../lib"
```

The second param is the starting point for the first one in `File.expand_path`.

```ruby
File.expand_path(__FILE__)
 => "/Users/jasonych99/workspace/ROR/RULER/rulers/(irb)"
File.expand_path("../../assets/base.css", __FILE__)
 => "/Users/jasonych99/workspace/ROR/RULER/assets/base.css"
```

`$0` = name of the script being **executed**.

For example, when running ruby hello\_world.rb, $0 = hello\_world.

```ruby
__FILE__ == $0 
# the source code file == the file I'm executing!
```

reference: <http://periclestheo.com/2014/02/what-is-up-with-__FILE__-and-$0.html>

## const\_get / send (fetch class/method by "string" or :sym)

check and return the constant

```ruby
const_get(:sym)
const_get("string")
Math.const_get(:PI)   #=> 3.14159265358979
```

Invoke the method

```ruby
obj.send(:sym)
obj.send("string")
```

```ruby
class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  def oui
    "My name is #{@name}"
  end
end

target = Object.const_get("Person") # Person
target.class # Class

obj = Person.new("Jason") # #<Person:0x007f9012999248 @name="Jason">
obj.oui # "My name is Jason"
obj.send(:oui)  # "My name is Jason"
obj.send("oui") # "My name is Jason"
```

## include / extend

`include` provides **instance methods** for the class that mixes it in.

`extend` provides **class methods** for the class that mixes it in.

```ruby
module Foo
  def foo
    puts 'heyyyyoooo!'
  end
end

class Bar
  include Foo
end

Bar.new.foo # heyyyyoooo!
Bar.foo # NoMethodError: undefined method ‘foo’ for Bar:Class

class Baz
  extend Foo
end

Baz.foo # heyyyyoooo!
Baz.new.foo # NoMethodError: undefined method ‘foo’ for #<Baz:0x1e708>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://huang-jason.gitbook.io/ruby-rails-syntax/chap_1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
