2010-06-29 67 views
1

使用accept_nested_attributes_for时,我遇到需要原件存在的验证时卡住了。该代码将有助于澄清这句话。有没有办法检查记录是否由活动记录中的另一个模型构建?

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 

我想编写云像一个验证...

class Bar < ActiveRecord::Base 
    validates_presence_of :foo, :unless => :being_built_by_foo? 
end 

我目前使用rails3.beta4

谢谢

唉我不对这篇文章有一个答案,但我想出了另一种方式,所以我不需要验证。

因为bar不应该没有foo,那么任何创建没有foo_id的bar的请求都是错误的。在实际的例子中,foo是一个项目,而bar是一个出价。它是一个嵌套的资源,但我希望能够访问json应用程序,以便能够从/ bids位置查询信息,以便路由器看起来像。

resources :bids 
resources :projects do 
    resources: bids 
end 

,然后我必须确保所有HTML访问使用project_bids_path或的form_for [:项目,@出价]等,这接下来的部分是基本上未经检验,但到目前为止所期望的行为是存在的。我从Yehuda的职位的想法上通用的行动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 

然而,做了这一切之后,我最肯定觉得不值得。我认为nested_attributes会破坏一些东西,如果验证不起作用,它可以得到改进,但是在仔细查看一段代码之后,我不确定如何修复它,或者它是否值得。

回答

0

首先,当使用nested_attributes时,您将看到容器的存在。在这个例子中:当你保存Foo并且还有Bar的嵌套表单时,Bar则由Foo构建。

我认为如果您确定只在Foo的上下文中使用Bar,则不需要进行这种验证。

顺便说一句,尽量写验证如下(为Rails3中新的首选语法):

validates :foo, :presence => true 

希望这有助于 一个。

+0

感谢格式化提示!我遇到的问题来自于尝试创建一个不错的界面。该项目还有一个JSon API部分。在现实中,酒吧是一个投标,foo是一个项目。在创建项目时从Web UI中,您可以使用nested_attributes设置出价。项目之后,您可以在使用nested_attributes的项目页面上编辑出价。在json方面,我希望有人能够通过在project_id中发布到出价控制器来创建出价。要做到这一点,我需要验证project_id是否存在,现在不幸的是,它在控制器中。 – daicoden 2010-07-01 10:34:35

+0

你总是可以做一个很好的解决方法,而不使用仅使用一点JS的基于json的请求。例如,您为嵌入式表单制作出价,然后使用JS创建链接/按钮以添加新的出价表单(只需点击即可添加尽可能多的出价)。当您编辑/保存项目时,您会正确保存出价。如果你对这个解决方案感兴趣,我可以给你一些示例代码;-) – 2010-07-01 11:07:15

+0

这是一个好主意!我仍然认为你应该可以设置验证! >。但是,我一直在想的例子越来越多。我想我可以为该项目的另一部分设置JavaScript,但我很欣赏这个提议。特别是对于这个出价问题,我实际上需要使其成为嵌套资源,因为没有项目就不能存在出价。谢谢你的帮助! – daicoden 2010-07-01 13:20:30