Developing rails app for both api and front end. so we have products controller for api and products controller for the front and Product model is one for both.
Like that
class Api::V1::ProductsController < ActionController::API
def create
@product.save
end
end
class ProductsController < ActionController::Base
def create
@product.save
render @product
end
end
class Product < ActiveRecord::Base
def weight=(value)
weight = convert_to_lb
super(weight)
end
end
Basically in product we have 'weight field' and this field is basically capture weight from the warehouse. it will be different unit for the user. so i'm going to save whatever weight is capture by unit, its lb,g or stone but it will convert to lb and store into database.
So i write the overide method for the conversation. but i want this override method should only call for front app only and not for the api. because api will always post weight in lb(its need to be convert in client side)
Can you guys anyone suggest the solution? what should i use or what should i do for this kind of scenario.suggest if its any other solution for that kind of situation as well.
CodePudding user response:
It's better to keep Product
model as simple as possible (Single-responsibility principle) and keep weight conversion outside.
I think it would be great to use Decorator pattern. Imagine class that works like this:
@product = ProductInKilogram.new(Product.find(params[:id]))
@product.update product_params
@product.weight # => kg weight here
So, you should use this new ProductInKilogram
from Api::V1::ProductsController
only.
You have options to implement that.
Inheritance
class ProductInKilogram < Product
def weight=(value)
weight = convert_to_lb
super(weight)
end
end
product = ProductInKilogram.find(1)
product.weight = 1
It's easy, but complexity of ProductInKilogram is high. For example you can't test such class in an isolation without database.
SimpleDelegator
class ProductInKilogram < SimpleDelegator
def weight=(value)
__getobj__.weight = convert_to_lb(value)
end
end
ProductInKilogram.new(Product.find(1))
Plain Ruby (My Favourite)
class ProductInKilogram
def initialize(obj)
@obj = obj
end
def weight=(value)
@obj.weight = convert_to_lb(value)
end
def weight
convert_to_kg @obj.weight
end
def save
@obj.save
end
# All other required methods
end
Looks a little bit verbose, but it is simple. It's quit easy to test such class, because it does nothing about persitance.