Rails 4中的虚拟属性

时间:2015-06-18 11:59:47

标签: ruby-on-rails ruby ruby-on-rails-4 virtual-attribute

我有一个产品型号,我需要在_form视图中写入,管理员想要插入的产品编号。 我有另一张供应表(产品数量) 所以在我的产品表中我没有属性数量,但我只有supply_id(链接我的两个产品和供应表)

由于我的产品表中没有数量,因此我在产品上使用了虚拟属性。

我不得不更改新产品和编辑产品的视图 在新的原因我想要字段数量,但在编辑中我不想要(因为我使用另一个视图来做这个) 所以,我删除了部分_form并创建了单独的视图。 另外,我必须在产品的控制器中设置如果我想更新产品,我必须调用set_quantity回调,因为我必须插入"假的"填充params[:product][:quantity]的值。这是因为我在产品模型中的数量虚拟字段上设置了验证状态为true。我想知道,如果所有这些故事都是正确的(它有效,但我想对这个故事的编程设计提出建议。因为我不喜欢这样一个事实,即我给出一个假值来填充数量字段时我必须更新产品)

控制器:

class ProductsController < ApplicationController
    include SavePicture 
    before_action :set_product, only: [:show, :edit, :update, :destroy]
    before_action :set_quantita, only: [:update]
    ....

    def set_quantita
       params[:product][:quantita]=2  #fake value for the update action
    end
    ....
end

型号:

class Product < ActiveRecord::Base
    belongs_to :supply ,dependent: :destroy
    attr_accessor :quantita
    validates :quantita, presence:true
end

如果在更新操作的情况下有更好的方法来填充param[:product][:quantity],你能说我吗?因为我不喜欢我给它2的值这一事实。谢谢。

1 个答案:

答案 0 :(得分:10)

您可以在产品型号上创建自定义getter / setter,而不是使用attr_accessor。请注意,这些不受常规实例属性的支持。

您也可以add a validation on the supply association代替您的虚拟属性。

class Product < ActiveRecord::Base
  belongs_to :supply ,dependent: :destroy
  validates_associated :supply, presence:true

  # getter method
  def quantita
    supply
  end

  def quantita=(val)
    if supply
      supply.update_attributes(value: val)
    else
      supply = Supply.create(value: val)
    end
  end
end

在Ruby中,赋值实际上是通过消息传递完成的:

product.quantita = 1

将调用product#quantita=,以1作为参数。

另一种方法是使用nested attributes来供应。

class Product < ActiveRecord::Base
  belongs_to :supply ,dependent: :destroy
  validates_associated :supply, presence:true
  accepts_nested_attributes_for :supply
end

这意味着Product接受supply_attributes - 属性哈希。

class ProductsController < ApplicationController

  #...
  before_action :set_product, only: [:show, :edit, :update, :destroy]

  def create
    # will create both a Product and Supply
    @product = Product.create(product_params)
  end

  def update
    # will update both Product and Supply
    @product.update(product_params)
  end

  private

  def product_params
    # Remember to whitelist the nested parameters!
    params.require(:product)
          .allow(:foo, supply_attributes: [:foo, :bar])
  end
  # ...
end