何时何地创建新动作?

时间:2014-04-07 00:28:00

标签: ruby-on-rails

使用carrierwave我的用户现在可以上传自己的头像了!好极了!这是我的更新操作:

  def update

    @image = @user.create_avatar(file_name: user_params[:avatar][:file_name])

    respond_to do |format|
      if @user.update_attributes(user_params.delete avatar: [:file_name]) # this automatically deletes any avatar instances, as uploaded files are saved in a seperate model
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

这是我的表格:

<%= form_for(@user, :html => { :multipart => true }) do |f| %>
    <%= f.fields_for :avatar do |f| %>
        <%= f.file_field :file_name %>
        <%= f.submit %>
    <% end %> 
<% end %>

但是,当有人没有上传头像时,上述操作会爆发,因为首先user_params没有:avatar键,因此调用[:file_name]会导致未定义的方法没有错误。

我可以通过条件轻松解决这个问题,但是我应该创建一个单独的动作来更新我的头像吗?可能def avatar_update?我只是不确定最好的rails方式,因为我有一个单独的Image模型,但我不觉得这样的动作应该进入图像控制器,因为用户模型有这样的关系:

has_one :avatar, class_name: 'Image', foreign_key: :user_id

对我来说,它确实感觉就像avatar_update动作“属于”用户控制器和图像控制器之间的某处,所以我真的不知道放在哪里。将它放在图像控制器中会是RESTful,但是在未来的某个时刻,图像模型将属于许多不同的模型。这一思路会导致图像控制器中的几个动作沿着avatar_updatephoto_update以及panorama_updatepost_image_update以及我的应用程序的不同类型的各种事物图像。

那么我应该在哪里进行update_avatar动作?

1 个答案:

答案 0 :(得分:1)

尽管图像与多个模型相关联,但您的所有图片上传都足够相似,您可以在图像控制器中保留一个update操作。此操作将更新图像,然后重定向到相关记录所在的#show页面。想象一下,图像可以属于用户,文章或专辑:

class ImagesController < ApplicationController
  ...
  def update
    if @image.update_attributes(image_params)
      redirect_to @image.associated_record, notice: 'Image was successfully updated.'
    else
      render action: 'edit'
    end
  end
end


class Image < ActiveRecord::Base
  ...

  def associated_record
    user || article || album
  end
end

另一种可能性是,根据与之关联的模型,每个图像#update动作将会非常不同。在这种情况下,在其关联模型下创建多个ImageController个命名空间,每个模型都有自己的#update操作。例如:

# in app/controllers/users/images_controller.rb
class Users::ImagesController < ApplicationController
end

# in config/routes.rb
resources :users do
  resources :images, controller: 'users/images'
end

资料来源:Rails AntiPatterns:最佳实践Ruby on Rails Refactoring,“Rat's nest resources”一章