[英]Bulk insert using one model
我正在嘗試使用textarea和一個Submit按鈕創建一個表單,該表單將允許用戶進行批量插入。 例如,輸入看起來像這樣:
0001;MR A
0002;MR B
結果將如下所示:
mysql> select * from members;
+------+------+------+
| id | no | name |
+------+------+------+
| 1 | 0001 | MR A |
+------+------+------+
| 2 | 0002 | MR B |
+------+------+------+
我是Rails的新手,我不確定如何進行此操作。 我應該使用attr_accessor
嗎? 如何在表單視圖中處理驗證失敗? 有什么例子嗎? 提前致謝。
更新資料
基於MissingHandle的評論,我創建了一個Scaffold並將其代碼替換為:
class MemberBulk < ActiveRecord::Base
attr_accessor :member
def self.columns
@columsn ||= []
end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
end
column :data, :text
validates :data, :create_members, :presence => true
def create_members
rows = self.data.split("\r\n")
@member = Array.new
rows.each_with_index { |row, i|
rows[i] = row.strip
cols = row.split(";")
p = Member.new
p.no = cols[0]
p.name = cols[1]
if p.valid?
member << p
else
p.errors.map { |k, v| errors.add(:data, "\"#{row}\" #{v}") }
end
}
end
def create_or_update
member.each { |p|
p.save
}
end
end
我知道代碼還遠遠不夠完整,但是我需要知道這是正確的方法嗎?
class MemberBulk < ActiveRecord::Base
#Tells Rails this is not actually tied to a database table
# or is it self.abstract_class = true
# or @abstract_class = true
# ?
abstract_class = true
# members holds array of members to be saved
# submitted_text is the data submitted in the form for a bulk update
attr_accessor :members, :submitted_text
attr_accessible :submitted_text
before_validation :build_members_from_text
def build_members_from_text
self.members = []
submitted_text.each_line("\r\n") do |member_as_text|
member_as_array = member_as_text.split(";")
self.members << Member.new(:number => member_as_array[0], :name => member_as_array[1])
end
end
def valid?
self.members.all?{ |m| m.valid? }
end
def save
self.members.all?{ |m| m.save }
end
end
class Member < ActiveRecord::Base
validates :number, :presence => true, :numericality => true
validates :name, :presence => true
end
因此,在此代碼中,成員是一個數組,該數組是單個成員對象的集合。 我的想法是,您要盡可能將工作交給Member類,因為該類實際上將綁定到數據庫表,並且可以在其上期待標准的Rails模型行為。 為了做到這一點,我重寫了所有ActiveRecord模型共有的兩種方法:save和有效。 MemberBulk僅在其所有成員均有效的情況下才有效,並且僅在所有成員均已保存時才視為已保存。 您可能還應該重寫errors方法,以返回其基礎成員的錯誤,並可能在所提交的文本中指出該成員的錯誤。
最后,我不得不從使用抽象類更改為活動模型(不知道為什么),但是當我升級到Rails v3.1時,它停止了工作。 這是工作代碼:
class MemberBulk
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :input, :data
validates :input, presence: true
def initialize(attributes = {})no
attributes.each do |name, value|
send("#{name}=", value) if respond_to?("#{name}=")
end
end
def persisted?
false
end
def save
unless self.valid?
return false
end
data = Array.new
# Check for spaces
input.strip.split("\r\n").each do |i|
if i.strip.empty?
errors.add(:input, "There shouldn't be any empty lines")
end
no, nama = i.strip.split(";")
if no.nil? or nama.nil?
errors.add(:input, "#{i} doesn't have no or name")
else
no.strip!
nama.strip!
if no.empty? or nama.empty?
errors.add(:input, "#{i} doesn't have no or name")
end
end
p = Member.new(no: no, nama: nama)
if p.valid?
data << p
else
p.errors.full_messages.each do |error|
errors.add(:input, "\"#{i}\": #{error}")
end
end
end # input.strip
if errors.empty?
if data.any?
begin
data.each do |d|
d.save
end
rescue Exception => e
raise ActiveRecord::Rollback
end
else
errors.add(:input, "No data to be processed")
return false
end
else
return false
end
end # def
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.