• 如何确保订单状态安全性 at 2014年04月15日

    涉及金额的运算,要使用事务,而不是 callback. 事务里,加上线程的保护: http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html

  • 我觉得这是一个很复杂的问题,使用 Conerns 就这个意思:

    为什么呢?我避免将一个大的 ActiveRecord 类里面的一部分方法放到某个关联类或者模块里面,然后将它们混入。我有一次听到这样的说法:
    
    Any application with an app/concerns directory is concerning. 我同意,组合优于继承。但是,像这样使用混入就像是将混乱放到 6 个不同的抽屉然后关上它。确实,它表面上看去干净多了。但是垃圾抽屉的做法实际上使得它难以识别并且难以分解和提取业务模型。
    

    使用 Conerns 就是把一个大的 Model,抽出来,然后放入 Conerns,或者是把 Model 里的方法分类的放入不同的 Conerns 里,例如这样:

    class User < ActiveRecord::Base
      ...
      #Virtual Attributes
      def full_name
        [first_name, last_name].join(' ')
      end
    
      def full_name=(name)
        split = name.split(' ', 2)
        self.first_name = split.first
        self.last_name = split.last
      end
      ...
    end
    

    上面是一个 User 里的一个Virtual Attributes,我可以使用 Conerns,把Virtual Attributes挪出去。添加一个virtual_attributes.rb,到 Conerns 里:

    class User
      module VirtualAttributes
        extend ActiveSupport::Concern
    
        def full_name
          [first_name, last_name].join(' ')
        end
    
        def full_name=(name)
          split = name.split(' ', 2)
          self.first_name = split.first
          self.last_name = split.last
        end
      end
    end
    
    class User < ActiveRecord::Base
      include VirtualAttributes 
      ...
    end
    

    这样 Model 就瘦了一圈,当我要找 User 的 VirtualAttributes 时,到这个 Conerns 里找就可以了。一下方便了很多,也简洁了。Conerns 是非常通用的,所以我主要想讲一下我对 Services 用法的理解。


    把刚刚的 VirtualAttributes 里放到 Services 里,看怎么样?

    class UserVirtualAttributes
      def initialize(user)
        @user = user
      end
    
      def full_name
        [@user.first_name, @user.last_name].join(' ')
      end
    
       def full_name=(name)
         # 这个方法比较复杂,所以先不写
       end
    end
    

    调用:

    @user = User.find(params[:id])
    @user_full_name = UserVirtualAttributes.new(@user).full_name
    

    这个看起来貌似没有使用 Conerns 那么酷哦!当然,这种情况,就不适合使用 Services。那什么时候适合使用 Services?

    其实 Services 是一个面向对象的思想,Rails 把所有东西都放到 MVC 里,所以当我第一次接触 Rails 的时候,顿时觉得和我认识的面向对象有点不太一样。我说说我对面向对象的理解,举个人骑自行车的简单例子来说说我理解的面向对象。

    如果我要做一个人骑自行车的程序,至少要三个类,分别是:

    人(手、腿等),骑的动作(脚踩一次脚踏板 => 自行车运动范围),自行车(轮,脚踏板等)
    
    class People
      ...
      def right_left
        ...
      end
    end
    
    class Bike
      ...
      def right_pedal
        ...
      end
    end
    
    class RideBike
      ...
      def ride
        @people = People.new
        @bike = Bike.new
        ...
      end
    end
    

    大概意思这样子,感觉有点瞎扯,代码就不详细写下去了。主要要表达的意思就是,面向对象的思维就是把事物更合理的抽象出来的思想。

    所以上面的 full_name 属于 User 的属性,应该放倒 User 里,那是不是我们现在 User 里的所有方法都是正确的呢?如果从面向对象的思想来说,我们常用的密码校验,密码加密等事情,就是不应该放在 User 里的,而应该抽象出来放到Services中,如7种重构膨胀 ActiveRecord 模型的方法说的一个例子:

    class UserAuthenticator
      def initialize(user)
        @user = user
      end
    
      def authenticate(unencrypted_password)
        return false unless @user
    
        if BCrypt::Password.new(@user.password_digest) == unencrypted_password
          @user
        else
          false
        end
      end
    end
    

    调用方法:

    UserAuthenticator.new(user).authenticate(params[:password])
    

    而大部分教材和我们管用的做法是:

    class User < ActiveRecord::Base
      ...
      def authenticate(unencrypted_password)
        if BCrypt::Password.new(password_digest) == unencrypted_password
          self
        else
          false
        end
      end 
      ...
    end
    

    上面的案例我觉得是一个可以使用 Services 的情况。因为我觉得 UserAuthenticator 不属于 User 的时期。把 UserAuthenticator 放在 User 里,感觉就像:要判断一个人是否生病,还得用自己的方法。而我觉得正确的表达是:使用特定的Services,来检查这个人是否生病了


    我的观点是 Services 这个问题是非常复杂的,初建项目可以不需要考虑这么深层的问题。 我觉得 Services 最难使用的是如何保证团队里的思想一致性,情况就像如果我使用上面的UserAuthenticator,而团队里的人员觉得放在 User 里更合适,诸如此类的观点不一致的情况,会导致整个项目变得更凌乱,就针对这个问题,我没有想过有什么特别好的办法。 所以我还特别想了解,各个团队间应该怎么解决这样的问题比较好呢?

  • #3 楼 @Peter 其实用capistrano是不是做不到类似chef部署多台服务器?

  • 庆生电子书七折优惠 at 2014年04月01日

    赶在活动结束前入手了,翻译的质量不错,都入手了有。 今日入手了《Rails Guides》

    我想问问之前在淘宝买的《Ruby on Rails 教程》现在更新需要做什么操作呢?

  • 可惜啊,只在北京。😄

  • #1 楼 @rociiu 怎么选择用 concerns,还是 services?只使用 services 了?

  • 如果我没记错的话,client_side_validations不对 rails4 支持,并且不在更新了。

  • :thumbsup: :thumbsup: 👍 👍

  • #9 楼 @coolesting 这是一个有人脉觉得有技术重要,一个有技术觉得有人脉重要的年代。 除非做的是 zf 项目,不然我觉得最关键还是执行力吧。

  • IE 是什么?

  • 认真你就输了。

  • rubysl在这里起到什么作用?

  • @admin_articles = Admin::Article.all.page(params[:page]).per(5)
    
    在View中写入<%= paginate @admin_article %>
    

    因为你的<%= paginate @admin_article %>应该改成<%= paginate @admin_articles %>少了一个 s。

  • 一段 HTMLBars 的 slide at 2014年01月25日

    这玩意几时完成?

  • #25 楼 @cqcn1991 在这个模板里,migration 需要运行cap deploy:migrations,需要特点的 task 可以自己独立写一个的。

  • 用的js.erb的感觉就是:小项目还好,大项目那 js 简直是凌乱的不忍直视。

  • ["a", "b", "c", "d"].map.with_index.to_a
    
  • 日常口腔护理心得 at 2013年11月04日

    #31 楼 @mojidong 敏感牙或者是蛀牙,敏感牙用冷酸灵之类的一段时间会好,如果蛀牙就要补。

  • 以前我也遇见过这个问题,就是在 where 之前先做判断了。而且无论是只有一个数字也得放在[ ]里。

  • Ember Data 1.0 overview at 2013年10月30日

    #7 楼 @darkbaby123 更新 store 里的数据,就是这个 ajax 请求返回来的数据在 ED store 里的跟新一遍

  • passenger 一直都可以不中断部署所有一直用,但是很多人推 unicorn,还搞不懂原因。现在想试用 puma 看看。

  • rails 4.0 图片上传 at 2013年10月29日

    #2 楼 @hlt http://ruby-china.org/wiki/gems gem 'carrierwave'这个够用啦。

  • rails 4.0 图片上传 at 2013年10月29日

    gem 'carrierwave'

  • Ember Data 1.0 overview at 2013年10月28日

    #4 楼 @darkbaby123

    App.Order = DS.Model.extend
      ...
    
      editOrderDeliveryInfo: (params) ->
        self = this
        $.ajax(
          type: "PUT"
          url: "/api/orders/#{self.get('id')}/set_delivery_info"
          data:
            set_delivery_info:
              express_number: params["express_number"]
              delivery_total: params["delivery_total"]
              delivery_place_id: params["delivery_place"]
              express_info_id: params["express_info"]
              cost_total: params["cost_total"]
        ).then( ->
          self.reload()
        )
    

    现在来说,在 ember data 里面,我是这样写的,不知道怎么样的情况下需要对 ember data 添加新的特性。

  • Ember Data 1.0 overview at 2013年10月26日

    Cool

  • 这个是我目前看过最好的: https://github.com/artberri/sidr

  • 我的 Air 硬盘挂了. at 2013年10月18日

    苹果公司今日在其官网发布公告,在 2012 年 6 月到 2013 年 6 月期间出售的 MacBook Air 内置的 SSD 硬盘存在隐患,将召回存在问题的产品,免费更换内置硬盘。根据苹果官网的公告,将召回所有在 2012 年 6 月至 2013 年 6 月间出售、搭载 64/128GB 固态硬盘的 2012 款 Macbook Air 笔记本电脑,它们的固态硬盘很可能会发生故障,导致用户数据丢失。苹果公司在公告中建议所有 2012 款 Macbook Air 笔记本用户在 Mac App Store 中更新固态硬盘固件至 1.1 版,这个版本固件会检测你的硬盘是否存在问题,如果检测到硬盘存在问题,苹果强烈建议停止安装一切系统更新和应用程序,立刻前往苹果零售店或者授权维修店免费更换硬盘。更换硬盘后的 MacBook Air 保修日期不会延长。用户如果确认要更换硬盘,需要自行提前备份好数据,因为新硬盘只会安装一个全新的操作系统。如果有用户已经为此问题付费维修过 SSD 硬盘,可以联系苹果公司退还当时所付的全部维修款 (即维修硬盘的花费,而非整机款)。

  • #18 楼 @jasl 擦,这算保修范围内吗?

  • #20 楼 @cqcn1991 把 vps 部署的 id 的公钥和你电脑的公钥都加到 github ssh keys 里,就可以了。

  • 《小狗钱钱》