hey,
When using accepts_nested_attributes_for, I got stuck when having a validation which required the original to be present. The code will help clear up that sentence.
class Foo < ActiveRecord::Base
has_one :bar
accepts_nested_attributes :bar
end
class Bar < ActiveRecord::Base
#property name: string
belongs_to :foo
validates_presence_of :foo #trouble line!
end
#now when you do
foo = Foo.create! :bar_attributes => {:name => 'steve'}
#you get an error because the bar validation failed
I would like to write a validation that goes something like...
class Bar < ActiveRecord::Base
validates_presence_of :foo, :unless => :being_built_by_foo?
end
I am currently using rails3.beta4
Thank you
Alas I don't have an answer to this post, but the I came up with another way so I didn't need the validation.
Since bar should never be without a foo then any request to create a bar without a foo_id is an error. In the real example a foo is a project, and bar is a bid. It is a nested resource, but I wanted to give access to json apps to be able to query the info from the /bids location so the router looked like.
resources :bids
resources :projects do
resources: bids
end
and then I just had to make sure all html access used project_bids_path or form_for [:project,@bid] etc. This next part is largely untested but so far the desired behavior is there. I got the idea from Yehuda's post on generic actions http://yehudakatz.com/2009/12/20/generic-actions-in-rails-3/
#I'm sure there is a better way then map.connect
map.connect "projects/invalid_id", :controller => "projects", :action => "invalid_id"
resources :projects
resources :bids
end
#couple of changes from Yehuda
def redirect(*args, &block)
options = args.last.is_a?(Hash) ? args.pop : {}
path = args.shift || block
path_proc = path.is_a?(Proc) ? path : proc {|params| path % params }
status = options[:status] || 301
lambda do |env|
req = Rack::Request.new(env)
#Get both the query paramaters and url paramaters
params = env["action_dispatch.request.path_parameters"].merge req.params
url = path_proc.call(params.stringify_keys)
#Doesn't add the port back in!
#url = req.scheme + '://' + req.host + params
#content-type might be a bad idea, need to look into what happens for different requests
[status, {'Location' => url, 'Content-Type' => env['HTTP_ACCEPT'].split(',').first}, ['Moved Permanently']]
end
end
def bid_path
redirect do |params|
if params['project_id']
"/projects/#{params['project_id']}/bids/#{params['id']}"
else
'/projects/invalid_id'
end
end
end
match "bids", :to => bid_path
match "bids/:id", :to => bid_path
however, after doing all of this I most definitely don't think it worth it. I think nested_attributes breaks things and can be improved if that validation doesn't work, but after looking through the code for a little while I'm not sure exactly how to fix it or if it's worth it.