2010-12-01 13 views
0

Ich habe folgendes Modell:Ruby on Rails - Ein virtuelles Attribut

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 

Wie würde ich ein virtuelles Attribut im Modell erstelle mir pro Quadratzoll jeden Material die Kosten zu geben?

Auch hat ich ein anderes Modell, das den Mehrwertsteuerwert gilt:

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 

Wie verwende ich dieses Modell einen Gesamtpreis pro Quadratzoll für jede Materialposition, um mich also müssen sich auf dem Mehrwertsteuersatz hinzufügen?

bearbeiten - ich jetzt die Mehrwertsteuer-Wert in dem folgenden Modell speichern:

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

bearbeiten - Das ist mein 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 

Antwort

3

Es ist nicht wirklich sinnvoll, das in die Tabelle aufzunehmen, oder es müsste bei jedem Update neu berechnet werden.

Wie Matchu schon sagt, Sie sollten nur eine Methode in der Modellklasse definieren.

Hinweis: Ich habe eine Klassenvariable hinzugefügt, um den Steuerwert zu halten.

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 

Und einiger 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 

Ich bin nicht ganz sicher, was genau Ihr Steueranwendungsfall ist, aber nicht, dass ein wenig mehr Sinn machen?

+0

Wie wähle ich die richtige Rate mit 'whichTax.rate'? – freshest

+0

@freshest: Siehe meine Bearbeitung. Hilft das überhaupt? –

+0

Gibt es eine Möglichkeit, alles in das Modell zu verschieben? Wenn ich die Gesamtkosten vom MaterialCost-Modell bekomme, wurde die Mehrwertsteuer bereits erhoben. – freshest

0

Es ist nicht wirklich ein virtuelles Attribut pro se, es ist nur eine Methode, oder?

def cost_per_square_inch 
    cost/height/width 
end 
+0

Wenn ich versuche, diese Daten mit etwas wie diese '@mount = Materialkosten.find (1,: select => 'cost_per_square_mm')' in der Steuerung zu erhalten, bekomme ich Unbekannte Spalte 'cost_per_square_mm' Fehler? – freshest

+0

Sie können Finder nicht verwenden, um virtuelle Attribute zu finden. Sie sind virtuell - das heißt, sie existieren nur in dem Modell, solange das Modell im Speicher existiert, aber nicht in dem, in dem das Modell gespeichert ist (z. B. eine Zeile in einer Datenbanktabelle). – yfeldblum

+3

Sie können stattdessen '@amount = MaterialCost.find (1) .cost_per_square_mm' verwenden. – yfeldblum