允许用户仅编辑Ruby on Rails上的一些字段

时间:2011-02-17 14:13:54

标签: ruby-on-rails

如何实现用户只能编辑记录中的某些字段?

例如:

用户可以在系统上注册并选择并指定用户名,密码等。但注册用户只能编辑他的姓名,电子邮件和密码,而不能编辑他的用户名。

我有一个部分_form,用于新功能和编辑功能。 部分看起来像这样:

    <% form_for @user do |f| %>
    <%= f.error_messages %>
    <p>
            <%= f.label :gruebl_employee_id %><br />
            <%= f.collection_select(:firma_employee_id, FirmaEmployee.find(:all).sort_by{|p| p.lastname.downcase},:id,:full_name, {  :include_blank => "---keine Mitarbeiter---", :prompt => "---Bitte auswählen---"}, { :style => "width: 332px;"}) %>
        </p>
         <%= observe_field(:user_firma_employee_id,
         :frequency => 0.25,
         :url => { :action => :retrieveinfo },
         :with => "'id='+value") %>

        <p>
          <%= f.label :username %><br />
          <%= f.text_field :username %>
        </p>

         <p>
          <%= f.label :admin, "Administrator ?" %><br />
          <%= f.check_box :admin %>
        </p>

        <p>
          <%= f.label :email %><br />
          <%= f.text_field :email %>
        </p>
        <p>
          <%= f.label :password %><br />
          <%= f.password_field :password %>
        </p>
        <p>
          <%= f.label :password_confirmation %><br />
          <%= f.password_field :password_confirmation %>
        </p>
        <p><%= f.submit %></p>
<%end%>

我要做的是阻止用户更改员工和用户名属性。

提前致谢。

4 个答案:

答案 0 :(得分:9)

在几个地方照顾好这个。

首先,在User模型中使用attr_accessible,仅包含您希望用户编辑的那些:

attr_accessible :name, :email, :password, :password_confirmation #...

然后在形式partial中,仅在显示注册表单时显示用户名字段:

<% if @user.new_record? %>
  <%= f.text_field :username %>
<% end %>

最后,在创建操作中,手动设置用户名字段,因为它现在位于attr_accessible列表中,您无法批量分配它:

@user = User.new(params[:user])
@user.username = params[:user][:username]

请注意,如果可以通过批量分配设置用户名,即使您在表单中禁用了用户名字段,它仍然可以修改(很容易在客户端更改表单中的字段值) 。这就是我们必须使用attr_accessible进行预检的原因。

编辑:注意到你的部分,最好将admin字段保护为用户名,否则用户可以通过更改客户端的字段值将自己设置为admin。

答案 1 :(得分:0)

我可以看到你有两种方法可以做到这一点。

1 - 使用html支持使文本框只读。所以在你的情况下,user_name文本框将是这样的

<input type="text" name="user_name" value="<User Name>" readonly="readonly" />

2 - 但我更喜欢在rails应用程序中创建一个只读文本框,帮助者可以在需要时调用它

所以示例是

在我的应用程序助手

module ApplicationHelper

    def read_only_text_field(object_name, method, options = {})
          text_field(object_name, method, :disabled => true)
    end
end

在我看来我有

<%= read_only_text_field :user, :user_name %>

我认为它更干旱/铁路。

**重要 - 并确保在保存等时从控制器中计算只读值。通过这种方式,即使用户更改这些只读值,您仍然无法解决问题:D

希望这会有所帮助

欢呼声

sameera

答案 2 :(得分:0)

诀窍是将“对象”与标签结合使用,以用于您不想更改的任何内容。以下是您应该如何为用户名编写代码:

<%= f.label(:username, f.object.username) %>

答案 3 :(得分:0)

这是我针对类似问题的相关解决方案-我们有一些字段,希望用户能够设置自己,我们在创建记录时不需要它们,但是我们不希望一旦更改它们就可以对其进行更改已设置。

  validate :forbid_changing_some_field, on: :update

  def forbid_changing_some_field
    return unless some_field_changed?
    return if some_field_was.nil?

    self.some_field = some_field_was
    errors.add(:some_field, 'can not be changed!')
  end

让我惊讶的是update_attribute仍然有效,它绕过了验证。没什么大不了的,因为实际上对记录的更新是批量分配的-但我在测试中对此进行了明确说明。这是一些测试。

    describe 'forbids changing some field once set' do
      let(:initial_some_field) { 'initial some field value' }
      it 'defaults as nil' do
        expect(record.some_field).to be nil
      end

      it 'can be set' do
        expect {
          record.update_attribute(:some_field, initial_some_field)
        }.to change {
          record.some_field
        }.from(nil).to(initial_some_field)
      end

      describe 'once it is set' do
        before do
          record.update_attribute(:some_field, initial_some_field)
        end

        it 'makes the record invalid if changed' do
          record.some_field = 'new value'
          expect(record).not_to be_valid
        end

        it 'does not change in mass update' do
          expect {
            record.update_attributes(some_field: 'new value')
          }.not_to change {
            record.some_field
          }.from(initial_some_field)
        end

        it 'DOES change in update_attribute!! (skips validations' do
          expect {
            record.update_attribute(:some_field, 'other new value')
          }.to change {
            record.some_field
          }.from(initial_some_field).to('other new value')
        end
      end
    end