【问题标题】:rails don't find the attributerails 找不到属性
【发布时间】:2011-07-12 15:30:40
【问题描述】:

我有这个模型

#post.rb
class Post < ActiveRecord::Base
    belongs_to :user
    after_initialize :create_token
    attr_accessible :token
    protected
    def create_token
      self.token = "#{Digest::MD5.hexdigest("#{self.id}")[0,4]}"
    end 
end

rails c

Post.find(:all,:conditions => { :user_id => 11})
 => [#<Post id: 26, content: "<p><strong>Yao Ming</strong> (<a shape=\"rect\" title...", user_id: 11, created_at: "2011-07-12 15:08:30", updated_at: "2011-07-12 15:08:30", title: "Yao Ming", guid: "0010f6c3-040b-4e13-aa38-3a002e6f2022", contentHash: "\xB9\\\xCBK\xB0A>4\xC4~\xFC\"\xEA7\xA6y", token: "4e73">]

token: "4e73",但是当我尝试

Post.find(:all,:conditions => { :user_id => 11, :token => "4e73"}) 
 => []

我收到[],为什么?

更多信息

Post.find(:all,:conditions => { :user_id => 11}).first.token.class
=> String 

Post.find(:all,:conditions => { :user_id => 11}).first.token
=> "3769" 

【问题讨论】:

  • Post.find(:all,:conditions =&gt; { :token =&gt; "4e73"}) 你能得到什么
  • Post.find(:all,:conditions => { :token => "4e73"}) => []
  • 还有Post.find(:all,:conditions =&gt; { :user_id =&gt; 11}).first.token.class?
  • Post.find(:all,:conditions => { :user_id => 11}).first.token.class => String

标签: ruby-on-rails ruby-on-rails-3 rails-models


【解决方案1】:

根据 Rails 指南:

只要有 Active Record,就会调用 after_initialize 回调 通过直接使用 new 或在记录时实例化对象 从数据库中加载。

您可能应该找到另一种方法来初始化此“令牌”字段,否则每次从数据库重新加载记录时它都会更改。

【讨论】:

    【解决方案2】:

    好吧,要基于id 构建属性,id 必须存在。最后,这样做:

    after_create :create_token
    
    def create_token
      self.token = "#{Digest::MD5.hexdigest("#{self.id}")[0,4]}"
      self.save
    end
    

    【讨论】:

    • 是的,主要问题是在原始代码中,令牌从未保存到数据库中。
    • @Alex - Aotea Studios:我不明白你的评论
    • 我只是同意你的回答。据我所知,问题中的代码初始化了令牌但从不保存它,这就是find 不起作用的原因。
    • 嗯,它是在 before_save 之前用不同的方式初始化的,所以它有点隐含。但是是的,没有例子
    【解决方案3】:

    正如 Eugen 所说,这就是问题所在,在所有情况下 Rails 都没有本地方法可以做到这一点,所以你必须做的是:

    class Post < ActiveRecord::Base
        belongs_to :user
        after_initialize :create_token
        attr_accessible :token
        protected
        def create_token
            if new?
              self.token = "#{Digest::MD5.hexdigest("#{self.id}")[0,4]}"
            end
        end 
    end
    

    或者干脆

    class Post < ActiveRecord::Base
        belongs_to :user
        attr_accessible :token
        protected
        def after_initialize
            if new?
              self.token = "#{Digest::MD5.hexdigest("#{self.id}")[0,4]}"
            end
        end 
    end
    

    【讨论】:

    • 编辑 after_initialize 回调,您可以在代码中像 create_token 函数一样使用它
    【解决方案4】:

    我会用

    before_create :create_token
    

    所以它只在记录第一次插入数据库时​​生成。

    【讨论】:

    • 与 before_create 任何 post.token 被称为相等
    • 对。我错过了您基于 self.id 创建令牌。更改您的令牌生成器以使用标题加上内容加上时间来生成唯一的 md5 令牌,而不仅仅是 id。我看到有些人建议使用 after_create 但我不喜欢这样做只是因为您最终使用 INSERT 来创建记录,然后 UPDATE 设置令牌。使用 before_create,您只需要 INSERT。恕我直言,任何可以最小化数据库访问的事情都是一件好事。
    猜你喜欢
    • 1970-01-01
    • 2018-05-06
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多