2016-11-08 3 views
0

Редактировать: Основная проблема заключалась в том, что при добавлении эталонных полей я использовал театры: ссылки, а не театры: ссылки, поэтому поле не было помечено как внешний ключ. Как только я расстегнул эти миграции и вернул их правильно, я смог выполнить эту работу.Как вручную сохранить ссылочный объект в Rails

В моем контроллере showtimes я пытаюсь автоматически установить идентификатор театра на любой театр, которому принадлежит экран, который пользователь вводил, но когда я пытаюсь сохранить его как целое или строку, я получаю сообщение об ошибке. Тем не менее, когда я пытаюсь сохранить его как объект театра, я получаю «Неопроверенный параметр: театр» с консоли, а из приложения rails - «Театр должен существовать».

showtimes_controller:

class ShowtimesController < ApplicationController 
    before_action :set_theater, only: [:create, :edit] 
    before_action :set_showtime, only: [:show, :edit, :update, :destroy] 

    # GET /showtimes 
    # GET /showtimes.json 
    def index 
    @showtimes = Showtime.all 
    end 

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

    # GET /showtimes/new 
    def new 
    @showtime = Showtime.new 
    end 

    # GET /showtimes/1/edit 
    def edit 
    end 

    # POST /showtimes 
    # POST /showtimes.json 
    def create 

    @showtime = Showtime.new(showtime_params) 

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

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

    # DELETE /showtimes/1 
    # DELETE /showtimes/1.json 
    def destroy 
    @showtime.destroy 
    respond_to do |format| 
     format.html { redirect_to showtimes_url, notice: 'Showtime was successfully destroyed.' } 
     format.json { head :no_content } 
    end 
    end 

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

    def set_theater 
     screenInfo = Screen.where("id = ?", params[:showtime][:screen]) 
     params['showtime']['theater'] = Theater.find(screenInfo[0]['theater_id']) 
    end 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def showtime_params 
     params.require(:showtime).permit(:date, :time, :archived, :movie_id, :theater, :screen) 
    end 
end 

Showtimes модель:

class Showtime < ApplicationRecord 
    belongs_to :movie 
    belongs_to :theater 
end 

Showtimes _form

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

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

    <div class="field"> 
    <%= f.label :date %> 
    <%= f.date_select :date %> 
    </div> 

    <div class="field"> 
    <%= f.label :time %> 
    <%= f.time_select :time %> 
    </div> 

    <div class="field"> 
    <%= f.label :archived %> 
    <%= f.check_box :archived %> 
    </div> 

    <div class="field"> 
    <%= f.label :movie_id %> 
    <%= f.text_field :movie_id %> 
    </div> 

    <div class="field"> 
    <%= f.label :screen %> 
    <%= f.text_field :screen %> 
    </div> 

    <%= f.hidden_field :theater, :value => "" %> 

    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

Ошибка при попытке сохранить в виде целого числа:

