I have a model of product and I need to write in the _form view , the number of the product that an admin wants to insert.
I have another table with the Supply (number of product)
so in my product table I don't have the attribute quantity , but I have just the supply_id
(that links my two tables of product and supply)
Since I don't have the quantity in my product table, I used a virtual attribute on Product.
I had to change the view of the new and edit product
cause in the new I want the field quantity but in the edit I don't want (cause I use another view to do this)
So, I deleted the partial _form and created separate view.
Also, I had to set in the controller of products that if I want to update a product, i have to call a set_quantity callback, cause I have to insert a "fake" value to fill the params[:product][:quantity]
. This , because I setted the validation presence true ,on the quantity virtual field in the product model. I want to know , if all this story is right (it works , but I want a suggestion about the programming design of this story. Cause I don't like the fact that I give a fake value to fill the quantity field when I have to update a product)
Controller:
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
Model:
class Product < ActiveRecord::Base
belongs_to :supply ,dependent: :destroy
attr_accessor :quantita
validates :quantita, presence:true
end
Can you say me if there is a better way to fill the param[:product][:quantity]
in the case of the update action? Cause i don't like the fact that i give it the value of 2. Thank you.
Instead of using attr_accessor
you could create custom getter/setters on your product model. Note that these are not backed by an regular instance attribute.
Also you can add a validation on the supply
association instead of your virtual attribute.
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
In Ruby assignment is actually done by message passing:
product.quantita = 1
Will call product#quantita=
, with 1 as the argument.
Another alternative is to use nested attributes for the supply.
class Product < ActiveRecord::Base
belongs_to :supply ,dependent: :destroy
validates_associated :supply, presence:true
accepts_nested_attributes_for :supply
end
This means that Product
accepts supply_attributes
- a hash of 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