2015-06-24 3 views
-1

ВыпускRails - Как обновить запись, а затем динамически обновлять значения в другой модели на основе значения изменяемой записи?

Говорят, у меня есть помост с именем ServiceMenu, который содержит только лишь одно выпадающее меню, которое имеет 3 значения Тормоза, колодки и глушителя. У меня есть модель Service, в которой хранятся все службы, принадлежащие пользователю, на модели под названием Tech. Каждый tech имеет возможность добавления какой-либо один из service_menu (Тормозов, колодки и Глушитель) к их дб профиль, который называется, services.

Проблема, которую я предвижу, если бы я обновлять какие-либо один из ServiceMenu имен говорят от Brakse к Тормоза, то techs все равно будет иметь старое service_menu имя в своем профиле. Я бы обнаружил, что делаю много домашнего хозяйства, обновляя более 1000 записей из-за typo или просто желая обновить имя ServiceMenu.


Файлы

service_menu.rb

class ServiceMenu < ActiveRecord::Base 
    has_many :services 
end 

service.rb

class Service < ActiveRecord::Base 
    belongs_to :tech 
    belongs_to :service_menu 
end 

service_menus_controller.rb

def update 
    respond_to do |format| 
    if @service_menu.update(service_menu_params) 
    format.html { redirect_to @service_menu, notice: 'Service menu was successfully updated.' } 
    else 
    @position_count = ServiceMenu.count 
    format.html { render :edit } 
    end 
end 

service_controller

def new 
    @service = current_tech.services.build 
end 



def create 
    @service = current_tech.services.build(service_params) 

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

схема

create_table "service_menus", force: :cascade do |t| 
    t.string "name",      limit: 255 
    t.datetime "service_icon_updated_at" 
    t.integer "service_icon_file_size", limit: 4 
    t.string "service_icon_content_type", limit: 255 
    t.string "service_icon_file_name", limit: 255 
    t.integer "position",     limit: 4 
    t.datetime "created_at",       null: false 
    t.datetime "updated_at",       null: false 
    end 


    create_table "services", force: :cascade do |t| 
    t.string "name",  limit: 255 
    t.integer "tech_id", limit: 4 
    t.datetime "created_at",    null: false 
    t.datetime "updated_at",    null: false 
    end 


    create_table "techs", force: :cascade do |t| 
    t.string "email",     limit: 255, default: "", null: false 
    t.string "username",    limit: 255 
    t.datetime "avatar_updated_at" 
    t.integer "avatar_file_size",  limit: 4 
    t.string "avatar_content_type", limit: 255 
    t.string "avatar_file_name",  limit: 255 
    t.string "encrypted_password",  limit: 255, default: "", null: false 
    t.string "reset_password_token", limit: 255 
    t.datetime "reset_password_sent_at" 
    t.datetime "remember_created_at" 
    t.integer "sign_in_count",   limit: 4, default: 0, null: false 
    t.datetime "current_sign_in_at" 
    t.datetime "last_sign_in_at" 
    t.string "current_sign_in_ip",  limit: 255 
    t.string "last_sign_in_ip",  limit: 255 
    t.datetime "created_at",          null: false 
    t.datetime "updated_at",          null: false 
    t.string "first_name",    limit: 255 
    t.string "last_name",    limit: 255 
end 

Вопрос

Как я могу выполнить задачу обновления нескольких записей динамически в services дб на обновленное имя в ServiceMenu в любое время я внести изменения значения? Для того, слова:

  • Обновить запись на ServiceMenu из опечатка Brakse к Тормоза
  • После обновления записи на ServiceMenu, Rails будет найти в services дб всех значений в name колонке что = Brakse
  • обновить все Brakse значения в столбце nameBr AKES

Редактировать

ли что-то вроде этого в любое время я обновляю ничего на ServiceMenu выпадающего меню.

if @service_menu.update(service_menu_params) 
@service.update.where(name: "Old `ServiceMenu` value which , ie.**Brakse**", "The new `ServiceMenu` value which is now **Brakes**") 

Пожалуйста, помогите, как это осуществить. Любая помощь очень ценится.

ответ

0

Если мне не хватает какого-либо нюанса на вопрос, переименование пункта обслуживания от Brakse to Brake - это все, что вам нужно сделать - ассоциации останутся действительными.

Это предполагает, конечно, что таблица services имеет поле name, но это трудно понять, не видя вашу схему.

Если это неправильный ответ, пожалуйста, покажите всю схему, а не только ассоциации.

+0

Я добавил содержание схемы, относящееся к этому сообщению. Миграция будет скорее ручным процессом. Я ищу более динамичное решение. Я также включил более подробную информацию. –

0

В Rails вы достигнете этого, создав модельные отношения между объектами. В вашем случае, а именно, что будет выглядеть примерно так:

class Tech < ActiveRecord::Base 
    has_many :services, inverse_of: :tech 
end 

