Rails 3模型子类让我疯狂!请帮助纠正网址/参数哈希值

Fir*_*lem 1 ruby inheritance model ruby-on-rails subclass

我对子类化铁的模型有问题.假设你有一个User模型,它的几个子类(用户类型)存储特定的方法和协会,例如:Director,Admin,Trainee,Instructor,等这只是简单的"单表继承".问题是2倍.

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

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

    如果你传入一个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">}
    
    Run Code Online (Sandbox Code Playgroud)

    显然,这表现不正常.我们怎样才能让rails一直使用基类?

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

    出于某种原因,如果用户是a Admin,则会将params hash发布为

    params[:admin]
    
    Run Code Online (Sandbox Code Playgroud)

    更糟糕的是,如果你查看表单的来源,它实际上是user[first_name]代替admin[first_name],而是一些东西肯定是搞砸了!实例变量也是@user如此,所以我不明白它为什么要发布到params[:admin].

这是(2)的表单视图代码:

<%= 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 %>
Run Code Online (Sandbox Code Playgroud)

以下是首次呈现视图的控制器操作以及提交表单时的操作:

  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
Run Code Online (Sandbox Code Playgroud)

除了思考一些非常不优雅的解决方案(特别是对于表单问题),我不知道如何解决它们.必须有更好的方法来处理这些情况.

Kri*_*ris 7

= simple_form_for @fruit, :as => :fruit do |form|
Run Code Online (Sandbox Code Playgroud)

@fruit可以是任何类(橙色,苹果,梨),它仍然会在输入前加上"水果",从而params[:fruit]每次都给出一个.