作为优化的一部分,我们不会将整个 User
存储在 session 中,而是将 User
包装在仅包含基本属性的外观中,例如 id
、username
和 admin?
。其他任何东西都是延迟加载的(使用 method_missing
)。当此对象写入 session 时,它会在编码之前卸载用户。
基本上:
class UserProxy
attr_reader :id
attr_reader :username
def initialize(user)
@user = user
reload_attributes!
end
def admin?
@admin
end
def self.model_name
User.model_name
end
def method_missing(meth, *args, &block)
@user ||= User.get!(id)
@user.send(meth, *args, &block)
ensure
reload_attributes! # seems as good a place as any to keep the data fresh
end
def unset_user!
@user = nil
self
end
def ==(*args, &block)
method_missing('==', *args, &block)
end
def !=(*args, &block)
method_missing('!=', *args, &block)
end
def self._load(data) # custom unmarshalling logic
UserProxy.new(ActiveSupport::JSON.decode(data)).unset_user!
end
def _dump(depth) # custom marshalling logic
reload_attributes!
ActiveSupport::JSON.encode({"id" => id, "username" => username, "admin" => admin})
end
private
def reload_attributes!
return if @user.nil?
@id = @user["id"]
@username = @user["username"]
@admin = @user["admin"]
end
end
这在任何地方都很好用(它的行为就像它包装的 DataMapper 用户一样,我们不必访问数据库来获取大多数页面请求的用户,因为重要的位( key 和用户名)已经加载。
Rails 创建的路径助手不适合它。
<%= url_for(@user) # should be /users/1234 %>
最初它会严重出错,因为它无法弄清楚 model_name
是什么,所以我通过将类方法 model_name
添加到我的 UserProxy 来解决这个问题
类并返回 User.model_name
,它现在找到了正确的路由,但是代替了用户 ID,它放置了:
<a href="/users/%23%3CUserProxy:0xa4449cc%3E">Chris Corbyn</a>
我不确定到哪里去解决这个问题。我已在 method_missing 中进行调试调用以查看正在调用的内容,但它甚至没有收到对 to_param
的调用,正如我所期望的那样。
最佳答案
我不敢相信我没有尝试过这个。我刚刚将 to_param
添加到代理并将调用委托(delegate)给用户对象并且它起作用了。我没有意识到 Rails 中的所有对象都有一个 to_param
方法,模型与否。那么我应该为 to_key
做同样的事情!
关于ruby-on-rails - 资源路径如何工作(内部)?我需要修复的不良行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6073774/