Rails polymorphic 与 accepts_nested_attributes_for 与 file upload

aisensiy · 2013年02月10日 · 最后由 simonykq 回复于 2013年04月11日 · 2863 次阅读

这个问题涉及 model 之间的关系,描述会比较长,请耐心一点。如果我没有说清楚,麻烦指正。

class Attachment
  attr_accessible :attachment, :attachmentable_id, :attachmentable_type
  belongs_to :attachmentable, polymorphic: true
end

class Task
  attr_accessible :content
  has_one :homework
end

class Homework
  attr_accessible :content, :task_id
  belongs_to :task
  has_many :attachments, as: :attachmentable
end

一个 task 可以有一个 homework,而一个 homework 可以包含很多的 attachment。 那么,我这里想要在创建 homework 的同时,创建 attachment。对 Homework 修改如下

class Homework
  attr_accessible :content, :task_id
  belongs_to :task
  has_many :attachments, as: :attachmentable
  accepts_nested_attributes_for :attachments  <------
end

然后 view 如下所示

<%= form_form(@homework) do |f| %>
  <%= f.fields_for :attachments do |ff| %>
    <%= ff.label :attachment %>
    <%= ff.file_field :attachment %>
  <% end %>
  <%= f.text_area :content %>
  <%= f.submit "commit" %>
<% end %>

controller 的方法如下

class TasksController 
  def show
    @task = Task.find(param[:id])
    @homework = Homework.new
    @homework.attachments.build
  end
end

页面的显示是没有问题的。一个 file_upload 的 input,一个 homework 的 content field。但是在填写好表单提交的时候报错说的意思大概是

attachmentable can not be blank

似乎意思是说 attachment 里面的 attachmentable_id attachmentable_type 有问题,怎么破?

attachementable 看起来挺蹊跷的... 直接用一个 attachement 不行么?

#1 楼 @luikore 因为它会被多个 model 使用,并且其实还有额外的信息。

<%= f.fields_for :attachments do |ff| %> 改成 <%= f.fields_for :attachments, @homework.attachments.new do |ff| %>试试呢?

#3 楼 @leomayleomay 我目前采用了类似的方法。

task controller

class TaskController
  def show
    @task = Task.find(param[:id])
    @homework = Homework.new
    @attachment = @homework.attachments.build <-----
  end
end

view 做一些变化

<%= form_form(@homework) do |f| %>
  <%= f.fields_for @attachment do |ff| %> <------
    <%= ff.label :attachment %>
    <%= ff.file_field :attachment %>
  <% end %>
  <%= f.text_area :content %>
  <%= f.submit "commit" %>
<% end %>

对 attachment 单独处理,而不是使用 accepts_nested_attributes_for

class HomeworkController
  def create
    @task = Task.find(params[:task_id])
    attachment_attrs = params[:homework].delete(:attachment)                                                                                      
    attachment_attrs[:project_id] = @task.project_id
    @task.create_homework!(params[:homework])
    @task.homework.attachments.create!(attachment_attrs)
    @task.finish_task unless @task.homework.blank?
    redirect_to [@task.project, @task]
  end
end

虽然这样可以解决问题,但是我依然对那个 accepts_nested_attributes_forpolymorphic 做处理的方法耿耿于怀。

homework#create的 params 贴上来看看,感觉你的参数有问题

感觉你的问题是在 Homework Model 上。在 attr_accessible 后还需要加上 ":attachments_attributes"

需要 登录 后方可回复, 如果你还没有账号请 注册新账号