2016-08-17 12 views
0

Ich lerne und erstelle meine erste App mit Ruby on Rails, indem ich ein bestehendes Projekt klonen und anpassen kann. Ich steckte in dem Schreiben eines Controllers fest und hoffe, dass jemand einen Tipp hat, mir zu helfen.Controller für eine App für Reservierungen einrichten

Kontext ich eine Trainingsplattform bin Gebäude: Benutzer ein Trainings entwerfen können, können diese Schulungen an mehreren Terminen gegeben werden (Ich nenne diese Trainingseinheiten ‚Thrills‘), (andere) Benutzer auf diese Nervenkitzel mit Vorbehalten abonnieren .

Conceptualization of models

Complication Ich habe den Benutzer, Schulungen und Reservierungen Modell jetzt ausgeführt werden, aber ich will in den Nervenkitzel Modell hinzufügen zwischen (Ich weiß, das nicht der einfachste Weg ist, aber ich folgte eine Ausbildung, die das Thrill-Modell nicht enthalten). Ich habe das Modell und eine einfache Ansicht erstellt, wo ein Trainer in der Lage sein sollte, einem bestehenden Training (in Trainings/Edit) Nervenkitzel hinzuzufügen. Leider nach einem Tag versucht, ich habe nicht das geschafft, ich bekomme immer wieder:

NoMethodError in ThrillsController#create

