<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>limkurn (林坤)</title>
    <link>https://ruby-china.org/limkurn</link>
    <description>时间在推着你前进，不管你愿不愿意～。～</description>
    <language>en-us</language>
    <item>
      <title>推送相关的一些整理</title>
      <description>&lt;h2 id="推送相关"&gt;推送相关&lt;/h2&gt;
&lt;p&gt;blog： &lt;a href="https://limkurn.gitbooks.io/limkurn-blog/content/%E7%AC%AC%E4%B9%9D%E7%AB%A0-push.html" rel="nofollow" target="_blank"&gt;https://limkurn.gitbooks.io/limkurn-blog/content/%E7%AC%AC%E4%B9%9D%E7%AB%A0-push.html&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="前言"&gt;前言&lt;/h3&gt;
&lt;p&gt;在现在主要负责的项目中，推送刚开始使用的是极光推送，不过后面在 app 版本 3.2 左右换到了友盟，同时根据客户端的策略封装一些 api。但是本身没有做什么深究。最近又兼顾着做一个公司的小项目，正好做到推送这块。所以查阅一些资料 blog 整理了下，权当抛砖引玉。&lt;/p&gt;
&lt;h3 id="推送平台选择"&gt;推送平台选择&lt;/h3&gt;
&lt;p&gt;如果是小公司，貌似没有人想着自己去搭一个推送平台，主要还是用第三方平台。我们主要的项目原来使用极光，不过在我接手项目的时候，这个推送基本上是废的（没有用起来）。后面处于客户端的偏好，以及一些统计方面的需求换到友盟。昨天还接受到甲方需求，看到竞品在使用个推，可能会对接个推。我搜了下 ruby china 上有&lt;a href="http://ruby-china.org/topics/20786" title=""&gt;帖子&lt;/a&gt;讨论的，给选择推送平台有一些建议，帮助你去除一些不靠谱的平台。&lt;/p&gt;
&lt;h3 id="一些需要知道"&gt;一些需要知道&lt;/h3&gt;&lt;h4 id="ios推送实现"&gt;ios 推送实现&lt;/h4&gt;
&lt;p&gt;苹果自身承担了更多，拥有 APNS 服务以及其特殊的后台机制，在实现 ios 端推送的时候，可以自己去看文档封转 api，也可以直接使用第三方封好 (因为集成了第三方 sdk，我们项目是这样的).大致原理图：&lt;/p&gt;

