rails_to 重复记录
rails_to for a duplicate record
以下代码在控制台中运行良好,并且做我想做的(第一行就可以,其他只是模拟更改。实际上它是真实的,这些是唯一需要的更改):
irb(main):012:0> year = Year.find(678).dup
Year Load (0.4ms) SELECT "years".* FROM "years" WHERE "years"."id" = ORDER BY "years"."year_date" ASC LIMIT [["id", 678], ["LIMIT", 1]]
=> #<Year id: nil, year_date: "1905-09-01", created_at: nil, updated_at: nil, resto: false, resid: true, file_basename: nil, person_id: 86, location_id: 95, title: "Resident", notes: "", resto_name: "", aws_url: nil, from_where_url: nil, caption: nil, croatian: true, from_where: nil, doc_id: 66>
irb(main):013:0> year.location_id = 211
=> 211
irb(main):014:0> year.resto = true
=> true
irb(main):015:0> year.resid = false
=> false
irb(main):016:0> year.title = "Co-proprietor"
=> "Co-proprietor"
irb(main):017:0> year.save
(0.3ms) BEGIN
Location Load (0.5ms) SELECT "locations".* FROM "locations" WHERE "locations"."id" = LIMIT [["id", 211], ["LIMIT", 1]]
Person Load (0.3ms) SELECT "people".* FROM "people" WHERE "people"."id" = LIMIT [["id", 86], ["LIMIT", 1]]
Doc Load (0.2ms) SELECT "docs".* FROM "docs" WHERE "docs"."id" = LIMIT [["id", 66], ["LIMIT", 1]]
Year Create (5.3ms) INSERT INTO "years" ("year_date", "created_at", "updated_at", "resto", "resid", "person_id", "location_id", "title", "notes", "resto_name", "croatian", "doc_id") VALUES (, , , , , , , , , , , ) RETURNING "id" [["year_date", "1905-09-01"], ["created_at", "2020-05-10 15:12:37.102224"], ["updated_at", "2020-05-10 15:12:37.102224"], ["resto", true], ["resid", false], ["person_id", 86], ["location_id", 211], ["title", "Co-proprietor"], ["notes", ""], ["resto_name", ""], ["croatian", true], ["doc_id", 66]]
(40.9ms) COMMIT
=> true
当然,我会在 edit
或 new
页面中进行更改。我只希望使用我所在的 show
页面中信息的副本创建该页面。用例是创建一堆记录,许多记录几乎是重复的,但确实需要手动完成,因为没有更改信息的模式。
我创建了各种按钮,但没有任何效果
<%= link_to 'Duplicate this connection (FIXME)', new_year_path(@year.dup), action: dup %>
与:
def dup
@year = Year.find(params[:id]).dup
end
另一个迭代:<%= link_to 'Duplicate this connection (FIXME)', edit_year_path(@year.dup) %>
No route matches {:action=>"edit", :controller=>"years", :id=>nil}, missing required keys: [:id]
我对此迷路了,但可能没那么难。
当您在此处对 ActiveRecord 模型对象调用 #.dup
时,它会复制除 id
和基本时间戳之外的所有属性。这意味着您有一个未持久化的对象。这就是您收到异常消息的原因。
假设您要复制记录 678,比方说,我期望这样的路径:
/years/new?base_id=678
在上面,base_id=678
是查询字符串参数。
你会像这样生成它:
<%= link_to "Duplicate", new_year_path(base_id: @year&.id) %>
(当然假设@year
已经初始化)
然后,在您的控制器操作中:
def new
@year = Year.find_by(id: params[:base_id])&.dup || Year.new
end
假设我们找到有问题的 Year
记录,我们复制它。否则,我们回退到一个新的 Year
对象,一切都很好。
这应该可以解决您的问题。
搜索要复制的记录,调用attributes
获取所有属性键值,丢弃时间戳列并将其传递给create
方法以创建记录。
def dup
year = Year.find(params[:id])
@year = Year.create!(year.attributes.except("created_at", "updated_at"))
end
resources :years do
get :duplicate
end
class Year < ApplicationRecord
# creates a new instance of year with a a subset of the attributes
# @return [Year]
def duplicate
# attributes returns a hash with string keys
whitelist = %w( foo bar baz )
self.class.new(attributes.slice(*whitelist))
end
end
class YearsController < ApplicationController
# ...
# GET /years/:id/duplicate
def duplicate
@year = Year.find(:id).duplicate
render :new
end
# ...
end
将要复制的属性列入白名单而不是列入黑名单可能是个好主意。
以下代码在控制台中运行良好,并且做我想做的(第一行就可以,其他只是模拟更改。实际上它是真实的,这些是唯一需要的更改):
irb(main):012:0> year = Year.find(678).dup
Year Load (0.4ms) SELECT "years".* FROM "years" WHERE "years"."id" = ORDER BY "years"."year_date" ASC LIMIT [["id", 678], ["LIMIT", 1]]
=> #<Year id: nil, year_date: "1905-09-01", created_at: nil, updated_at: nil, resto: false, resid: true, file_basename: nil, person_id: 86, location_id: 95, title: "Resident", notes: "", resto_name: "", aws_url: nil, from_where_url: nil, caption: nil, croatian: true, from_where: nil, doc_id: 66>
irb(main):013:0> year.location_id = 211
=> 211
irb(main):014:0> year.resto = true
=> true
irb(main):015:0> year.resid = false
=> false
irb(main):016:0> year.title = "Co-proprietor"
=> "Co-proprietor"
irb(main):017:0> year.save
(0.3ms) BEGIN
Location Load (0.5ms) SELECT "locations".* FROM "locations" WHERE "locations"."id" = LIMIT [["id", 211], ["LIMIT", 1]]
Person Load (0.3ms) SELECT "people".* FROM "people" WHERE "people"."id" = LIMIT [["id", 86], ["LIMIT", 1]]
Doc Load (0.2ms) SELECT "docs".* FROM "docs" WHERE "docs"."id" = LIMIT [["id", 66], ["LIMIT", 1]]
Year Create (5.3ms) INSERT INTO "years" ("year_date", "created_at", "updated_at", "resto", "resid", "person_id", "location_id", "title", "notes", "resto_name", "croatian", "doc_id") VALUES (, , , , , , , , , , , ) RETURNING "id" [["year_date", "1905-09-01"], ["created_at", "2020-05-10 15:12:37.102224"], ["updated_at", "2020-05-10 15:12:37.102224"], ["resto", true], ["resid", false], ["person_id", 86], ["location_id", 211], ["title", "Co-proprietor"], ["notes", ""], ["resto_name", ""], ["croatian", true], ["doc_id", 66]]
(40.9ms) COMMIT
=> true
当然,我会在 edit
或 new
页面中进行更改。我只希望使用我所在的 show
页面中信息的副本创建该页面。用例是创建一堆记录,许多记录几乎是重复的,但确实需要手动完成,因为没有更改信息的模式。
我创建了各种按钮,但没有任何效果
<%= link_to 'Duplicate this connection (FIXME)', new_year_path(@year.dup), action: dup %>
与:
def dup
@year = Year.find(params[:id]).dup
end
另一个迭代:<%= link_to 'Duplicate this connection (FIXME)', edit_year_path(@year.dup) %>
No route matches {:action=>"edit", :controller=>"years", :id=>nil}, missing required keys: [:id]
我对此迷路了,但可能没那么难。
当您在此处对 ActiveRecord 模型对象调用 #.dup
时,它会复制除 id
和基本时间戳之外的所有属性。这意味着您有一个未持久化的对象。这就是您收到异常消息的原因。
假设您要复制记录 678,比方说,我期望这样的路径:
/years/new?base_id=678
在上面,base_id=678
是查询字符串参数。
你会像这样生成它:
<%= link_to "Duplicate", new_year_path(base_id: @year&.id) %>
(当然假设@year
已经初始化)
然后,在您的控制器操作中:
def new
@year = Year.find_by(id: params[:base_id])&.dup || Year.new
end
假设我们找到有问题的 Year
记录,我们复制它。否则,我们回退到一个新的 Year
对象,一切都很好。
这应该可以解决您的问题。
搜索要复制的记录,调用attributes
获取所有属性键值,丢弃时间戳列并将其传递给create
方法以创建记录。
def dup
year = Year.find(params[:id])
@year = Year.create!(year.attributes.except("created_at", "updated_at"))
end
resources :years do
get :duplicate
end
class Year < ApplicationRecord
# creates a new instance of year with a a subset of the attributes
# @return [Year]
def duplicate
# attributes returns a hash with string keys
whitelist = %w( foo bar baz )
self.class.new(attributes.slice(*whitelist))
end
end
class YearsController < ApplicationController
# ...
# GET /years/:id/duplicate
def duplicate
@year = Year.find(:id).duplicate
render :new
end
# ...
end
将要复制的属性列入白名单而不是列入黑名单可能是个好主意。