<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>bjmark (bjmark)</title>
    <link>https://ruby-china.org/bjmark</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>用 Phoenix 开发一个小应用，谈点感受</title>
      <description>&lt;p&gt;首先，Elixir 大量地借鉴了 Ruby，Phoenix 大量地借鉴了 Rails，所以 Rails 开发者学习 Elixir 和 Phoenix 会比较轻松。&lt;/p&gt;

&lt;p&gt;第二，Elixir 也许没有 Ruby 好，但已经足够好，使用 Elixir 理由不是 Elixir 语言本身，而是 Elixir 下面的基础 Erlang 虚机，Erlang 虚机在分布和并发上的优势以及其设计理念 (不担心局部代码崩溃，确保整个应用运行) 完全值得投入时间去学习和尝试。&lt;/p&gt;

&lt;p&gt;介绍一下我的学习路径，学 Elixir 看了《Elixir 程序设计》和《Elixir In Action》还有 elixir-lang.org 上的 getting started，感觉官网上的教程更简洁适用些。学 Phoenix 看了《Programming Phoenix》，感觉这书写的有些繁琐，但好像也没别的选择了。&lt;/p&gt;

&lt;p&gt;附上我的小应用的网址：&lt;a href="http://www.my-note.cn" rel="nofollow" target="_blank"&gt;http://www.my-note.cn&lt;/a&gt; ,是一个用标签管理个人信息零散信息的简单应用，我用它管理 ruby 代码的用例，也许你也用的上，欢迎大家试试。&lt;/p&gt;</description>
      <author>bjmark</author>
      <pubDate>Sat, 06 Aug 2016 13:15:44 +0800</pubDate>
      <link>https://ruby-china.org/topics/30751</link>
      <guid>https://ruby-china.org/topics/30751</guid>
    </item>
    <item>
      <title>active_support/concern.rb 是否有点多此一举？</title>
      <description>&lt;p&gt;下面是源码中对问题的描述及利用 concern 的解决方式&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ActiveSupport&lt;/span&gt;
  &lt;span class="c1"&gt;# A typical module looks like this:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   module M&lt;/span&gt;
  &lt;span class="c1"&gt;#     def self.included(base)&lt;/span&gt;
  &lt;span class="c1"&gt;#       base.extend ClassMethods&lt;/span&gt;
  &lt;span class="c1"&gt;#       base.class_eval do&lt;/span&gt;
  &lt;span class="c1"&gt;#         scope :disabled, -&amp;gt; { where(disabled: true) }&lt;/span&gt;
  &lt;span class="c1"&gt;#       end&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#     module ClassMethods&lt;/span&gt;
  &lt;span class="c1"&gt;#       ...&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# By using &amp;lt;tt&amp;gt;ActiveSupport::Concern&amp;lt;/tt&amp;gt; the above module could instead be&lt;/span&gt;
  &lt;span class="c1"&gt;# written as:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   require 'active_support/concern'&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   module M&lt;/span&gt;
  &lt;span class="c1"&gt;#     extend ActiveSupport::Concern&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#     included do&lt;/span&gt;
  &lt;span class="c1"&gt;#       scope :disabled, -&amp;gt; { where(disabled: true) }&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#     module ClassMethods&lt;/span&gt;
  &lt;span class="c1"&gt;#       ...&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# Moreover, it gracefully handles module dependencies. Given a +Foo+ module&lt;/span&gt;
  &lt;span class="c1"&gt;# and a +Bar+ module which depends on the former, we would typically write the&lt;/span&gt;
  &lt;span class="c1"&gt;# following:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   module Foo&lt;/span&gt;
  &lt;span class="c1"&gt;#     def self.included(base)&lt;/span&gt;
  &lt;span class="c1"&gt;#       base.class_eval do&lt;/span&gt;
  &lt;span class="c1"&gt;#         def self.method_injected_by_foo&lt;/span&gt;
  &lt;span class="c1"&gt;#           ...&lt;/span&gt;
  &lt;span class="c1"&gt;#         end&lt;/span&gt;
  &lt;span class="c1"&gt;#       end&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   module Bar&lt;/span&gt;
  &lt;span class="c1"&gt;#     def self.included(base)&lt;/span&gt;
  &lt;span class="c1"&gt;#       base.method_injected_by_foo&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   class Host&lt;/span&gt;
  &lt;span class="c1"&gt;#     include Foo # We need to include this dependency for Bar&lt;/span&gt;
  &lt;span class="c1"&gt;#     include Bar # Bar is the module that Host really needs&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We&lt;/span&gt;
  &lt;span class="c1"&gt;# could try to hide these from +Host+ directly including +Foo+ in +Bar+:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   module Bar&lt;/span&gt;
  &lt;span class="c1"&gt;#     include Foo&lt;/span&gt;
  &lt;span class="c1"&gt;#     def self.included(base)&lt;/span&gt;
  &lt;span class="c1"&gt;#       base.method_injected_by_foo&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   class Host&lt;/span&gt;
  &lt;span class="c1"&gt;#     include Bar&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# Unfortunately this won't work, since when +Foo+ is included, its &amp;lt;tt&amp;gt;base&amp;lt;/tt&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;# is the +Bar+ module, not the +Host+ class. With &amp;lt;tt&amp;gt;ActiveSupport::Concern&amp;lt;/tt&amp;gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;# module dependencies are properly resolved:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   require 'active_support/concern'&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   module Foo&lt;/span&gt;
  &lt;span class="c1"&gt;#     extend ActiveSupport::Concern&lt;/span&gt;
  &lt;span class="c1"&gt;#     included do&lt;/span&gt;
  &lt;span class="c1"&gt;#       def self.method_injected_by_foo&lt;/span&gt;
  &lt;span class="c1"&gt;#         ...&lt;/span&gt;
  &lt;span class="c1"&gt;#       end&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   module Bar&lt;/span&gt;
  &lt;span class="c1"&gt;#     extend ActiveSupport::Concern&lt;/span&gt;
  &lt;span class="c1"&gt;#     include Foo&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#     included do&lt;/span&gt;
  &lt;span class="c1"&gt;#       self.method_injected_by_foo&lt;/span&gt;
  &lt;span class="c1"&gt;#     end&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#   class Host&lt;/span&gt;
  &lt;span class="c1"&gt;#     include Bar # works, Bar takes care now of its dependencies&lt;/span&gt;
  &lt;span class="c1"&gt;#   end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;首先我认为这根本不是个问题。
Bar 依赖于 Foo，那么先 include Foo，再 include Bar，通过代码说出来把事情说清楚，简单明了，易于理解。&lt;/p&gt;

&lt;p&gt;其次，如果不想 include Foo，只想 include Bar，下面的方法是不是更简单些呢？&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Foo&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;included&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class_eval&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method_injected_by_foo&lt;/span&gt;
        &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"method_injected_by_foo"&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Bar&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;included&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:include&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method_injected_by_foo&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;
  &lt;span class="c1"&gt;#include Foo&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Bar&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>bjmark</author>
      <pubDate>Sat, 16 Nov 2013 18:31:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/15590</link>
      <guid>https://ruby-china.org/topics/15590</guid>
    </item>
  </channel>
</rss>
