Home > OS >  Determine in model that which controller is trigger the save action?
Determine in model that which controller is trigger the save action?

Time:11-16

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.

Links

  • Related