NoMethodError (undefined method `thrills' for nil:NilClass): (line 16)

Meine TrainingsController für def bearbeiten sieht aus wie

def edit 
     if current_user.id == @training.user.id 
      @photos = @training.photos 
      @thrill = @training.thrills.create(thrill_params) 
      @thrills = @training.thrills 
     else 
      redirect_to root_path, notice: "Je hebt hier helaas geen toegang tot" 
     end 
    end 

    def update 
     if @training.update(training_params) 

      if params[:images] 
      params[:images].each do |image| 
       @training.photos.create(image: image) 
      end 
      end 

      @thrill = @training.thrills.create(thrill_params) 
      @thrills = @training.thrills 

      @photos = @training.photos 

      redirect_to edit_training_path(@training), notice: "Updated..." 
     else 
      render:edit 
     end 
    end 

Und mein ThrillsController wie

sieht
class ThrillsController < ApplicationController 

    def create 

     @thrill = @training.thrills.create(thrill_params) 
     redirect_to @thrill.training, notice: "Je thrill is aangemaakt!"   
    end 

    private 
    def thrill_params 
     params.require(:thrill).permit(:trilldate, :thrillhr, :thrillmin, :training_id) 
    end 

end 

Und mein Formular, um einen Nervenkitzel in Ansichten/Nervenkitzel/_form.html.erb hinzuzufügen, die in Ansichten/Trainings/edit.html.erb

gerendert wird

Der vollständige Code der App kann hier https://github.com/chrisrutte/musc

Frage Ich bin natürlich einfach falsch, etwas zu tun hier gefunden werden, so hoffe ich jemanden, der mir den Hinweis zur Verfügung stellen kann, wie neue Nervenkitzel sparen in meiner Nervenkitzel-Modell.

Wenn weitere Informationen benötigt werden, zögern Sie nicht mich zu fragen.

Vielen Dank im Voraus!

+0

Sie sollten Objekte zuweisen, dann verwenden Sie sie, eine andere Möglichkeit, es wird nicht funktionieren. Welche Codezeile erzeugt einen Fehler? – AndreyS

+0

Ja, die vollständige Stack-Trace wäre hilfreich. Du rufst an vielen Orten eine Nervenkitzel-Methode an, also gibt es viele Orte, an denen etwas Null sein kann, das du nicht für null hältst. – quinn

+0

Gerade hinzugefügt die Zeile. Danke für Ihr Interesse! @AndreyS –

Antwort

0

Zuerst sehen wir uns an, was die Modelle für diese Art von Setup aussehen würde:

class Training < ActiveRecord::Base 
    has_many :thrills 
    has_many :users, through: :thrills 
end 

class Thrills < ActiveRecord::Base 
    belongs_to :training 
    has_many :reservations 
    has_many :users, through: :reservations 
end 

class Reservation < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :thrill 
    has_one :training, though: :thrill 
end 

class User < ActiveRecord::Base 
    has_many :reservations 
    has_many :thrills, through: :reservations 
    has_many :trainings, through: :thrills 
end 

Stellen Sie sicher, dass die Rails guide on associations wie dies lesen ist recht komplex.

Beachten Sie, dass die Reservierung als Join-Modell funktioniert.

Reservierung hat auch eine indirekte Beziehung zu Training. Dies soll vermeiden, doppelte Fremdschlüssel auf mehreren Ebenen zu haben. Gleiches gilt für das Benutzermodell. Der Hauptgrund ist, dass ActiveRecord den Fremdschlüssel nur einmal schreibt!

Wenn die Routen einrichten Sie werden wahrscheinlich wollen to use nesting:

resources :trainings, shallow: true do 
    resources :thrills 
end 

Wir können dann Setup den Controller.

class ThrillsController < ApplicationController 

    before_action :set_training!, only: [:new, :create, :index] 
    before_action :set_thrill!, only: [:show, :edit, :update, :destroy] 

    # GET /trainings/:training_id/thrills/new 
    def new 
    @thrill = @training.thrills.new 
    end 

    # POST /trainings/:training_id/thrills 
    def create 
    @thrill = @training.thrills.new(thrill_params) 

    if @thrill.save 
     redirect_to @thrill 
    else 
     render :new 
    end 
    end 

    # GET /trainings/:training_id/thrills 
    def index 
    @thrills = @training.thrills 
    end 

    # this is not nested. 
    # GET /thrills/:id 
    def show 
    end 

    # this is not nested. 
    # GET /thrills/:id/edit 
    def edit 
    end 

    # this is not nested. 
    # PUT|PATCH /thrills/:id 
    def update 
    if @thrill.update(thrill_params) 
     redirect_to @thrill 
    else 
     render :edit 
    end 
    end 

    # ... 

    private 
    def set_training! 
     @training = Training.find(params[:training_id]) 
    end 

    def set_thrill! 
     @thill = Thrill.joins(:training).find(params[:id]) 
     @training = @thill.training 
    end 

    def thrill_params 
     params.require(:thrill) 
       .permit(:trilldate, :thrillhr, :thrillmin, :training_id) 
    end 
end 

Und lässt Setup die Form:

<%= form_for([@training, @thrill]) do |f| %> 
    <div class="form-group"> 
     <%= f.text_field :thrillhr, placeholder: "Uur", class: "form-control" %> 
    </div> 
    <div class="actions"> 
    <%= f.submit "Create", class: "btn btn-primary" %> 
    </div> 
<% end %> 

Da wir die training_id obwohl Form action Attribut und nicht in Form Körper wir form_for([@training, @thrill]) verwenden, die es uns geben Sie den Pfad /trainings/6/thrills zum Beispiel passieren wollen .

Allerdings möchten wir für unser Bearbeitungsformular /thrills/1 stattdessen. Also lassen Sie das beheben:

+1

Es gibt viele andere Idiosynkrasien in Ihrer App - Sie sollten verschachtelte Attribute verwenden, um Fotos zu erstellen. Attribute mit dem Namen des Modells/der Tabelle (trilldate, thrillhr) nicht als überflüssig vorwegnehmen, sehr unrund und dumm aussehen. – max

+1

Im Allgemeinen sind verschachtelte Ressourcen wahrscheinlich der schwierigste Teil von Schienen für Anfänger - lesen Sie sich die Leitartikel durch. – max

+0

Das hat mir wirklich geholfen. Vor allem der Teil zum Set_training! und die Verwendung von durch jetzt ergibt Sinn für mich. Der traurige Teil ist, dass der Code immer noch den Fehler gibt: ActionView :: Template :: Error (undefinierte Methode 'new_record? 'Für nil: NilClass): Das gibt mir das Gefühl, dass es die Zeile in Thrillscontroller def def nicht erkennt. Hier sollte die Klasse @thrill gesetzt sein. Hast du irgendeine Idee? Danke für Ihre Tipps, sie sind sehr geschätzt :) –

Verwandte Themen