【问题标题】:advice for restful design?对宁静设计的建议?
【发布时间】:2011-10-29 12:01:33
【问题描述】:

我有一个关于为我正在开发的应用程序的特定部分构建宁静设计的最佳方式的问题。

应用的一些背景:

User has_one :settings_for_email

有一个 profile_controller,它有一个显示动作。像这样的:

def show
  @user = current_user
end

最初是这样设置的,以便表单将回传到配置文件控制器..类似于:

<% form_for profile_path(@user) do |f| %>
  <% f.fields_for :settings_for_email do |s| %>
    <% ... form fields ... %>
  <% end %>
<% end %>

profile_controller 的更新操作是这样的:

def update
  @user = User.find(params[:id])
  @user.settings_for_email.update_attributes(params[:user][:settings_for_email])
end

....

我不喜欢这个,因为它有一个漏洞,允许更改正在编辑的用户记录...将其更改为 @user = current_user,对我来说没有多大意义,因为它是一个更新操作,需要某种 ID.. 所以去 /profile/123 或 profile/456 会产生相同的用户记录(因为它会使用 current_user,params[:id] 将是多余的).. 这对我来说似乎很奇怪。

附带说明,我需要一个控制器操作来将用户的电子邮件设置重置为默认值。

所以,我最终做的是开辟一条新路线:

resource :settings_for_email, :only => :create do
  post :reset, :on => :member
end

然后创建一个 settings_for_email_controller:

#settings_for_email_controller.rb
def create
  current_user.settings_for_email.update_attributes(params[:settings_for_email_controller])
  redirect_to profile_url
end

def reset
  current_user.reset_settings_for_email!
  redirect_to profile_url
end

...

但后来我想知道,这可以通过任何方式改进吗?

如果我真的想让这 100% 安宁,最好这样做:

#update_settings_for_email_controller:
def create
  current_user.settings_for_email.update_attributes(params[:settings_for_email_controller])
redirect_to profile_url
end

#reset_settings_for_email_controller:
def create
  current_user.reset_settings_for_email!
  redirect_to profile_url
end

我对此持怀疑态度,因为为此设置两个控制器似乎有点愚蠢。但我想不出更好的方法来做到这一点。同样,使用 update 需要一个 id,destroy 也是如此。我最初认为使用销毁操作来执行“重置”会很好,但是 - 再次......它会涉及浪费的 id 参数。所以我想我会在这里问一下你们对这种事情的看法?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 rest architecture


    【解决方案1】:

    我认为您有点混淆了:这里有两个用户。有需要更改详细信息的用户,然后有进行实际更改的用户。通常,它们是相同的,但并非总是如此,例如:管理员可能需要重置某些用户的密码。

    正在更改的用户记录的 id 应该进入 REST 接口,User.find params[:id] 应该会处理好。

    进行更改的用户与身份验证(确保该用户就是她声称的身份)和授权(是否允许该用户进行更改?)有关。这就是您拨打current_user 时获得的用户。像devise 这样的宝石可以帮助解决这个问题。

    一般来说,你的控制器动作应该得到current_user,并且目标用户,确保当前用户被授权对目标用户执行动作(因为他们是同一个用户,当前用户是管理员或您在应用程序中拥有的任何其他逻辑),然后才执行该操作。

    【讨论】:

    • 据我了解您所说,我的控制器操作应如下所示: user = User.find(params[:id]);如果用户!= current_user;渲染:文本=>“错误!!!!!!”;别的; user.update_attributes(params[:user]);结尾 .... ?你是这个意思吗?这似乎是一个愚蠢的条件检查,因为登录用户 (current_user) 将始终是应该更新的记录。 ?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多