ruby-on-rails - Rails 3 模型子类让我发疯!请帮助更正 urls/params 哈希

标签 ruby-on-rails ruby inheritance model subclass

我对 Rail 模型的子类化有疑问。假设你有一个 User 模型和它的几个子类(用户类型),它们存储特定的方法和关联,例如:DirectorAdminTraineeInstructor等,这只是简单的“单表继承”。问题是双重的。

  1. 当您传递子类而不是基类时,路径/url 经常崩溃或做奇怪的事情。这是一个例子:

    <% if user.enabled? %>
      <%= link_to 'Disable', disable_user_path(user) %>
    <% else %>
      <%= link_to 'Enable', enable_user_path(user) %>
    <% end %>
    

    如果您传入一个 User 模型,它就可以正常工作。但是如果你传递一个子类,比如 Admin,它会抛出这个异常:

    No route matches {:controller=>"users", :action=>"disable", :id=>#<Admin id: 1, first_name: "Ken", ..., created_at: "2011-05-23 21:01:35", updated_at: "2011-05-23 21:04:28">}
    

    显然,这是不正确的行为。我们怎样才能让 Rails 一直使用基类?

  2. 更令人不安的是表单(我正在使用 simple_form)。假设您有一个 /profile 表单。您希望所有 User 子类都能平等地访问它,并且您不想在特殊情况下处理它们的子类;它应该是 100% 通用的。

    出于某种原因,如果用户是 Admin,它会将参数哈希发布为

    params[:admin]
    

    更糟糕的是,如果您查看表单的源代码,它实际上是 user[first_name] 而不是 admin[first_name],所以肯定有问题!实例变量也是 @user,所以我不明白为什么它应该发布到 params[:admin]

这是 (2) 的表单 View 代码:

<%= simple_form_for(@user, :url => profiles_path, :method => :put, :html => {:multipart => true}) do |f| %>
  <%= f.error_notification %>

  <div class="form">
    <fieldset>
      <legend>Personal Information</legend>
      <%= f.input :first_name %>
      <%= f.input :last_name %>
    </fieldset>

    <fieldset>
      <legend>Credentials</legend>
      <%= f.input :email %>
    </fieldset>

    <fieldset>
      <legend>Preferences</legend>
      <%= f.input :receive_email_notifications %>
      <%= f.input :receive_newsletters %>
      <%= f.input :allow_private_messages %>
    </fieldset>

    <fieldset>
      <legend>Avatar</legend>
      <p>
          Select an image from your computer to use as your avatar. You will be given the oppurtunity
          to crop this image further after your image has been uploaded.
      </p>
      <%= f.input :avatar, :as => :file, :label => "Select File" %>
      <%= f.hidden_field :avatar_cache %>
    </fieldset>

    <div class="actions">
      <%= f.button :submit, :value => "Update Profile" %>
      <%= link_to 'Cancel', profiles_path %>
    </div>
  </div>

<% end %>

以下是首先呈现 View 和提交表单时的 Controller 操作:

  def edit
    @user = User.find(current_user.id)
  end

  def update
    @user = User.find(current_user.id)

    if @user.update_attributes(params[:user]) # <-- this bombs for Admin subclass
      if params[:user][:avatar] # <-- this would bomb also.
        redirect_to(crop_avatar_profiles_path)
      else
        redirect_to(profiles_path, :notice => 'Your profile was successfully updated.')
      end
    else
      render :action => "edit"
    end
  end

  def crop_avatar
    @user = User.find(current_user.id)
  end

  def update_avatar
    @user = User.find(current_user.id)
    @user.crop(params[:x].to_i, params[:y].to_i, params[:h].to_i, params[:w].to_i)

    redirect_to(profiles_path, :notice => 'Your profile and avatar was successfully updated.')
  end

除了想出一些非常不雅的解决方案(尤其是表单问题)之外,我对如何解决它们一筹莫展。必须有更好的方法来处理这些情况。

最佳答案

= simple_form_for @fruit, :as => :fruit do |form|

@fruit 可以是任何类(Orange、Apple、Pear),它仍然会在输入前加上“fruit”前缀,因此每次都会给出一个 params[:fruit] .

关于ruby-on-rails - Rails 3 模型子类让我发疯!请帮助更正 urls/params 哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6103855/

相关文章:

javascript - Rails 将 localhost 放入 include 标签和 javascript 的方法

ruby-on-rails - 数组在递归函数中的奇怪行为

html - rails 设计一个循环

ruby-on-rails - Rails - 强参数 - 嵌套对象

ruby - 评论限制

ruby-on-rails - 如何在 Rails 中只运行特定的 Rspec 测试?

ruby-on-rails - 如何更改此 ruby​​ 匹配线以返回 true 或 false

c++ - 在两个子类中使用基本乘法运算符

java - java中的装饰器设计模式

java - 使用 AspectJ 模拟接口(interface)和方法的注解继承