Как заменить данные в одной записи данными из другой записи в контроллере в Ruby на Rails? - PullRequest
0 голосов
/ 30 марта 2020

Итак, во-первых, я абсолютный новичок, извините, если мой код выглядит ужасно. Я работаю на платформе бронирования, где пользователи могут бронировать места в автобусе и обмениваться ими друг с другом, если они им не нужны. Обмен ими - единственный способ избавиться от бронирования места, они не могут просто отменить / удалить его.

Если пользователю не нужны его Booking, тогда он / она может создать Angebot (предложение) на рынке / в списке для данного Booking. Другие пользователи могут запросить его с помощью Anfrage (запрос). Этот Anfrage (запрос) содержит альтернативные данные запрашивающего пользователя, которые содержат те же столбцы, что и Booking. Сейчас я пытаюсь заменить данные в одном Booking данными из Anfrage (запрос). Это достигается, когда пользователь, создавший Angebot (предложение) и владеющий Booking, принимает один из Anfrage (запрос).

def update_booking_durch_anfrage
    @angebot = Angebot.where(id: anfrage_params[:angebot_id]).first 
    @booking = Booking.find_by_id(@angebot)
    @gleiche_anfragen = Anfrage.find_by_id(@angebot)
    respond_to do |format|
      if @booking.update( 
        user_id: @angebot.user_id,
        vorname: @angebot.vorname,
        nachname: @angebot.nachname,
        email: @angebot.email,
        handynummer: @angebot.handynummer
      ) 
        @gleiche_anfragen.destroy
        @angebot.destroy

        format.html { flash[:notice] = 'Die Buchung wurde erfolgreich auf dich übertragen!' and redirect_to action: "index" }
        format.json { render :show, status: :ok, location: @booking }
      else
        format.html { render :edit }
        format.json { render json: @booking.errors, status: :unprocessable_entity }
      end
    end
  end

Здесь указаны schema.rb и отношения между моделями.

create_table "anfrages", force: :cascade do |t|
    t.integer "angebot_id"
    t.integer "user_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "vorname"
    t.string "nachname"
    t.string "handynummer"
    t.string "email"
    t.index ["angebot_id"], name: "index_anfrages_on_angebot_id"
    t.index ["user_id"], name: "index_anfrages_on_user_id"
  end

  create_table "angebots", force: :cascade do |t|
    t.integer "booking_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["booking_id"], name: "index_angebots_on_booking_id"
  end

  create_table "bookings", force: :cascade do |t|
    t.integer "bus_id"
    t.integer "user_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "vorname"
    t.string "nachname"
    t.string "handynummer"
    t.string "email"
    t.index ["bus_id"], name: "index_bookings_on_bus_id"
    t.index ["user_id"], name: "index_bookings_on_user_id"
  end
class Angebot < ApplicationRecord
    attr_accessor :user_id, :vorname, :nachname, :email, :handynummer
    belongs_to :booking
    has_many :anfrages
end

class Anfrage < ApplicationRecord
    belongs_to :angebot
    belongs_to :user
end

class Booking < ApplicationRecord
    belongs_to :bus
    belongs_to :user
    has_one :angebot
end

Но сейчас этот метод не делает то, что должен. Он просто перенаправляет меня в edit.html.erb представление из Anfrages, ничего не делая с данными. Я думаю, что это связано с тем, как rails обрабатывает обновления и соответствующие формы, но я понятия не имею, как это изменить.

Другое дело, что я не уверен, является ли контроллер подходящим местом для этого вид логики c и возможно она относится к модели.

Заранее спасибо за помощь и время.

Ответы [ 2 ]

0 голосов
/ 04 апреля 2020

Итак, я понял, что случилось. Сначала метод link_to, на мой взгляд, отправлял неправильные параметры, поэтому я настроил его правильно. Метод update_booking_durch_anfrage не смог правильно получить эти данные из-за всех связей. Теперь я создал этот 4-шаговый подход к извлечению данных, который, кажется, работает. И последнее, что вы видите, это то, что данные, которые я пытался заменить, были не в Angebot, а в Anfrage ...

Так что вот решение, которое выбирает правильное Booking и обновляет его данными с правильных Anfrage. Важно, чтобы ссылка в представлении использовала PUT, потому что вы хотите обновить данные. Большое спасибо также Джастину за его booking_attributes метод, который сделал его намного проще.

<%= link_to 'Tauschanfrage annehmen', {:controller => "angebots", :action => "update_booking_durch_anfrage", :id => anfrage.id, :angebot_id => anfrage.angebot_id }, :method => :put, data: { confirm: 'Bist du dir sicher, dass du die Tauschanfrage annehmen möchtest?'}, class: 'btn btn-outline-primary' %>

Как вы можете видеть, он отправляет нужные параметры, которые необходимы {:controller => "angebots", :action => "update_booking_durch_anfrage", :id => anfrage.id, :angebot_id => anfrage.angebot_id }

Затем метод в контроллере выбирает правильные данные множеством .where методов.

    def update_booking_durch_anfrage  
      @anfrage = Anfrage.where(id: anfrage_params[:id]).first
      @angebot = Angebot.where(id: anfrage_params[:angebot_id]).first
      @booking = Booking.where(id: @angebot.booking_id).first
      @gleiche_anfragen = Anfrage.where(angebot_id: anfrage_params[:angebot_id]).first
        respond_to do |format|
          if @booking.update!(@anfrage.booking_attributes) 
            @gleiche_anfragen.destroy
            @angebot.destroy
            format.html { flash[:notice] = 'Die Buchung wurde erfolgreich übertragen!' and redirect_to action: "index" }
          else
            format.html { flash[:notice] = 'Irgendwas ist schief gegangen...' and redirect_to action: "index" }  
          end
        end
     end



class Anfrage < ApplicationRecord
    belongs_to :angebot
    belongs_to :user

    validates :vorname, presence: true
    validates :nachname, presence: true
    validates :email, presence: true, :format => /\A[^@\s]+@[^@\s]+\z/

    def booking_attributes
        %i[user_id vorname nachname email handynummer].map do |a|
          [a, send(a)]
        end.to_h
    end
end

class Booking < ApplicationRecord
        belongs_to :bus
        belongs_to :user
        has_one :angebot, dependent: :destroy
        validates :vorname, presence: true
        validates :nachname, presence: true
        validates :email, presence: true, :format => /\A[^@\s]+@[^@\s]+\z/
end

Сохраняет данные после проверки в Модели, и все работает гладко. Я уверен, что это много спагетти-кода, но он выполняет свою работу ...

0 голосов
/ 30 марта 2020

Глядя на ваш код, логика вашего контроллера c выглядит как

if @booking.update(...)
else
 ...
 format.html { render :edit }
end

Так что происходит то, что обновление резервирования не работает, возвращает false и перенаправляет вас в окно редактирования. Вы можете получить более точную информацию о том, почему не удается обновить это бронирование, вместо этого позвонив по номеру @booking.update!(...), что вызовет ошибку, а не просто вернет false, если бронирование не обновляется.

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

class Angebot
  def booking_attributes
    %i[user_id vorname nachname email handynummer].map do |a|
      [a, send(a)]
    end.to_h
  end
end

# Controller

@booking.update(@angebot.booking_attributes)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...