【问题标题】:Is there a way to check if a record was built by another model in active record?有没有办法检查记录是否由活动记录中的另一个模型构建?
【发布时间】:2010-06-29 09:11:05
【问题描述】:

当使用accepts_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 [:project,@bid] 等。下一部分很大程度上未经测试,但到目前为止所需的行为已经存在。我从 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 破坏了一些东西,如果验证不起作用,可以改进,但是在浏览了一段时间代码后,我不确定如何修复它或者是否值得。

【问题讨论】:

    标签: ruby activerecord ruby-on-rails-3


    【解决方案1】:

    首先,当使用nested_attributes 时,您将获得容器的存在。在示例中:当你保存 Foo 并且还有一个 Bar 的嵌套形式时,Bar 是由 Foo 构建的。

    如果您确定仅在 Foo 的上下文中使用 Bar,我认为没有必要进行这种验证。

    顺便说一句,尝试编写如下验证(Rails3 的新首选语法):

    validates :foo, :presence => true
    

    希望这会有所帮助, 一个。

    【讨论】:

    • 感谢格式化提示!我遇到的问题来自试图制作一个漂亮的界面。该项目也有一个 JSON API 部分。实际上 bar 是一个投标,而 foo 是一个项目。创建项目时,您可以从 Web UI 中使用nested_attributes 设置出价。项目结束后,您可以在使用nested_attributes 的项目页面上编辑出价。在 json 方面,我希望有人能够通过使用 project_id 发布到投标控制器来创建投标。为此,我需要验证 project_id 是否存在,不幸的是目前它在控制器中。
    • 你总是可以做一个很好的解决方法,而无需使用基于 json 的请求,只需使用一点 JS。例如,您制作一个嵌套的投标表格,然后使用 JS 创建一个链接/按钮来添加一个新的投标表格(您可以添加任意数量的投标,只需单击即可)。当您编辑/保存项目时,您将获得正确保存的投标。如果您对此解决方案感兴趣,我可以给您一些示例代码 ;-)
    • 这是个好主意!我仍然认为您应该能够设置该验证! >.
    猜你喜欢
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多