2016-06-08 11 views
0

Ich entwickle eine App, in der Benutzer ein persönliches Ernährungstagebuch haben können.Datensatz in Tabelle suchen und ID in einer anderen Tabelle in Rails speichern

Es ist ziemlich einfach: ein Benutzer kann nach einem Nährstoff auf einer Nährstofftabelle suchen (sagen wir Milch) - zZ durch eine ziemlich einfache Suchform - und sollte dann in der Lage sein, den Betrag zu sparen, den er von diesem Nährstoff verbrauchte die nährstoff_id) auf einer zweiten Tabelle, die Diaries genannt wird (die die nährstoff_id als Fremdschlüssel und ein ganzzahliges Feld namens "Menge" enthält).

Meine Suche funktioniert. Ich kann auch neue Datensätze in Diaries erstellen, aber ich muss die nutritive_id manuell eingeben.

Meine Frage ist nun, wie kann ich das leicht machen? Idealerweise findet ein Benutzer einen Nährstoff, klickt darauf und wird auf eine Seite umgeleitet, auf der dieser Nährstoff zusammen mit einem Feld für "Menge" und einer Speicherschaltfläche angezeigt wird, um beide Informationen (Nährstoff-ID und Menge) in der Diaries-Tabelle zu speichern.

Am Ende des Tages denke ich, der Benutzer wird auf die neue Aktion meines Tagebuch-Controller geleitet werden - die Frage ist, wie meine App die nutrient_id für diese Aktion für den Nährstoff setzt der Benutzer zuvor ausgewählt?

Tut mir leid, wenn das eine zu einfache Frage ist, aber ich habe erst vor ein paar Wochen angefangen zu programmieren.

Vielen Dank für Ihre Hilfe!

Mein Code sieht wie folgt aus:

nutrient.rb

class Nutrient < ActiveRecord::Base 
    has_many :diaries 

    def self.search(search) 
    where("name LIKE ?", "%#{search}%") 
    end 

end 

diary.rb

class Diary < ActiveRecord::Base 
    belongs_to :nutrient 
end 

nutrients_controller.rb

