Update quantity of a model from another

1

I am working on a project where there is a Stock of Bidons (Drums) , but I would like to edit the main Stock of this when that Stock is taken in another model , for example when you make a purchase of a main product and this Stock is subtracted with the one you enter.

The models are:

Buy

class Compra < ActiveRecord::Base
    belongs_to :bidon #De acá recogemos el Stock principal
end

Bidon

class Bidon < ActiveRecord::Base
    has_many :compras
end

In the shopping model, I have access to : bidon_id , I can select the drum, but I am saving the quantity with another field called: quantity_buckets. The name of the field in the Bidons model is only : quantity and you thought that in the buyer_controller you could subtract the : quantity_buckets with the : quantity of the Bidons model to achieve the discount of the Main Stock when creating the purchase. This I will do with other modules, so I need some guidance please.

compras_controller.rb

 def new
    @compra = Compra.new
    @bidons = Bidon.all.map{ |b| [b.id] }
  end

 def create
    @compra = Compra.new(compra_params)
    @compra.bidon_id = params[:bidon_id]
end

   private
    # Use callbacks to share common setup or constraints between actions.
    def set_compra
      @compra = Compra.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def compra_params
      params.require(:compra).permit(:proveedor_id, :cantidad_bidones, :calibradas, :calibre, :tipo, :bidon_id)
    end
end

In the purchase form I have the following:

  <div class="field">
    <%= f.label :cantidad_bidones %><br>
    <%= f.number_field :cantidad_bidones %>
  </div>
      <div class="field">
      <%= select_tag(:bidon_id, options_for_select(@bidons), :prompt => "Seleccione los Bidones") %>
    </div>

Only that would be my query, how to modify the existing data in the Bidons model in this case : quantity

    
asked by Mosiah Ricardo 18.10.2016 в 12:04
source

2 answers

1

All the logic of your application will always be in the models. Since Ruby On Rails is a framework oriented to the MVC model view controller. The solution of having a service is not the correct one because the framework does not work that way. The services are used but for development in java.

So the best solution, with best practices, is to use callbacks Here is the complete documentation of this for you to read. Callbacks Therefore in your shopping model you must have a callback

  

after_save

So this thing that aria is that every time you save a purchase record automatically triggers a method that will run only after the purchase is saved.

It would fit like this

class Bidon
  has_many :compras
end

class Compra
  after_save :descontar_bidones

  belongs_to :bidon

  private
  # Este es un metodo que se disparara automaticamente despues que se guarde una compra
  # self.bidon llama a la relacion belongs_to que esta arriba y le descuenta la cantidad comprada este es un campo de la tabla compra.
  # luego se guarda el objeto relacionado
  def descontar_bidones
    self.bidon.existencias -= self.cantidad_comprada
    self.bidon.save
  end
end

I hope I help you.

    
answered by 24.11.2016 / 16:47
source
3

I agree with the comments you have received. It is difficult to know what logic you are implementing, and it gives the feeling that it is not correct. However, if you are sure of your implementation, what you are looking for could be something like this:

 def create
  @compra = Compra.new(compra_params)
  @bidon = Bidon.find(params[:bidon_id])
  @compra.bidon = @bidon

  @bidon.cantidad -= @compra.cantidad_bidones

  #responde a la petición como veas conveniente
end

However this is considered very logical for a controller. Instead, I would advise you to use a service.

/app/services/service_compra.rb

class ServicioCompra
  attr_accessor :compra, :bidon

  def initialize(compra, bidon)
    @compra = compra
    @bidon = bidon
  end

  def realizar_compra
    compra.bidon = bidon
    bidon.cantidad -= compra.cantidad_bidones

    compra.save && bidon.save
  end
end

From the controller you should call this service:

 def create
  @compra = Compra.new(compra_params)
  @bidon = Bidon.find(params[:bidon_id])

  ServicioCompra.new(compra, bidon).realizar_compra

  #responde a la petición como veas conveniente
end

The code could still be improved, but I think that this path would be the right one

    
answered by 20.10.2016 в 10:27