0

I have the following model:

  create_table "material_costs", :force => true do |t|
    t.string   "material"
    t.integer  "height"
    t.integer  "width"
    t.decimal  "cost",       :precision => 4, :scale => 2
    t.datetime "created_at"
    t.datetime "updated_at"
  end

How would I create a virtual attribute in the model to give me the cost per square inch of each material?

Also I have another model which holds the VAT value:

  create_table "taxes", :force => true do |t|
    t.string   "name"
    t.decimal  "rate",       :precision => 10, :scale => 0
    t.datetime "created_at"
    t.datetime "updated_at"
  end

How do I use this model to give me a total price per square inch for each material item ie need to add on the VAT rate?

Edit - I now store the VAT value in the following model:

  create_table "app_options", :force => true do |t|
    t.string   "name"
    t.string   "value"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

Edit - This is my controller code:

  def calculate_quote
    @moulding = Moulding.find( params[:id], :select => 'cost, width' )
    @mount = MaterialCost.find(1).total_cost_per_square_mm
    @glass = MaterialCost.find(2).total_cost_per_square_mm
    @backing_board = MaterialCost.find(3).total_cost_per_square_mm
    @wastage = AppOption.find( 2, :select => 'value' )
    @markup = AppOption.find( 3, :select => 'value' )

    respond_to do |format|
      format.json { render :json => { :moulding => @moulding, :mount => @mount, :glass => @glass, :backing_board => @backing_board, :wastage => @wastage, :markup => @markup } }
    end
  end

2 Answers 2

3

It doesn't really make sense to put that in the table, or it would need to be recalculated on every update.

As Matchu suggests, you should just define a method in the model class.

Note: I've added a class variable to hold the tax value.

class MaterialCost < ActiveRecord::Base
  # Initialize the tax rate on initialization of the class
  @@tax = AppOptions.find(:first, :name => 'VAT').value.to_f

  # ...

  def base_cost_per_square_inch
    cost / (height * width)
  end

  def total_cost_per_square_inch
    base_cost_per_square_inch * (1 + @@tax)
  end
end

And some controller code:

class MaterialsController < ApplicationController

  def calculate_full_price
    # GET /Materials/calculate_full_price/5

    # Get the material in question using the ID param.
    material = MaterialCost.find(:first, :id => params[:id])

    # Calculate the total price
    @total_price_per_sq_in_with_tax = material.total_cost_per_square_inch

    # Done (fall off to render the normal view)
  end

end

I'm not quite sure what your tax use case is exactly, but does that make a little more sense?

Sign up to request clarification or add additional context in comments.

8 Comments

Is there a way to move everything into the model? So that when I get the total cost from from the MaterialCost model the VAT has already been applied.
@freshest: You can accomplish that with associations and then update your model's methods accordingly. Does a MaterialCost have more than one tax with which it can be associated, or will it have exactly one (well, or zero)?
The VAT rate is now stored in an AppOptions table. This is where the application keeps various settings which can be set by the user. So the AppOptions table just has name and value columns and each of the entries are not related to each other in any way. I would like each entry in MaterialCosts to have this VAT value applied to it.
@freshest: Okay... I've set a class variable in the MaterialCost model which should more or less do what you want. Let me know what you think...
@Platinum Azure - Please see my edit. Also I am getting following error - ArgumentError in MouldingsController#calculate_quote - Unknown key(s): name
|
0

It's not really a virtual attribute per se, it's just a method, right?

def cost_per_square_inch
  cost / height / width
end

3 Comments

When I try to extract this data using something like this @mount = MaterialCost.find( 1, :select => 'cost_per_square_mm' ) in the controller I get Unknown column 'cost_per_square_mm' error?
You cannot use finders to find virtual attributes. They are virtual - that is, they exist only in the model so long as the model exists in memory, but not in whatever the model is saved to (e.g., a row in a database table).
You can instead use @amount = MaterialCost.find(1).cost_per_square_mm.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.