2017-03-06 4 views
1

Ich bin ein Rails Newbie und obwohl ich eine App mit Erb-Dateien, Ruby und Postgres erstellt habe, finde ich es schwierig zu finden, wie die Syntax für die Klassenmethoden schreiben, vor allem, wenn Sie mehr als nur CRUD machen wollen.Wie verknüpften Datensatz erstellen und ändern mit has_one

Ich habe zwei Tabellen: Material & Materialkosten Material has_one material_cost und material_cost gehört zu Material.

Jeder neue Eintrag im Materialmodell sollte automatisch den einen Eintrag in material_costs ausfüllen. Mit drei Feldern von Material muss ich die Daten ändern, die den neuen Materialkostensatz erstellen.

Ich habe stundenlang versucht, die richtige Syntax für eine build_with Funktion zu finden. Nicht so einfach, sogar mit den Rails Docs.

Code so weit:

class Material < ApplicationRecord 
    has_and_belongs_to_many :job_entries 
    has_one :material_costs, :material_charges, :dependent => :destroy 

@material = current_material 
@material_cost = @material.build_material_costs(
      :cost_a4 => ((@material.cost_per_sqm +  @material.ink_per_sqm) * 0.0626514876) 
      :cost_a3 => ((@material.cost_per_sqm + @material.ink_per_sqm) * 0.124548139) 


end 

class MaterialCost < ApplicationRecord 
belongs_to :materials 
end 

Migration

class CreateMaterials < ActiveRecord::Migration[5.0] 
    def change 
    create_table :materials do |t| 
     t.string :product_name, :guk_name 
     t.integer :roll_width_in, :roll_length_m, :factor, :rounded_sale_price 
     t.float :list_price, :cost_per_sqm, :ink_per_sqm, :supplier_discount, :sell_per_sqm 

     t.timestamps 
    end 
    end 
end 

Bin ich auf dem richtigen Weg? Kennt jemand benutzerfreundliche Anleitungen zum Erstellen der Klassenmodellmethoden für die grundlegende Abfrage und Änderung von Daten? Dank, meine Maschine

class CreateMaterials < ActiveRecord::Migration[5.0] 
def change 
    create_table :materials do |t| 
    t.string :product_name, :guk_name 
    t.integer :roll_width_in, :roll_length_m, :factor, :rounded_sale_price 
    t.float :list_price, :cost_per_sqm, :ink_per_sqm, :supplier_discount, :sell_per_sqm 
    t.timestamps 
    end 
    end 
end 


class CreateMaterialCosts < ActiveRecord::Migration[5.0] 
    def change 
    create_table :material_costs do |t| 
    t.float :cost_a4, :cost_a3, :cost_a2, :cost_a1, :cost_b0, :cost_b1, :cost_b2 
    t.float :cost_b3, :cost_b4 
    t.timestamps 
    end 
end 
end 

Nach Schließung und den psql-Server neu zu starten und bekommen den Server zurück, neu zu erstellen, die db, godhar dann schließlich die Migration alle meine Migrationen ich in Fehler Hölle bin. Wenn man die Tische fallen gelassen hat, was ist die Konvention? Soll ich die Migrationsdateien bearbeiten, damit das Umbenennen von Spalten und alle diese Bearbeitungsmigrationen nicht ausgeführt werden? Hat ich die Chance, bei Null zu beginnen, oder muss ich auch alle meine Änderungen migrieren? Werden wir ID-Spalten hinzufügen? Ich dachte, dass Rails durch die Beziehungen die IDs für uns aufstellt, ich bin mir sicher, dass ich das irgendwo gelesen habe? Wo und wann fügen wir ID-Spalten hinzu?

Antwort

2

Versuchen Sie folgendes:

class Material < ApplicationRecord 
    has_and_belongs_to_many :job_entries 
    has_one :material_cost, :material_charge, :dependent => :destroy 

    after_create do 
    self.create_material_cost(
     cost_a4: (self.cost_per_sqm + self.ink_per_sqm) * 0.0626514876), 
     cost_a3: (self.cost_per_sqm + self.ink_per_sqm) * 0.124548139) 
    ) 
    end 

