2018年4月26日 星期四

同時定義 class method 和 instance method 的潮潮寫法

You can delegate method to your `class` since your class is also a object in Ruby, fanny~


```ruby
class Foo
  def self.bar
    return "Hello"
  end
  delegate :bar, to: :class
end
```

```ruby
Foo.bar
# => "Hello"

Foo.new.bar
# => "Hello"
```


Awesome.

為子 class 寫 class method 在 class 裡調用


老生常談的小技巧了,剛好看到 kickstarer 的一段 code,貼過來回溫一下


```ruby
    # Define attributes to be serialize in the `data` column.
    # It generates setters and getters for those.
    #
    # Example:
    #
    # class MyEvent < Events::BaseEvent
    #   belongs_to :post
    #
    #   data_attributes :title, :description
    # end
    #
    # MyEvent.create!(post: post, title: "Hello", description: "", metadata: {})
    def self.data_attributes(*attrs)
      @data_attributes ||= []

      attrs.map(&:to_s).each do |attr|
        @data_attributes << attr unless @data_attributes.include?(attr)

        define_method attr do
          self.data ||= {}
          self.data[attr]
        end

        define_method "#{attr}=" do |arg|
          self.data ||= {}
          self.data[attr] = arg
        end
      end

      @data_attributes
    end
```

https://gist.github.com/pcreux/d094affd957a336af4f59b85f6ec0e6d


Rails 不常用但可以變得很實用的 callback



## after_initialize && after_find

```ruby

class User < ApplicationRecord
  after_initialize do |user|
    puts "You have initialized an object!"
  end

  after_find do |user|
    puts "You have found an object!"
  end
end

>> User.new
You have initialized an object!
=> #<User id: nil>

>> User.first
You have found an object!
You have initialized an object!
=> #<User id: 1>
```

主要是 after_initialize 的部分,用來設定初始值挺方便的

http://guides.rubyonrails.org/active_record_callbacks.html#after-initialize-and-after-find


little funny learn from ruby private

I usually make my private methods like this:

```
class Foo
  private

  def private_method
  end
end
```

However, there is inline-style private method like this:

```
class Foo
  private def private_method
  end

  def puiblic_method_yo!
  end
end
```

Additionally, attr_reader is also available for inline-style private method:

```
class Foo
  private attr_reader :bar
end
```

So fancy, isn't it? lol

kickstarter 的 event sourcing approach

也解釋了一些 event sourcing 相關的東西,還不錯的深入淺出好文,而且還有 gif 圖加分XD

這張就很棒的解釋了他們所謂的 Aggregation (綠色, state), Reactor (黃色), Calculator (藍色箭頭), Event (藍色方塊)



https://kickstarter.engineering/event-sourcing-made-simple-4a2625113224

How rails store your migration history


有時候手動操作 database 刪掉了 table,於是乎 rails migration 跟 database 就對不起來了,要怎麼樣騙 rails 說上一個 create table 的 migration file 沒跑過呢?how does rails track this?

Ans: Rails 存了一個 schema_migrations 的 table 在database 裡面,只要把相對應的 record 刪掉就行了,easy peasy


https://stackoverflow.com/questions/12057408/how-does-rails-keep-track-of-which-migrations-have-run-for-a-database



2018年4月25日 星期三

ActionCable and AWS ELB 的坑



ActionCable old fix

在 puma 前面裝一層 nginx 已經解決 ActionCable 透過 ELB failed 的問題,主要是用 nginx 手動加上 `Connection "Upgrade"` 的 header

```
  location @puma {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Ssl on;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://puma;
  }

  location /cable {
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Forwarded-Host $host;
    proxy_set_header   X-Forwarded-Server $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_buffering    on;
    proxy_http_version 1.1;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Connection "Upgrade";
    proxy_set_header   X-Forwarded-Proto https;
    proxy_pass         http://puma;
    gzip off;
  }
```

https://blog.jverkamp.com/2015/07/20/configuring-websockets-behind-an-aws-elb/
https://in1004kyu.github.io/2017/06/14/rails-cable-aws.html
https://unboxed.co/blog/actioncable-on-aws/ (這一個是用 ALB 不過一樣可以參考看看)
https://keithpblog.org/post/rails-5-tutorial-chat-app-can-we-deploy-it/
https://github.com/rubytaiwan/AMA/issues/135


最後決定拿掉,原因:

Quote by CTO

大概就是 aws 的传统 load balancer elb 基本也只支持 http 的网页请求
但是 actioncable wss 是一种 tcp 协议,load balancer 也要支持 tcp 连线方式才行
改了 elb 设定支持 tcp 连线方式,又会让原本 http 的行为有点问题
就是 deploy 时 puma restart load balancer 不会先 queue 住用户连线就会喷 502
然后 aws 比较好的 alb 功能比较强的 load balancer 好像无法调整支持 tcp 连线
但是 alb 可以支持 load balancer 去规划防火墙连线规则挡 ddos
所以前几天我找 aws 技术支持关于挡 ddos 他也是建议我们快点改架构可以用 alb