Rails 3 CanCan HTML 帮助程序

发布于 2024-12-15 17:55:50 字数 1064 浏览 3 评论 0原文

我正在使用标准 Rails HTML 助手

<%= form_for @person do |f| %>
 <%= f.label :first_name %>:
 <%= f.text_field :first_name %><br />
<%end%>

,但是假设如果当前用户无法编辑first_name,我想停用text_field。所以 CanCan 说我可以做到这一点

<%= f.text_field :name if can? :update, @person, :first_name %>

这很好,但我想以某种方式抽象它类似于:

<%= f.conditional_text_field :first_name %>

在这个例子中,我的自定义构建的 HTML 帮助程序知道我正在谈论一个 @person,因为它是在表单帮助程序中通过 f.object。我喜欢这个,因为可以集中控制不可编辑属性的重构处理。我可以选择显示禁用的输入框,或者可以渲染文本。如果没有别的事,如果 CanCan 发生变化、将来被某些东西取代,或者我想加入一些疯狂的工作流程,我有一个方便的钩子来更新授权。

  1. 这看起来是个好主意吗?

  2. 已经有这方面的 gem 了吗?


更新

我目前正在考虑添加一个助手,如下所示:

def can_text_field(f, field, *args)
  field = field.to_sym
  if can? :update, f.object, field
    return f.text_field field.to_sym *args
  else
    if can? :read, f.object, field
      return f.object.send(field)
    else
      return "Not Authorized"
    end
  end
end

I'm using stanard rails HTML helpers

<%= form_for @person do |f| %>
 <%= f.label :first_name %>:
 <%= f.text_field :first_name %><br />
<%end%>

But lets say I want to de-activate the text_field if if first_name is not editable by the current user. So CanCan says I can do this

<%= f.text_field :name if can? :update, @person, :first_name %>

This is fine and dandy, but I would like to abstract this somehow similar to:

<%= f.conditional_text_field :first_name %>

In this example, my custom built HTML helper knows I'm talking about a @person because the it is in the form helper via f.object. I like this because the re-factored handling of un-editable attributes can be centrally controlled. I could opt to display a disabled input box, or I could render the text. If nothing else I have a convenient hook to update authorization if CanCan changes, is replaced by something in the future, or I want to hook in some crazy workflow thing.

  1. Does this look like a good idea?

  2. Is there a gem for this already?


Update

I'm currently looking at adding a helper as follows:

def can_text_field(f, field, *args)
  field = field.to_sym
  if can? :update, f.object, field
    return f.text_field field.to_sym *args
  else
    if can? :read, f.object, field
      return f.object.send(field)
    else
      return "Not Authorized"
    end
  end
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吲‖鸣 2024-12-22 17:55:50

我去更新 FormHelper

class ActionView::Helpers::FormBuilder

  alias :original_text_field :text_field
  def text_field(method, options = {})
    if @@current_ability.cannot? :update, self.object, method.to_sym
      options[:disabled]="disabled"
    end
    self.original_text_field(method, options)
  end

  alias :origianl_collection_select :collection_select
  def collection_select(method, collection, id_method, display_method,
                        options={}, html_options={})
    if @@current_ability.cannot? :update, self.object, method.to_sym
      html_options[:disabled]="disabled"
    end
    self.original_collection_select(method, collection, id_method,
                                    display_method, options, html_options)
  end

  def self.set_current_ability(current_ability)
    @@current_ability = current_ability
  end

end

我必须添加一个控制器 before_filter 来加载具有 current_ability 的 FormBuilder

class ApplicationController < ActionController::Base
  before_filter :set_current_ability

  private

  def set_current_ability
    ActionView::Helpers::FormBuilder.set_current_ability( current_ability )
  end
end

I went with updating FormHelper

class ActionView::Helpers::FormBuilder

  alias :original_text_field :text_field
  def text_field(method, options = {})
    if @@current_ability.cannot? :update, self.object, method.to_sym
      options[:disabled]="disabled"
    end
    self.original_text_field(method, options)
  end

  alias :origianl_collection_select :collection_select
  def collection_select(method, collection, id_method, display_method,
                        options={}, html_options={})
    if @@current_ability.cannot? :update, self.object, method.to_sym
      html_options[:disabled]="disabled"
    end
    self.original_collection_select(method, collection, id_method,
                                    display_method, options, html_options)
  end

  def self.set_current_ability(current_ability)
    @@current_ability = current_ability
  end

end

I had to add a controller before_filter to load the FormBuilder with current_ability

class ApplicationController < ActionController::Base
  before_filter :set_current_ability

  private

  def set_current_ability
    ActionView::Helpers::FormBuilder.set_current_ability( current_ability )
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文