class Service < ActiveRecord::Base 
    belongs_to :tech, inverse_of: :services 
    belongs_to :service_menu, inverse_of :services 
end 

class ServiceMenu < ActiveRecord::Base 
    has_many :services, inverse_of: :service_menu 
end 

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

Короче говоря, если вы добавите соответствующие отношения к вашим моделям (как указано выше), вам не придется беспокоиться о чем-либо подобном. Это красота объектно-ориентированного программирования.

Пожалуйста, обратите внимание: как текущая структура модели установлена, вы будете нуждаться внешних ключей, ссылающихся на вашем Service классе, и для Tech класса, а также ServiceMenu класса. Это миграция будет выглядеть примерно так:

rails generate migration AddTechAndServiceMenuRefToServices tech:references service_menu:references 

, что миграция будет добавлять как tech_id и service_menu_id столбцы в Service класса, создавая тем самым правильное соотношение между вашими различными моделями.

+0

Привет, Коллин, я очень ценю ваш ответ. Я добавил все, что вы упомянули, кроме переноса. Поскольку у меня уже есть внешний ключ 'tech' от предыдущей миграции, я выполнил следующее: add_service_menu_ref_to_services, который создал' add_reference: services,: service_menu, index: true' и 'add_foreign_key: services,: service_menus, после:: name '. Я перезапустил сервер и выполнил несколько инструкций, но, к сожалению, не смог добиться желаемых результатов. –

+0

Я думаю, что я могу столкнуться с тем, что я использую '@service = ** current_tech **. Services.build'. Поскольку я создаю новую службу как 'current_tech' (помощник Devise), только к' tech_id' будет применен к 'services' db, но не к' service_id'. Похоже, я могу Опять же, я ценю вашу помощь. Закрытие, которое я достиг для достижения желаемых результатов, использует это: 'Service.where (name: @temp_var) .update_all (имя: @ service_menu.name)' _where clause_ не распознает vars, а скорее фактическое " stings " –

0

Эти имена моделей ServiceMenu и Service действительно запутывают в этом контексте и, вероятно, должны быть Service и RenderedService соответственно.Сказав это, давайте посмотрим, что вам нужно, чтобы заставить это работать без, требуя этого утверждения обновления вообще.

Добавьте следующие соотношения в смеси:.

class ServiceMenu < ActiveRecord::Base 
    has_many :services 
end 

class Service < ActiveRecord::Base 
    belongs_to :service_menu 
    belongs_to :tech 
end 

class Tech < ActiveRecord::Base 
    has_many :services 
end 

Модель Сервис в настоящее время относится к ServiceMenu, используя его имя, которое где ваша путаница приходит в Вместо названия, есть модель Service см ServiceMenu с помощью service_menu_id, создавая миграцию так:

rails generate migration AddServiceMenuIdToServices service_menu_id:references 

После того, как эти изменения сделаны вам необходимо настроить свой код, чтобы использовать новый столбец service_menu_id в модели сервиса.

Если раньше вы делали что-то вроде:

s = Service.new(name: 'Brakes', tech: Tech.find_by(name: 'Bob')) 

теперь вы должны сделать что-то вроде:

s = Service.new(service_menu: ServiceMenu.find_by(name: 'Brakes'), tech: Tech.find_by(name: 'Bob')) 

Saving s теперь будет сохранить ссылку на конкретный пункт ServiceMenu, который в настоящее время называется " Тормоза. Если вы измените имя этого конкретного элемента ServiceMenu в будущем на «Barkes», это изменение будет автоматически отражено в модели Service, поскольку оно больше не сохраняет имя пункта меню службы в служебной записи.

Если вы были ранее использовать что-то вроде:

s = Service.find(100) 
puts s.name 

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

s = Service.find(100) 
puts s.service_menu.name 

У вас по-прежнему будет поле имени в модели службы, которое необходимо удалить с помощью переноса. Если у вас есть данные в этой системе, вам нужно заполнить поле service_menu_id для всех моделей сервисов, используя данные в поле имени.

+0

Привет, Джейбед, спасибо за ваш ответ. «ServiceMenu» - это страница, содержащая единое меню транспортных средств, таких как тормоза, удары, глушитель и т. Д. «ServiceMenu» - это ограниченная страница, доступная только для администраторов. Я бы предпочел, чтобы «Techs» или кто-то еще не добавлял и не удалял пункты меню из этого меню.То, что вы упомянули, я уже имел на месте, кроме миграции 'service_menu_id'. Тем не менее, я был не приемлем для достижения желаемых результатов. Как упоминалось ниже в сообщении Collin, закрытие, которое я получил для достижения желаемых результатов, использует это в действии обновления 'service_menu': –

+0

' Service.where (name: @temp_var) .update_all (name: @ service_menu.name) ' 'temp_var' находится в действии' edit'. Однако _where clause_ не распознает vars, а скорее фактические «укусы», –