Theater(#70015922237640) expected, got Fixnum(#11723820) 

Ошибка при попытке сохранить в виде строки:

Theater(#70015868755420) expected, got String(#11739240) 

Бревна при попытке сохранить как объект театра:

Started POST "/showtimes" for IP at 2016-11-08 20:22:37 +0000 
Processing by ShowtimesController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"nENPV5d6YRXdcx3H+Xa9ZypGtyFlaTg+zyENGB10TmW9OyWxLR9Dsl7nDoG9irq+3qApiNA2/oEqL5RZ0SXorA==", "showtime"=>{"date(1i)"=>"2016", "date(2i)"=>"11", "date(3i)"=>"8", "time(1i)"=>"2016", "time(2i)"=>"11", "time(3i)"=>"8", "time(4i)"=>"20", "time(5i)"=>"22", "archived"=>"0", "movie_id"=>"2", "screen"=>"1", "theater"=>""}, "commit"=>"Create Showtime"} 
    [1m[36mScreen Load (0.3ms)[0m [1m[34mSELECT "screens".* FROM "screens" WHERE (id = '1')[0m 
    [1m[36mTheater Load (0.2ms)[0m [1m[34mSELECT "theaters".* FROM "theaters" WHERE "theaters"."id" = ? LIMIT ?[0m [["id", 1], ["LIMIT", 1]] 
Unpermitted parameter: theater 
    [1m[35m (0.1ms)[0m [1m[36mbegin transaction[0m 
    [1m[36mMovie Load (0.2ms)[0m [1m[34mSELECT "movies".* FROM "movies" WHERE "movies"."id" = ? LIMIT ?[0m [["id", 2], ["LIMIT", 1]] 
    [1m[35m (0.2ms)[0m [1m[31mrollback transaction[0m 
    Rendering showtimes/new.html.erb within layouts/application 
    Rendered showtimes/_form.html.erb (13.6ms) 
    Rendered showtimes/new.html.erb within layouts/application (16.4ms) 
Completed 200 OK in 323ms (Views: 86.5ms | ActiveRecord: 3.9ms) 

Как, черт возьми, я сохранить этот параметр?

+1

Почему у вас есть театр вместо theater_id? – inye

+0

'Непередаваемый параметр: театр 'это важная вещь, которую нужно учитывать и учитывать ... это означает, что в вашей строке' allow/require' чего-то не хватает –

ответ

0

Вы пытались присвоить свой объект переменной экземпляра и назначить ее перед сохранением?

На вашем before_action

def set_theater 
    @theather = ... # Code to find the theather 
end 

На вашем действии создать

def create 
    @showtime = Showtime.new(showtime_params) 
    @showtime.theather = @theather 
    ... # Code to save and handle errors 
end 
+0

Я получаю 'ActiveModel :: MissingAttributeError (не могу писать неизвестный атрибут 'theater_id'):' ошибка с использованием этого. Не уверен, почему, потому что я обслуживаю весь объект – vman411gamer

+0

Используете ли вы какие-либо отладочные камни, такие как byebug? Было бы здорово увидеть, работает ли метод 'set_theather'. – rebagliatte

+1

«ActiveModel :: MissingAttributeError», это интересно ... можете ли вы дать нам больше контекста для этой ошибки? загляните в консольное окно или файл журнала (log/development.log) и найдите эту ошибку .... после нее должна быть stacktrace (которая составляет около 30-ичных строк имен файлов с номерами после них). Скопируйте это и вставьте его в исходный вопрос. Эта stacktrace покажет нам, какая строка кода вызвала эту ошибку, что очень помогает нам разобраться, что именно пошло не так. –

0

используется theater вместо theater_id в нескольких местах в вашем коде, и вы должны изменить его во всех местах, чтобы это работало.

Во-первых - вы не можете выбрать в нашем виде ... HTML не распознает тип theater в theater и не будет проходить один через - так ваша форма должна пройти theater_id вместо (который будет целым что он с радостью может справиться).

# eg here make sure it's a theater_id 
<%= f.hidden_field :theater_id, :value => @theater.id %> 

рядом - ваш требуйте/разрешение, вероятно, что бросает некоторые ошибки - вам нужно, чтобы быть theater_id, а также:

def showtime_params 
    params.require(:showtime).permit(:date, :time, :archived, :movie_id, :theater_id, :screen) 
end 

Теперь вам нужно получить театр из, используя экранную информацию пары - но также иметь в виде, что это может прийти через, как ноль несколько раз (так сторожевой пункт всегда хорошо):

def set_theater 
    if params[:showtime].present? && params[:showtime][:screen_id].present? 
    screen_info = Screen.find(params[:showtime][:screen_id]) 
    @theater = Theater.find(screenInfo.theater_id) 
    end 
end 

Примечание: Я обновил именование-схему, чтобы быть железнодорожным стандартом и удаляю го ING, где вы пытаетесь установить театр в Params, как показано ниже:

params['showtime']['theater'] = Theater.find(screenInfo[0]['theater_id']) 

Я не знаю, что вы на самом деле пытаетесь сделать с этой строки кода, но все это, PARAMS не работает, что Кстати, считайте, что params - это «набор вещей, которые были переданы нам от пользователя, а затем выброшены» - мы не используем его для хранения новых значений, которые мы создаем контроллером. Вот что @variable s являются для

Можете ли вы объяснить более, что вы пытаетесь сделать, и мы подумаем, правильный способ сделать это :)

+1

Спасибо за помощь, но я это понял. Пришлось отменить миграцию, где я занимался театром: ссылка вместо театра: ссылки, поэтому он не был помечен как foreign_key, делающий все это намного сложнее – vman411gamer

Смежные вопросы