获取未拥有父项的belongs_to父对象

时间:2013-05-25 21:24:47

标签: ruby-on-rails activerecord

我有ProductPrice,产品和菜单

产品belongs_to菜单和ProductPrice到产品。

我通过cocoon嵌套对象一次性创建产品价格。

在ProductPrice中,我有以下代码:

def menu
  self.product.menu;
end

价格取决于product_category和尺寸。因此,在创建新产品时,用户选择其所属的类别,然后通过ajax获取product_prices,以便用户可以为该产品的每个大小填写价格。使用此程序获取价格:

def self.get_product_prices(category_id, product_id)
  if category_id != "0"
    MenuCategory.find(category_id).product_sizes.map do |size|
      if product_id == "0"
        ProductPrice.new({:product_size_id => size.id })
      else
        ProductPrice.find_or_initialize_by_product_size_id_and_product_id(size.id, product_id)
      end
    end
  end
end

在创建此项时会出现错误,因为产品以nil的形式返回。有没有办法获得非持久产品所属的菜单?我可以看到它ProductPrice具有填充的product_id属性,并且始终使用填充的menu_id创建Product。

4 个答案:

答案 0 :(得分:0)

假设您的课程定义如下:

class Menu < ActiveRecord::Base
  has_many :products
end

class Product < ActiveRecord::Base
  belongs_to :menu
  has_one :product_price
end

class ProductPrice < ActiveRecord::Base
  belongs_to :product

  def menu
    product.menu
  end
end

您所描述的问题只有在确实未分配产品时才会出现。有了这个说,您可能需要编写测试以确保您的应用程序的任何部分product作为nil不会发生或处理。此外,可以添加验证以确保ProductPrice在创建每个对象时与Product有关联。

class ProductPrice < ActiveRecord::Base
  belongs_to :product

  validates :product, :presence => true

  def menu
    product.menu
  end
end

答案 1 :(得分:0)

必须将def菜单更改为:

def menu
  if !self.product.nil?
    self.product.menu
  end
end

答案 2 :(得分:0)

我遇到了与has_one / belongs_to关系类似的问题,其中每个关系都验证了另一个的存在。特别是在测试代码中,这使得在没有绕过验证或溢出堆栈的情况下存根其中一个是一个挑战。

解决方案是:

FactoryGirl.define do
  factory :person do
    ignore do
      skip_address false
    end
    after(:build) do |person, evaluator|
      person.address ||= FactoryGirl.build(:address, :person => person) unless evaluator.skip_address
    end
  end
  factory :address do
    ignore do
      skip_person false
    end
    after(:build) do |address, evaluator|
      address.person ||= FactoryGirl.build(:person, :address => address) unless evaluator.skip_person
    end
  end
end

忽略允许您在要测试验证代码时覆盖。

更好的设计方法是将它全部放在一个表中,但不幸的是,它是一个遗留数据库。

答案 3 :(得分:0)

我将从上面的答案中采用以下模型设置作为示例

class Menu < ActiveRecord::Base
  has_many :products
end 

class Product < ActiveRecord::Base
  belongs_to :menu
  has_one :product_price
end    

现在,就像它一样简单,您只需要在菜单和产品类的关联中添加:inverse_of,如下所示:

class Menu < ActiveRecord::Base
  has_many :products, inverse_of: :menu
end

class Product < ActiveRecord::Base
  belongs_to :menu, inverse_of: :product
  has_one :product_price
end

现在如果您这样做:

menu = Menu.new
product = menu.products.new
product.menu

你得到菜单对象而不是nil