Ruby on rails Rails—如何更新记录,然后根据被修改记录的值动态更新另一个模型上的值?
问题 假设我有一个名为Ruby on rails Rails—如何更新记录,然后根据被修改记录的值动态更新另一个模型上的值?,ruby-on-rails,ruby,Ruby On Rails,Ruby,问题 假设我有一个名为ServiceMenu的脚手架,它只包含一个下拉菜单,其中有三个值:刹车、刹车片和消音器。 我有一个Service模型,它将属于用户的所有服务存储在一个名为Tech的模型上。每个技术都能够将维修_菜单中的任何一个(制动器、刹车片和消声器)添加到其数据库配置文件中,该配置文件称为维修 我所看到的问题是,如果我更新了维修菜单中的任何一个名称,比如从Brakse到Brakes,技术人员的配置文件中仍然会有旧的维修菜单名称。我会发现,由于输入错误或只是想更新服务菜单名称,我会做很多
ServiceMenu
的脚手架,它只包含一个下拉菜单,其中有三个值:刹车、刹车片和消音器。
我有一个Service
模型,它将属于用户的所有服务存储在一个名为Tech
的模型上。每个技术
都能够将维修_菜单
中的任何一个(制动器、刹车片和消声器)添加到其数据库配置文件中,该配置文件称为维修
我所看到的问题是,如果我更新了维修菜单
中的任何一个名称,比如从Brakse到Brakes,技术人员
的配置文件中仍然会有旧的维修菜单
名称。我会发现,由于输入错误或只是想更新服务菜单
名称,我会做很多家务工作来更新1000多条记录
文件 服务菜单.rb
class ServiceMenu < ActiveRecord::Base
has_many :services
end
class Service < ActiveRecord::Base
belongs_to :tech
belongs_to :service_menu
end
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
服务控制器
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
问题 我如何执行将
服务
数据库中的多条记录动态更新为服务菜单
中更新名称的任务?
顺序如下:
- 更新
上从输入错误Brakse到Brakes的记录维修菜单
- 更新
上的记录后,Rails将在服务菜单
数据库中找到服务
列中所有=Brakse的值名称
- 将
列中的所有Brakse值更新为Brakesname
编辑 每当我更新
服务菜单
下拉菜单上的任何内容时,请执行类似操作
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**")
请就如何完成这一点提供帮助。
非常感谢您的帮助。除非我遗漏了问题的一些细微差别,否则您只需将服务项目从Brakse重命名为Brake即可——关联将保持有效 当然,这假设
services
表有一个name
字段,但是如果不查看您的模式,就很难知道
如果这不是正确答案,请显示整个模式,而不仅仅是关联 在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
rails generate migration AddTechAndServiceMenuRefToServices tech:references service_menu:references
该迁移将把
tech\u id
和service\u menu\u id
列添加到service
类中,从而在不同的模型之间建立适当的关系 这些模型名称ServiceMenu和Service在此上下文中非常容易混淆,应该分别为Service和RenderService。话虽如此,让我们看看在根本不需要update语句的情况下,您需要什么来让它工作
将以下关系添加到组合中:
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
一旦进行了这些更改,您就需要调整代码以使用服务模型中的新服务菜单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'))
s = Service.find(100)
puts s.name
s = Service.find(100)
puts s.service_menu.name
您现在应该执行以下操作:
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'))
s = Service.find(100)
puts s.name
s = Service.find(100)
puts s.service_menu.name
保存s将保存对当前称为“制动器”的特定维修菜单项的引用。如果将来将此特定服务菜单项的名称更改为“Barkes”,则此更改将自动反映在服务模型中,因为它不再将服务菜单项的名称存储在服务记录中
如果您以前使用过类似以下内容:
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'))
s = Service.find(100)
puts s.name
s = Service.find(100)
puts s.service_menu.name
要检索服务所引用的服务菜单项的名称,现在您可以使用如下内容:
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'))
s = Service.find(100)
puts s.name
s = Service.find(100)
puts s.service_menu.name
在服务模型中仍然有一个名称字段,需要使用迁移删除该字段。如果此系统中存在数据,则需要使用名称字段中的数据填充所有服务模型的服务菜单id字段。我已添加了与此帖子相关的架构内容。迁移更像是一个手动过程。我正在寻找一个更具活力的解决方案。我还提供了更多细节。嗨,贾维德,谢谢你的回复。
维修菜单
是一个包含单个车辆项目菜单的页面,如制动器、减震器、消音器等。。。。服务菜单
是一个受限页面,仅管理员可以访问。我希望Techs
或其他任何人不要在此菜单中添加或删除菜单项。您提到的,除了服务菜单\u id
迁移之外,我已经准备好了。然而,我未能达到预期的结果。正如下面柯林的帖子中所提到的,我在service\u菜单
更新操作中使用了这个选项:service.where(name:@temp\u var).update\u all(name:@service\u menu.name)
在编辑
操作中使用了这个选项。然而,where子句不识别VAR,而是实际的“stings”嗨,科林,我非常感谢你的回答。除了迁移,我已经添加了您提到的所有内容。因为我已经有了上一次迁移中的tech
外键,所以我改为执行以下操作:在创建add\u reference:services、:service\u menu、index:true
和add\u外键:services、:service\u menu之后,在::name
之后添加服务。我已重新启动服务器并多次执行您的指示,但不幸的是无法达到预期的结果。我想我可能遇到的是,我正在使用@service=**current_tech**.services.build
。由于我正在创建一个新服务作为当前的\u tech
(设计助手),因此只有技术id
将应用于服务
数据库,而不是服务id
。看来我可以再次感谢你的帮助。我得到的最后结果