end 

class MaterialCost < ApplicationRecord 
belongs_to :materials 
end 

after_create einen Code-Block gibt auf jedem Material automatisch ausgeführt werden, nachdem sie erstellt wurde. create_material_cost ist eine Hilfsmethode, die generiert wird, wenn Sie has_one-Beziehungen verwenden. Sie können damit eine MaterialCost erstellen, die automatisch dem angegebenen Material zugeordnet wird.

Wie bei Ihren Migrationen fügt yes rails automatisch eine ID-Spalte hinzu, wenn Sie keine angeben. Der Standardname ist: ID. Welche Schienen nicht automatisch automatisch hinzufügen, ist eine Fremdschlüsselspalte, um Ihre MaterialCosts mit ihrem übergeordneten Material zu verknüpfen. Sie können dies mit Hilfe einer neuen Migration zu schaffen:

class AddMaterialIDToMaterialCosts < ActiveRecord::Migration[5.0] 
    def change 
    add_column :material_costs, :material_id, :integer 
    end 
end 

Ihre Datenbank zurücksetzen und Ihre Migration neu zu laden, ausführen:

rails db:drop db:create db:migrate db:seed 

Seien Sie gewarnt, dass dies alle vorhandenen Daten löschen in Ihrer Datenbank.

+0

dank @eiko, sieht gut aus. Schwierigkeiten beim Seeding, um es zu testen. Sollte bald in Ordnung sein! – godhar

+0

@godhar Ich habe meine Antwort so bearbeitet, dass sie Kommentare zu deinen Wanderungssorgen enthält. – eiko

2

Nun sind Sie auf der rechten Spur, aber Sie müssen

  1. has_one singulär sein muss
  2. belongs_to singulär sein müssen, ein bisschen paar Dinge ändern
  3. Sie können von after_create Rückruf zu schaffen machen zugehörigen material_cost für Material
  4. Sie brauchen nicht @material = current_material, wie Sie es als self
  5. bezeichnen können
  6. Wenn Sie build verwenden, müssen Sie die Instanz speichern oder create
  7. Verwenden CONSTANT für die Werte wie 0.0626514876 und 0.124548139 so verwenden, wenn Sie sie Sie nicht ändern müssen müssen sie projektweit suchen. So

, nachdem diese Dinge Festsetzung der Code

sein

material.rb

class Material < ApplicationRecord 
    has_and_belongs_to_many :job_entries 
    has_one :material_cost, :material_charge, dependent: :destroy 

    after_create :set_material_cost 
    A3_FACTOR = 0.124548139 
    A4_FACTOR = 0.0626514876 

    private 

    def set_material_cost 
    @material_cost = self.create_material_cost(
     cost_a4: (cost_per_sqm + ink_per_sqm) * A4_FACTOR, 
     cost_a3: (cost_per_sqm + ink_per_sqm) * A3_FACTOR 
    ) 
    end 
end 

material_cost.rb

class MaterialCost < ApplicationRecord 
    belongs_to :material 
end 
+0

danke @Deepak ... das sieht nach der richtigen Syntax aus, jetzt habe ich Probleme beim Seeding der Materialtabelle, um zu sehen, ob es einen Datensatz für material_costs erstellt. Ich bekomme: unbekanntes Attribut material_id für MaterialCost. Ich dachte Rails formatiert alle IDs für Beziehungen? – godhar

+0

@godhar Sorry für die langsame Antwort. Haben Sie bereits Migrationen für Ihre Datenbank generiert? Wenn ja, könnten Sie Ihre Migrationsdateien für Material und MaterialCost hochladen? – eiko

+0

Ja, ich habe eine Reihe von Migrationen. Ich hatte meinen Rechner und den psql-Server ausgeschaltet, als ich ihn startete und die Tabellen und Migrationen neu erstellte. Alle diese Fehler sind aufgetreten. – godhar

Verwandte Themen