class NutrientsController < ApplicationController 
    before_action :set_nutrient, only: [:show, :edit, :update, :destroy] 

    # GET /nutrients 
    # GET /nutrients.json 
    def index 
    @nutrients = Nutrient.all 
    end 

    def search 
    if params[:search] 
     @nutrients = Nutrient.search(params[:search]).order("created_at DESC") 
     if @nutrients.present? 
     @nutrients 
     else 
     flash[:notice] = "Nutrient not found in database" 
     end 
    end 
    end 

    # GET /nutrients/1 
    # GET /nutrients/1.json 
    def show 
    end 

    # GET /nutrients/new 
    def new 
    @nutrient = Nutrient.new 
    end 

    # GET /nutrients/1/edit 
    def edit 
    end 

    # POST /nutrients 
    # POST /nutrients.json 
    def create 
    @nutrient = Nutrient.new(nutrient_params) 

    respond_to do |format| 
     if @nutrient.save 
     format.html { redirect_to @nutrient, notice: 'Nutrient was successfully created.' } 
     format.json { render :show, status: :created, location: @nutrient } 
     else 
     format.html { render :new } 
     format.json { render json: @nutrient.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # PATCH/PUT /nutrients/1 
    # PATCH/PUT /nutrients/1.json 
    def update 
    respond_to do |format| 
     if @nutrient.update(nutrient_params) 
     format.html { redirect_to @nutrient, notice: 'Nutrient was successfully updated.' } 
     format.json { render :show, status: :ok, location: @nutrient } 
     else 
     format.html { render :edit } 
     format.json { render json: @nutrient.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # DELETE /nutrients/1 
    # DELETE /nutrients/1.json 
    def destroy 
    @nutrient.destroy 
    respond_to do |format| 
     format.html { redirect_to nutrients_url, notice: 'Nutrient was successfully destroyed.' } 
     format.json { head :no_content } 
    end 
    end 

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

    # Never trust parameters from the scary internet, only allow the white list through. 
    def nutrient_params 
     params.require(:nutrient).permit(:name) 
    end 
end 

diaries_controller.rb

class DiariesController < ApplicationController 
    before_action :set_diary, only: [:show, :edit, :update, :destroy] 

    # GET /diaries 
    # GET /diaries.json 
    def index 
    @diaries = Diary.all 
    end 

    # GET /diaries/1 
    # GET /diaries/1.json 
    def show 
    end 

    # GET /diaries/new 
    def new 
    @diary = Diary.new 
    end 

    # GET /diaries/1/edit 
    def edit 
    end 

    # POST /diaries 
    # POST /diaries.json 
    def create 
    @diary = Diary.new(diary_params) 

    respond_to do |format| 
     if @diary.save 
     format.html { redirect_to @diary, notice: 'Diary was successfully created.' } 
     format.json { render :show, status: :created, location: @diary } 
     else 
     format.html { render :new } 
     format.json { render json: @diary.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # PATCH/PUT /diaries/1 
    # PATCH/PUT /diaries/1.json 
    def update 
    respond_to do |format| 
     if @diary.update(diary_params) 
     format.html { redirect_to @diary, notice: 'Diary was successfully updated.' } 
     format.json { render :show, status: :ok, location: @diary } 
     else 
     format.html { render :edit } 
     format.json { render json: @diary.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # DELETE /diaries/1 
    # DELETE /diaries/1.json 
    def destroy 
    @diary.destroy 
    respond_to do |format| 
     format.html { redirect_to diaries_url, notice: 'Diary was successfully destroyed.' } 
     format.json { head :no_content } 
    end 
    end 

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

    # Never trust parameters from the scary internet, only allow the white list through. 
    def diary_params 
     params.require(:diary).permit(:nutrient_id, :amount) 
    end 
end 

routes.rb

Rails.application.routes.draw do 

    resources :diaries 
    resources :nutrients do 
    collection do 
     get :search 
    end 
    end 

_form.html.erb (für ein neues Tagebuch Rekord)

<%= form_for(@diary) do |f| %> 
    <% if @diary.errors.any? %> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@diary.errors.count, "error") %> prohibited this diary from being saved:</h2> 

     <ul> 
     <% @diary.errors.full_messages.each do |message| %> 
     <li><%= message %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

    <div class="field"> 
    <%= f.label :nutrient_id %><br> 
    <%= f.number_field :nutrient_id %> 
    </div> 
    <div class="field"> 
    <%= f.label :amount %><br> 
    <%= f.number_field :amount %> 
    </div> 
    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

Antwort

2

Es gibt mehrere Möglichkeiten, dies wäre der beste Ansatz für mich eine der schnellsten und höchstwahrscheinlich die diaries unter nutrients, da Tagebücher zu Nest zu lösen sein belongs_to :nutrients

resources :nutrients do 
    resources :diaries 
    collection do 
     get :search 
    end 
    end 

auf diese Weise Ihr alle diaries Pfad-Methode ein @nutrient Argument und Ihre Route wie wäre annehmen würde: /nutrients/4/diaries/1

Also in Ihrem diar ies_controller, könnten Sie haben:

class DiariesController < ApplicationController 
    before_action :set_nutrient 

    def new 
    @diary = @nutrient.diaries.new 
    end 

    def create 
    @diary = @nutrient.diaries.new(diary_params) # you can safely remove the nutrient_id from the strong params 
    ... remaining logic here 
    end 
... 
    private 
    def set_nutrient 
    @nutrient ||= Nutrient.find(params[:nutrient_id]) 
    end 

    # You cans skip/ignore this method, if you don't want to be too strict 
    def set_diary 
    @diary ||= @nutrient.diaries.find(params[:id]) 
    end 
end 

Dann Ihrer Ansicht nach könnte man dann:

<%= form_for([@nutrient, @diary]) do |f| %> 
    <% if @diary.errors.any? %> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@diary.errors.count, "error") %> prohibited this diary from being saved:</h2> 

     <ul> 
     <% @diary.errors.full_messages.each do |message| %> 
     <li><%= message %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 
    <div class="field"> 
    <%= f.label :amount %><br> 
    <%= f.number_field :amount %> 
    </div> 
    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

Wie ich bereits erwähnt, gibt es noch andere Möglichkeiten, dies zu tun, wie Sie auch hidden_fields jedoch nutzen könnten scheint dies der sauberste Weg zu mir zu sein. Wenn Sie nicht möchten, dass Ihre Tagebuch-Routen verschachtelt werden, können Sie Folgendes erwarten: [die Liste der Aktionen, die nicht verschachtelt werden sollen, z. B. show], sowohl auf Ihrer before_action als auch auf Ihrer Route resources :diaries. Ich hoffe, ich kann Ihnen helfen oder andere Verwirrungen kennenlernen, denen Sie begegnen könnten.

+0

Dies ist genau das, was ich gesucht habe! Danke vielmals. – Oliver

Verwandte Themen