&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/38542/2011060310283569.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/38542/2011060313352593.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;(引用自：&lt;a href="http://blog.csdn.net/dongdongdongjl/article/details/8452211" rel="nofollow" target="_blank"&gt;http://blog.csdn.net/dongdongdongjl/article/details/8452211&lt;/a&gt; 可以看看)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="android推送实现"&gt;android 推送实现&lt;/h4&gt;
&lt;p&gt;对于 android 的推送，google 也有一个类似于 APNS 的 GCM（google cloud messaging）.但是在国内大家也就懂了。所以就要对安卓特殊处理了。对于安卓推送的实现机制和解决方案可以看看&lt;a href="http://www.cnblogs.com/hanyonglu/archive/2012/03/04/2378971.html" rel="nofollow" target="_blank" title=""&gt;这篇 blog&lt;/a&gt;，虽然是 2012 年的貌似并没有过时，其中归纳了常见解决方案的实现原理：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SMS(Push) 方式&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;轮询 (Pull) 方式&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;持久连接 (Push) 方式&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;sms 和轮询很容易被 kill 掉，国内推送产品大致的做法是在后台保持一个心跳服务不断维持 Client 与 Server 的 TCP 长连接来实现实时推送，看了下&lt;a href="https://segmentfault.com/a/1190000002654918" rel="nofollow" target="_blank" title=""&gt;个推的实现原理介绍&lt;/a&gt;就是使用的长连接。如果自己实现的话考虑的因素貌似比较多，例如如何保持不被回收，还要打点好一些软件加入白名单中（上次 keep 的全能神大人说有个白名单没处理好，缓存的视频文件就被删除了，虽然与推送无关，但还是得考虑）。还有一个各个 app 用的策略不一样，你开一个，我开一个服务，就会掉电比较厉害，如果体贴用户的话，考虑方案的时候也要考虑下这个。知乎上有个关于关于&lt;a href="https://www.zhihu.com/question/31828136" rel="nofollow" target="_blank" title=""&gt;安卓推送的回答&lt;/a&gt;最高票的那个（虽然票不多）蛮有意思可以看看。&lt;/p&gt;
&lt;h3 id="关于device token（安卓以友盟为例）"&gt;关于 device token（安卓以友盟为例）&lt;/h3&gt;&lt;h4 id="ios device token"&gt;ios device token&lt;/h4&gt;
&lt;p&gt;iOS 的 device token 原理可以看看上面一节 ios 推送实现的第二个图，或者查看&lt;a href="https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html" rel="nofollow" target="_blank" title=""&gt;官方文档&lt;/a&gt;，有详细的图文介绍 &lt;/p&gt;
&lt;h4 id="android device token"&gt;android device token&lt;/h4&gt;
&lt;p&gt;安卓使用友盟的时候 使用的是友盟自己的机制（友盟 id 和阿里巴巴集团统一的设备标识库的 id）结合起来 生成友盟对用户的唯一标识（但是没有一种算法能一定保证唯一 只能尽可能保证唯一）,然后：SDK 在初始化的时候向服务器端发起注册请求，由服务器端生成之后颁发给客户端的。&lt;/p&gt;
&lt;h4 id="什么时候device token 改变"&gt;什么时候 device token 改变&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;这是一个很需要注意的东西 后面推送依赖 device token 的时候，自己保存的用户的 device token 要保证有效，如果改变了要及时更新。ios 的我看到&lt;a href="http://www.mednoter.com/device-token.html" rel="nofollow" target="_blank" title=""&gt;小荣的 blog&lt;/a&gt; 以及他在帖子中参考的这个这个&lt;a href="http://stackoverflow.com/questions/6652242/does-the-apns-device-token-ever-change-once-created/7999690#7999690" rel="nofollow" target="_blank" title=""&gt;问题&lt;/a&gt;有一些很有用的信息，大致总结：1. 抹除了设备数据 2. 重装应用，3. 时间太长 token 过期 这几种情况 token 发生改变； &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;同样安卓的友盟官方自己给了&lt;a href="http://bbs.umeng.com/thread-11061-1-1.html" rel="nofollow" target="_blank" title=""&gt;详细的解释&lt;/a&gt; 一般是 设备重载  或者 另一种是没有 SD 卡 设备 id 改变。如果依赖 device token 我能想到的是在登陆和注册的时候带上设备信息以及 device token 信息 server 端保存或者更新用户的设备信息以及保持 device token 是最新有效的。即使重装 app 的时候用户登陆也可以刷新 token 和设备信息便于推送。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="两种推送策略（友盟）"&gt;两种推送策略（友盟）&lt;/h3&gt;
&lt;p&gt;我目前之见到过两种策略，如果有什么更好的策略，期望分享下&lt;/p&gt;
&lt;h4 id="依赖device token"&gt;依赖 device token&lt;/h4&gt;
&lt;p&gt;依赖 device token 的方案数据库保存用户的设备信息（ios 或 android）还有版本信息 app 以及最新的 device token，这样后面建立任务直接使用保存的 token，按照设备平台调用对应的第三方平台 api。这样的话还可以分平台  分组 分 app 版本分组去推。但是 app 不是设计为单点登陆的话，是否推送到多个设备需要根据业务和需求做对应的支持。如果是单点登陆的话，推送应该可以很好运作了。&lt;/p&gt;
&lt;h4 id="依赖alias 以及 alias type（不确定是不是友盟独有 其他第三方平台文档没看过）"&gt;依赖 alias 以及 alias type（不确定是不是友盟独有 其他第三方平台文档没看过）&lt;/h4&gt;
&lt;p&gt;依赖 alias 和 alias type 的方案就比较偷懒，比较适用于只需要 推单个用户 而且保存多设备推送到达的情况 以及全局推，由于没有维护 device token 等设备 版本信息。分组啊 分平台 分版本推送的需求就不能满足，短板还是很明显的。自己的产品就不要采用这种方式了。关于 alias 可以看看&lt;a href="http://zhidao.baidu.com/link?url=KU9h8KCCz-mcvlyvuypbRxr6qsoFgE-uijwF7HGTqCZ-GBYwxomy9lCCCy2zMju1V3xRKrQ4QaGyUEq84FYyxM4qLV75CMkRI73-brivSF_" rel="nofollow" target="_blank" title=""&gt;这个回答，虽然是百度里的&lt;/a&gt;&lt;/p&gt;
&lt;h4 id="device token + （alias + alias type）"&gt;device token + (alias + alias type)&lt;/h4&gt;
&lt;p&gt;将两者结合起来的方案 应该比较合适 能支持的功能更多，但是如果在分组推送等用 device token 要保证多设备都要受到推送的话，还是需要在保存用户 device token 的时候 还是需要想想额外的方案来做支持。只保持最新的 device token，只能保证用户推送到用户最近登陆的设备。&lt;/p&gt;
&lt;h3 id="后记"&gt;后记&lt;/h3&gt;
&lt;p&gt;经验有限，如果有更多，更好的方案和经验分享的，希望不吝分享。&lt;/p&gt;</description>
      <author>limkurn</author>
      <pubDate>Tue, 26 Jul 2016 17:06:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/30626</link>
      <guid>https://ruby-china.org/topics/30626</guid>
    </item>
    <item>
      <title>话说有没好一点的计算机词汇一类的书</title>
      <description>&lt;p&gt;每次看到不认识的都查然后再是不是收录两个感觉不靠谱。想问问有没有像四级红包书那类的计算机词汇书。我在亚马逊上搜评论很多都说有点旧。&lt;/p&gt;</description>
      <author>limkurn</author>
      <pubDate>Sat, 18 May 2013 01:16:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/11075</link>
      <guid>https://ruby-china.org/topics/11075</guid>
    </item>
    <item>
      <title>经如主页时出现多重重定向，如何排查</title>
      <description>&lt;p&gt;我在&lt;code&gt;rake routes&lt;/code&gt;后结果如下&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; root        /                                                projects#index
        new_user_session GET    /users/sign_in&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                         devise/sessions#new
            user_session POST   /users/sign_in&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                         devise/sessions#create
    destroy_user_session DELETE /users/sign_out&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                        devise/sessions#destroy
           user_password POST   /users/password&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                        devise/passwords#create
       new_user_password GET    /users/password/new&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                    devise/passwords#new
      edit_user_password GET    /users/password/edit&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                   devise/passwords#edit
                         PUT    /users/password&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                        devise/passwords#update
cancel_user_registration GET    /users/cancel&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                          devise/registrations#cancel
       user_registration POST   /users&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                 devise/registrations#create
   new_user_registration GET    /users/sign_up&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                         devise/registrations#new
  edit_user_registration GET    /users/edit&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                            devise/registrations#edit
                         PUT    /users&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                 devise/registrations#update
                         DELETE /users&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                 devise/registrations#destroy
              admin_root        /admin&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                                 admin/base#index
             admin_users GET    /admin/users&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                           admin/users#index
                         POST   /admin/users&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                           admin/users#create
          new_admin_user GET    /admin/users/new&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                       admin/users#new
         edit_admin_user GET    /admin/users/:id/edit&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                  admin/users#edit
              admin_user GET    /admin/users/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                       admin/users#show
                         PUT    /admin/users/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                       admin/users#update
                         DELETE /admin/users/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                       admin/users#destroy
       admin_permissions GET    /admin/permissions&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                     admin/permissions#index
                         POST   /admin/permissions&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                     admin/permissions#create
    new_admin_permission GET    /admin/permissions/new&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                 admin/permissions#new
   edit_admin_permission GET    /admin/permissions/:id/edit&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;            admin/permissions#edit
        admin_permission GET    /admin/permissions/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                 admin/permissions#show
                         PUT    /admin/permissions/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                 admin/permissions#update
                         DELETE /admin/permissions/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                 admin/permissions#destroy
            confirm_user GET    /awaiting_confirmation&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                 &lt;span class="nb"&gt;users&lt;/span&gt;&lt;span class="c"&gt;#confirmation&lt;/span&gt;
 update_user_permissions PUT    /admin/user/:user_id/permissions&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;       admin/permissions#update
         project_tickets GET    /projects/:project_id/tickets&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;          tickets#index
                         POST   /projects/:project_id/tickets&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;          tickets#create
      new_project_ticket GET    /projects/:project_id/tickets/new&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;      tickets#new
     edit_project_ticket GET    /projects/:project_id/tickets/:id/edit&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt; tickets#edit
          project_ticket GET    /projects/:project_id/tickets/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;      tickets#show
                         PUT    /projects/:project_id/tickets/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;      tickets#update
                         DELETE /projects/:project_id/tickets/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;      tickets#destroy
                projects GET    /projects&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                              projects#index
                         POST   /projects&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                              projects#create
             new_project GET    /projects/new&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                          projects#new
            edit_project GET    /projects/:id/edit&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                     projects#edit
                 project GET    /projects/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                          projects#show
                         PUT    /projects/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                          projects#update
                         DELETE /projects/:id&lt;span class="o"&gt;(&lt;/span&gt;.:format&lt;span class="o"&gt;)&lt;/span&gt;                          projects#destroy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果显示主页不是&lt;code&gt;projects#index&lt;/code&gt;
怎么会出现&lt;code&gt;http://localhost:3000/ 的网页生成了 过多的重定向。清除此网站的 Cookie 或允许第三方 Cookie 可能会解决该问题。如果 不能解决，可能是服务器配置有问题，而不是您的 计算机有问题。&lt;/code&gt;&lt;/p&gt;</description>
      <author>limkurn</author>
      <pubDate>Sun, 14 Apr 2013 12:08:40 +0800</pubDate>
      <link>https://ruby-china.org/topics/10179</link>
      <guid>https://ruby-china.org/topics/10179</guid>
    </item>
    <item>
      <title>关于 helper 里定义的方法的引用问题。</title>
      <description>&lt;p&gt;我在 sessions_helper.rb 中定义了一方法：signed_in?&lt;br&gt;
然后我在 users_controller.rb 里中的定义的一个方法中引用了这个方法。但是运行是显示 nomethoderror。所以想问下如何使这种引用有效，是否需要 require？&lt;/p&gt;</description>
      <author>limkurn</author>
      <pubDate>Wed, 30 Jan 2013 18:35:23 +0800</pubDate>
      <link>https://ruby-china.org/topics/8494</link>
      <guid>https://ruby-china.org/topics/8494</guid>
    </item>
    <item>
      <title>使用 gravatar_image_tag 图片怎么命名？</title>
      <description>&lt;p&gt;我在 app/assets/images 把图片命名为 xxx@xxx.com.jpg  xxx@xx.com xxx@xxx.con.png 页面加载的还是默认的图像。该怎么命名才行？&lt;/p&gt;</description>
      <author>limkurn</author>
      <pubDate>Sat, 26 Jan 2013 17:33:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/8386</link>
      <guid>https://ruby-china.org/topics/8386</guid>
    </item>
    <item>
      <title>unknown attribute: cart_id  错误</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;  
   &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cart&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
   &lt;span class="n"&gt;attr_accessible&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt;

    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:line_items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;dependent: :destroy&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
 &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

  &lt;span class="n"&gt;default_scope&lt;/span&gt; &lt;span class="ss"&gt;:order&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;


  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:line_items&lt;/span&gt; 
  &lt;span class="n"&gt;before_destroy&lt;/span&gt; &lt;span class="ss"&gt;:ensure_not_referenced_by_any_line_item&lt;/span&gt;
  &lt;span class="n"&gt;attr_accessible&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:image_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;


  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:image_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:presence&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:numericality&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:greater_than_or_equal_to&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:uniqueness&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:image_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:format&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;:with&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;%r{&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;(gif|jpg|png)$}i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="ss"&gt;:message&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'must be a url for GIF ,JPG OR PNG image_url'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kp"&gt;private&lt;/span&gt; 

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ensure_not_referenced_by_any_line_item&lt;/span&gt;
       &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt; 
        &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:base&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'line items present'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;          
        &lt;span class="k"&gt;end&lt;/span&gt;    
    &lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="n"&gt;line_item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
 &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LineItem&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;attr_accessible&lt;/span&gt;  &lt;span class="ss"&gt;:cart_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:quantity&lt;/span&gt;


  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:Product&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:cart&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;



&lt;span class="n"&gt;controller&lt;/span&gt;

 &lt;span class="n"&gt;line_item_controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt; &lt;span class="n"&gt;中的creat方法&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
   &lt;span class="vi"&gt;@cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_cart&lt;/span&gt;
   &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="no"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:product_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="vi"&gt;@line_item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@cart.line_items.build&lt;/span&gt;                     &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;这儿是第45行&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@line_item.product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;

   &lt;span class="n"&gt;respond_to&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@line_item.save&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;redirect_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@line_item.cart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;:notice&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="s1"&gt;'line item was successfully created.'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xml&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:xml&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@line_item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;:status&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:created&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:location&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@line_item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:action&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xml&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:xml&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vi"&gt;@line_item.errors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;:status&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:unprocessable_entity&lt;/span&gt;&lt;span class="p"&gt;}&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;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行是出现 ActiveRecord::UnknownAttributeError in LineItemsController#create&lt;/p&gt;

&lt;p&gt;unknown attribute: cart_id
app/controllers/line_items_controller.rb:45:in `create'&lt;/p&gt;

&lt;p&gt;我 google 了下  还是每搞懂哪儿错了。&lt;/p&gt;</description>
      <author>limkurn</author>
      <pubDate>Thu, 01 Nov 2012 13:23:19 +0800</pubDate>
      <link>https://ruby-china.org/topics/6454</link>
      <guid>https://ruby-china.org/topics/6454</guid>
    </item>
    <item>
      <title>跟着敏捷开发那本书敲的时候 出现个出错，看提示也没搞懂求教</title>
      <description>&lt;p&gt;ActiveModel::MassAssignmentSecurity::Error in LineItemsController#create&lt;/p&gt;

&lt;p&gt;Can't mass-assign protected attributes: product
Rails.root: /home/lim/work/depot&lt;/p&gt;

&lt;p&gt;Application Trace | Framework Trace | Full Trace
app/controllers/line_items_controller.rb:45:in `create'&lt;/p&gt;

&lt;p&gt;create 方法代码如下
def create
   &lt;a href="/cart" class="user-mention" title="@cart"&gt;&lt;i&gt;@&lt;/i&gt;cart&lt;/a&gt; = current_cart
   product=Product.find(params[:product_id])
   &lt;a href="/line_item" class="user-mention" title="@line_item"&gt;&lt;i&gt;@&lt;/i&gt;line_item&lt;/a&gt; = &lt;a href="/cart.line_items.buil" class="user-mention" title="@cart.line_items.buil"&gt;&lt;i&gt;@&lt;/i&gt;cart.line_items.buil&lt;/a&gt;d(:product =&amp;gt; product)&lt;/p&gt;

&lt;p&gt;respond_to do |format|
    if &lt;a href="/line_item.save" class="user-mention" title="@line_item.save"&gt;&lt;i&gt;@&lt;/i&gt;line_item.save&lt;/a&gt;
      format.html  { redirect_to(&lt;a href="/line_item.cart" class="user-mention" title="@line_item.cart"&gt;&lt;i&gt;@&lt;/i&gt;line_item.cart&lt;/a&gt;,
        :notice =&amp;gt;  'line item was successfully created.')}
      format.xml {render :xml =&amp;gt; &lt;a href="/line_item" class="user-mention" title="@line_item"&gt;&lt;i&gt;@&lt;/i&gt;line_item&lt;/a&gt;,
        :status =&amp;gt; :created ,:location =&amp;gt; &lt;a href="/line_item" class="user-mention" title="@line_item"&gt;&lt;i&gt;@&lt;/i&gt;line_item&lt;/a&gt;}
    else
      format.html {render :action =&amp;gt; "new"}
      format.xml {render :xml =&amp;gt; &lt;a href="/line_item.errors" class="user-mention" title="@line_item.errors"&gt;&lt;i&gt;@&lt;/i&gt;line_item.errors&lt;/a&gt;,
        :status =&amp;gt; :unprocessable_entity}
      end
    end
  end&lt;/p&gt;</description>
      <author>limkurn</author>
      <pubDate>Fri, 19 Oct 2012 10:10:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/6171</link>
      <guid>https://ruby-china.org/topics/6171</guid>
    </item>
  </channel>
</rss>
