使用设计和响应_with Rails 3 中的 attr_accessible
我正在使用 Rails 3 构建一个 API,使用 devise 来处理一些身份验证。
我通常使用 respond_with 方法返回各种资源的 xml/json。
例如 GET /groups.xml 将路由到
def index
respond_with Group.all
end
This 在我的站点上对各种资源运行良好,并返回格式良好的 json 或 xml,其中包含每个组的所有属性。
但是,当我调用 GET /users.xml 时,它仅响应每个用户属性的有限子集。事实证明,这里只会返回 attr_assessible 中定义的属性 - 我怀疑这是 devise 的一个“功能”,因为任何其他模型都不是这种情况。
谁能启发我吗?
编辑:这在 Devise 1.4.2 中已得到修复。详情请参阅下文
I'm building an API with Rails 3, using devise to handle some of the authentication.
I commonly use the respond_with method to return xml/json for various resources.
Eg GET /groups.xml will route to
def index
respond_with Group.all
end
This works fine across my site for various resources, and returns nicely formatted json or xml containing all the attributes of each group.
However, when I call GET /users.xml, it only responds with a limited subset of the each user's attributes. It turns out that only attributes defined in attr_assessible will be returned here - I suspect this is a "feature" of devise, because it's not the case for any other model.
Can anyone enlighten me?
Edit: This is sort of fixed in Devise 1.4.2. See below for details
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的怀疑正确。 Devise Authenticatable 模块覆盖 #to_xml 和 #to_json 首先检查类是否响应 #accessible_attributes 方法,如果响应则输出仅限于#accessible_attributes 返回的那些属性。来自authencatable.rb 的代码位于此处:
您会注意到此代码将#accessible_attributes 的结果合并到任何传入的选项中。因此,您可以指定 :only 选项,例如:
这将覆盖 Devise 施加的限制并生成仅包含您指定的字段的 xml 输出。您将需要包含您想要公开的每个字段,因为一旦您使用 :only 您将胜过正常操作。
在这种情况下,我认为您无法继续在控制器中使用 respond_with 快捷方式,因为您需要直接指定 xml 输出。您可能不得不退回到老式的 respond_to 块:
正如您已经发现的那样,您也可以仅添加您想要通过 attr_accessible 公开的其他字段模型类。但是,这会产生额外的副作用,使这些字段可批量分配,并且在这种情况下您可能不一定希望这样做。
Your suspicion is correct. The Devise Authenticatable module overrides #to_xml and #to_json to first check if the class responds to the #accessible_attributes method, and if it does then output is restricted to only those attributes returned by #accessible_attributes. The code from authenticatable.rb is here:
You'll notice that this code merges the result of #accessible_attributes into any passed-in options. As such, you can specify an :only option, such as:
This will override the Devise-imposed restriction and produce xml output that includes only the fields you specify. You will need to include every field you want exposed, since once you use :only you'll trump the normal operation.
I don't think you'll be able to continue to use the respond_with shortcut in your controller in this case, because you'll need to specify the xml output directly. You'll probably have to fall back to an old-school respond_to block:
As you already discovered, you could also just add the additional fields you want exposed via attr_accessible in the model class. However, this will have the added side-effect of making these fields mass-assignable and you may not necessarily want that in this situation.
Devise 的旧版本 (<1.4.2) 对 to_json 和 to_xml 方法执行了 Monkeypatch,覆盖了 :only =>; [] 选项以及 attr_accessible 中定义的属性。恼人的。
现在这已被更改,因此serialized_hash 被覆盖,并且任何 :only =>; to_json 或 to_xml 中设置的 [:attribute] 选项将被保留。
就我而言,我最终自己对 to_json 进行了猴子修补,并向所有 ActiveRecord 模型添加了 api_accessible 方法。
这意味着您现在可以定义在调用 to_json 时默认公开的属性(和方法!)列表。 Respond_with 还使用 to_json,因此它非常适合 API。
例如,user.rb
Older versions ( < 1.4.2) of Devise performed a monkeypatch on the to_json and to_xml methods, overwriting the :only => [] option with the attributes defined in attr_accessible. Annoying.
This has now been changed, so that serializable_hash is overwritten instead, and any :only => [:attribute] options set in to_json or to_xml are persisted.
In my case, I ended up monkeypatching to_json myself, and adding a method api_accessible to all ActiveRecord models.
This means that you can now define a list of attributes (and methods!) that will be exposed by default when calling to_json. Respond_with also uses to_json, so it works well for APIs.
Eg, user.rb