开发者

Validations misfiring in a form with multiple models

I'm building a web app that saves a user's goals and tasks, where a user has_many goals, and a goal has_many tasks. When I try to save a goal and task together, I keep getting validation errors saying "Tasks goal can't be blank" and "Tasks content can't be blank," even though they clearly aren't. I'm certain the problem isn't with the actual form, but with the goal controller's 'new' or 'create' code, but whatever I try, I can't seem to get it right. Any ideas on why the validations for the task model are misfiring? I've been working on this issue for too long and I'm about to give up. I've included the goal controller, goal model, task model, and debug info. If you need to see any other code, let me know.

Goal Controller:

def new 
  @title = "New Goal"
  @goal = Goal.new
  @goal.tasks.build
end     

def create
  @user = current_user
  @goal = @user.goals.build(params[:goal])
  @task = @goal.tasks.build(params[:goal][:task])
  if @goal.save
    flash[:success] = "Goal created!"
    redirect_to user_path(@user) 
  else
    render 'new'
  end
end

Goal Model:

# Table name: goals
#
#  id              :integer         not null, primary key
#  user_id         :integer
#  content         :string(255)
#  completed       :boolean
#  completion_date :date
#  created_at      :datetime
#  updated_at      :datetime
#

class Goal < ActiveRecord::Base

  attr_accessible :content, :completed, :completion_date
  belongs_to :user
  has_many :tasks, :dependent => :destroy
  accepts_nested_attributes_for :tasks

  validates :user_id, :presence => true
  validates :content, :presence => true, :length => { :maximum => 140 }

end

Task Model:

#  id              :integer    开发者_开发问答     not null, primary key
#  goal_id         :integer
#  content         :string(255)
#  occur_on        :date
#  recur_on        :string(255)
#  completed       :boolean
#  completion_date :date
#  created_at      :datetime
#  updated_at      :datetime
#

class Task < ActiveRecord::Base

  attr_accessible :content, :occur_on, :recur_on, :completed
  belongs_to :goal

  validates :goal_id, :presence => true
  validates :content, :presence => true, :length => { :maximum => 140 }

end

Debug Dump after an unsuccessful save:

--- !map:ActiveSupport::HashWithIndifferentAccess 
utf8: "\xE2\x9C\x93"
authenticity_token: NF/vVwinKQlGAvBwEnlVX/d9Wvo19MipOkYb7qiElz0=
goal: !map:ActiveSupport::HashWithIndifferentAccess 
  content: some goal
  tasks_attributes: !map:ActiveSupport::HashWithIndifferentAccess 
    "0": !map:ActiveSupport::HashWithIndifferentAccess 
      content: some task
commit: Submit
action: create
controller: goals


This is a problem with nested attributes. You cannot validate the presence of the encapsulating model from the nested model (in your case, you cannot validate the presence of goal_id from Task). When validations are run the goal is not yet saved, and thus has no id, so it is impossible to assign it.

You can either eliminate the validation that is causing the problem, or not use the built-in nested attributes. In the latter case, you would need to add your own logic to first save the goal and then create any nested tasks.

Bummer, huh? I wish someone would come up with a good solution for this...maybe I'll work on it if I ever get some free time.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