rexport 0.5.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.rdoc +1 -1
- data/Rakefile +6 -34
- data/app/views/export_filters/_export_filter.html.erb +2 -2
- data/app/views/export_items/_export_item.html.erb +4 -4
- data/app/views/exports/_edit.html.erb +2 -2
- data/app/views/exports/_filters.html.erb +1 -1
- data/app/views/exports/_form.html.erb +6 -6
- data/app/views/exports/_rexport_model.html.erb +1 -1
- data/app/views/exports/_show.html.erb +7 -7
- data/app/views/exports/edit.html.erb +1 -1
- data/app/views/exports/index.html.erb +5 -5
- data/app/views/exports/new.html.erb +2 -2
- data/app/views/exports/show.html.erb +1 -1
- data/config/routes.rb +6 -6
- data/db/migrate/20091105182959_create_export_tables.rb +3 -3
- data/lib/rexport.rb +3 -1
- data/lib/rexport/data_field.rb +17 -0
- data/lib/rexport/data_fields.rb +17 -133
- data/lib/rexport/export_filter_methods.rb +46 -24
- data/lib/rexport/export_filters_controller_methods.rb +8 -4
- data/lib/rexport/export_item_methods.rb +29 -34
- data/lib/rexport/export_items_controller_methods.rb +13 -13
- data/lib/rexport/export_methods.rb +160 -208
- data/lib/rexport/exports_controller_methods.rb +34 -35
- data/lib/rexport/rexport_model.rb +118 -0
- data/lib/rexport/tree_node.rb +13 -16
- data/lib/rexport/version.rb +1 -1
- data/test/factories.rb +58 -53
- data/test/test_helper.rb +36 -39
- data/test/unit/data_field_test.rb +11 -11
- data/test/unit/data_fields_test.rb +53 -95
- data/test/unit/export_filter_methods_test.rb +37 -0
- data/test/unit/export_item_methods_test.rb +21 -0
- data/test/unit/export_methods_test.rb +181 -59
- data/test/unit/rexport_model_test.rb +122 -20
- data/test/unit/tree_node_test.rb +20 -20
- metadata +25 -38
- data/test/jenkins.bash +0 -3
- data/test/log/test.log +0 -3891
@@ -1,34 +1,56 @@
|
|
1
1
|
module Rexport #:nodoc:
|
2
2
|
module ExportFilterMethods
|
3
|
-
|
4
|
-
base.class_eval do
|
5
|
-
include InstanceMethods
|
3
|
+
extend ActiveSupport::Concern
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
included do
|
6
|
+
belongs_to :export
|
7
|
+
validates_presence_of :filter_field
|
8
|
+
end
|
9
|
+
|
10
|
+
def display_value
|
11
|
+
filter_on_associated_object? ? associated_object_value : value
|
12
|
+
end
|
13
|
+
|
14
|
+
def attributes_for_copy
|
15
|
+
attributes.slice('filter_field', 'value')
|
10
16
|
end
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
return '
|
21
|
-
begin
|
22
|
-
object = association.klass.find(value)
|
23
|
-
return object.respond_to?(:name) ? object.name : object.to_s
|
24
|
-
rescue ActiveRecord::RecordNotFound
|
25
|
-
return 'ASSOCIATED OBJECT NOT FOUND'
|
26
|
-
end
|
18
|
+
private
|
19
|
+
|
20
|
+
def associated_object_value
|
21
|
+
return 'UNDEFINED ASSOCIATION' unless filter_association
|
22
|
+
begin
|
23
|
+
object = filter_association.klass.find(value)
|
24
|
+
return object.respond_to?(:name) ? object.name : object.to_s
|
25
|
+
rescue ActiveRecord::RecordNotFound
|
26
|
+
return 'ASSOCIATED OBJECT NOT FOUND'
|
27
27
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
end
|
29
|
+
|
30
|
+
def filter_association
|
31
|
+
@filter_on_assocation ||= find_filter_association
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_filter_association
|
35
|
+
belongs_to_associations.detect do |association|
|
36
|
+
association.foreign_key == filter_foreign_key
|
31
37
|
end
|
32
38
|
end
|
39
|
+
|
40
|
+
def belongs_to_associations
|
41
|
+
export.get_klass_from_path(filter_path).reflect_on_all_associations(:belongs_to)
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter_path
|
45
|
+
filter_field.split('.')[0..-2]
|
46
|
+
end
|
47
|
+
|
48
|
+
def filter_foreign_key
|
49
|
+
filter_field.split('.').last
|
50
|
+
end
|
51
|
+
|
52
|
+
def filter_on_associated_object?
|
53
|
+
filter_field[/_id$/]
|
54
|
+
end
|
33
55
|
end
|
34
56
|
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
module Rexport
|
2
2
|
module ExportFiltersControllerMethods
|
3
3
|
def destroy
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
export_filter.destroy
|
5
|
+
redirect_to export_filter.export
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def export_filter
|
11
|
+
@export_filter ||= ExportFilter.find(params[:id])
|
8
12
|
end
|
9
13
|
end
|
10
14
|
end
|
@@ -1,45 +1,40 @@
|
|
1
1
|
module Rexport #:nodoc:
|
2
2
|
module ExportItemMethods
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
acts_as_list scope: :export
|
7
|
+
|
8
|
+
belongs_to :export
|
9
|
+
|
10
|
+
before_validation :replace_blank_name_with_rexport_field
|
11
|
+
validates_presence_of :name, :rexport_field
|
12
|
+
|
13
|
+
scope :ordered, -> { order :position }
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
module ClassMethods
|
17
17
|
def resort(export_item_ids)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
transaction do
|
19
|
+
export_item_ids.each_with_index do |id, index|
|
20
|
+
find(id.gsub(/[^0-9]/, '')).update_attribute(:position, index + 1)
|
21
|
+
end
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
rexport_field.split('.').values_at(-2..-1).map {|v| v.titleize}.join(' - ')
|
39
|
-
else
|
40
|
-
rexport_field.titleize
|
41
|
-
end
|
42
|
-
end
|
25
|
+
|
26
|
+
def attributes_for_copy
|
27
|
+
attributes.slice('position', 'name', 'rexport_field')
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def replace_blank_name_with_rexport_field
|
33
|
+
self.name = generate_name_from_rexport_field if name.blank?
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_name_from_rexport_field
|
37
|
+
rexport_field.split('.').last(2).map(&:titleize).join(' - ')
|
43
38
|
end
|
44
39
|
end
|
45
40
|
end
|
@@ -1,28 +1,28 @@
|
|
1
1
|
module Rexport
|
2
2
|
module ExportItemsControllerMethods
|
3
3
|
def edit
|
4
|
-
|
4
|
+
export_item
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def update
|
8
|
-
|
9
|
-
|
10
|
-
if @export_item.update_attributes(export_item_params)
|
11
|
-
redirect_to export_path(@export_item.export), notice: 'ExportItem was successfully updated.'
|
8
|
+
if export_item.update(export_item_params)
|
9
|
+
redirect_to export_path(export_item.export), notice: 'ExportItem was successfully updated.'
|
12
10
|
else
|
13
11
|
render :edit
|
14
12
|
end
|
15
13
|
end
|
16
|
-
|
14
|
+
|
17
15
|
def destroy
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
redirect_to export_path(@export_item.export)
|
16
|
+
export_item.destroy
|
17
|
+
redirect_to export_path(export_item.export)
|
22
18
|
end
|
23
|
-
|
19
|
+
|
24
20
|
private
|
25
|
-
|
21
|
+
|
22
|
+
def export_item
|
23
|
+
@export_item ||= ExportItem.find(params[:id])
|
24
|
+
end
|
25
|
+
|
26
26
|
def export_item_params
|
27
27
|
params.require(:export_item).permit(:name)
|
28
28
|
end
|
@@ -1,272 +1,224 @@
|
|
1
1
|
require 'csv'
|
2
2
|
|
3
3
|
module Rexport #:nodoc:
|
4
|
+
module ExportMethods
|
5
|
+
extend ActiveSupport::Concern
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
attr_accessor :klass, :path
|
9
|
-
|
10
|
-
def initialize(klass, path = nil)
|
11
|
-
self.klass = klass
|
12
|
-
self.path = path.to_s unless path.blank?
|
13
|
-
end
|
14
|
-
|
15
|
-
def rexport_fields_array
|
16
|
-
klass.rexport_fields_array
|
17
|
-
end
|
18
|
-
|
19
|
-
def field_path(field_name)
|
20
|
-
[path, field_name].compact * '.'
|
21
|
-
end
|
22
|
-
|
23
|
-
def collection_from_association(association)
|
24
|
-
return klass.send("find_#{association}_for_rexport") if klass.respond_to?("find_#{association}_for_rexport")
|
25
|
-
klass.reflect_on_association(association.to_sym).klass.all
|
26
|
-
end
|
7
|
+
included do
|
8
|
+
has_many :export_items, dependent: :destroy
|
9
|
+
has_many :export_filters, dependent: :destroy
|
27
10
|
|
28
|
-
|
29
|
-
return field.method unless field.method.include?('.')
|
30
|
-
association = field.method.split('.').first
|
31
|
-
klass.reflect_on_association(association.to_sym).foreign_key
|
32
|
-
end
|
11
|
+
validates_presence_of :name, :model_class_name
|
33
12
|
|
34
|
-
|
35
|
-
klass.name
|
36
|
-
end
|
37
|
-
end
|
13
|
+
after_save :save_export_items
|
38
14
|
|
39
|
-
|
40
|
-
|
41
|
-
base.extend ClassMethods
|
42
|
-
base.class_eval do
|
43
|
-
include InstanceMethods
|
44
|
-
|
45
|
-
has_many :export_items, :dependent => :destroy
|
46
|
-
has_many :export_filters, :dependent => :destroy
|
47
|
-
validates_presence_of :name, :model_class_name
|
48
|
-
after_save :save_export_items
|
49
|
-
scope :alphabetical, -> { order :name }
|
50
|
-
scope :categorical, -> { order :model_class_name }
|
51
|
-
scope :by_model, ->(model_class_name) { where(model_class_name: model_class_name) }
|
52
|
-
end
|
15
|
+
scope :alphabetical, -> { order :name }
|
16
|
+
scope :categorical, -> { order :model_class_name }
|
53
17
|
end
|
54
18
|
|
55
19
|
module ClassMethods
|
56
20
|
def models
|
57
21
|
%w(override_this_method)
|
58
22
|
end
|
59
|
-
|
60
|
-
def enabled
|
61
|
-
find(:all).select {|export| export.enabled? }
|
62
|
-
end
|
63
23
|
end
|
64
24
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
25
|
+
def full_name
|
26
|
+
"#{model_class_name.pluralize} - #{name}"
|
27
|
+
end
|
69
28
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
29
|
+
# Returns a string with the export data
|
30
|
+
def to_s
|
31
|
+
String.new.tap do |result|
|
32
|
+
result << header * '|' << "\n"
|
33
|
+
records.each do |record|
|
34
|
+
result << record * '|' << "\n"
|
77
35
|
end
|
78
36
|
end
|
37
|
+
end
|
79
38
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
39
|
+
# Returns a csv string with the export data
|
40
|
+
def to_csv(objects = nil)
|
41
|
+
seed_records(objects) unless objects.nil?
|
42
|
+
CSV.generate do |csv|
|
43
|
+
csv << header
|
44
|
+
records.each do |record|
|
45
|
+
csv << record
|
88
46
|
end
|
89
47
|
end
|
48
|
+
end
|
90
49
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
50
|
+
# Returns an array with the header names from the associated export_items
|
51
|
+
def header
|
52
|
+
export_items.ordered.map(&:name)
|
53
|
+
end
|
95
54
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
55
|
+
# Returns the export model class
|
56
|
+
def export_model
|
57
|
+
model_class_name.constantize
|
58
|
+
end
|
100
59
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
60
|
+
# Returns a RexportModel for the current export_model
|
61
|
+
def rexport_model
|
62
|
+
@rexport_model ||= RexportModel.new(export_model)
|
63
|
+
end
|
105
64
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
65
|
+
# Returns an array of RexportModels including export_model and associated rexport capable models
|
66
|
+
def rexport_models
|
67
|
+
@rexport_models ||= get_rexport_models(export_model)
|
68
|
+
end
|
110
69
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
70
|
+
# Returns the records for the export
|
71
|
+
def records
|
72
|
+
@records ||= get_records
|
73
|
+
end
|
115
74
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
75
|
+
# Returns a limited number of records for the export
|
76
|
+
def sample_records
|
77
|
+
get_records(Rexport::SAMPLE_SIZE)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a class based on a path array
|
81
|
+
def get_klass_from_path(path, klass = export_model)
|
82
|
+
return klass unless (association_name = path.shift)
|
83
|
+
get_klass_from_path(path, klass.reflect_on_association(association_name.to_sym).klass)
|
84
|
+
end
|
121
85
|
|
122
|
-
|
123
|
-
|
86
|
+
def has_rexport_field?(rexport_field)
|
87
|
+
rexport_fields.include?(rexport_field)
|
88
|
+
end
|
89
|
+
|
90
|
+
def rexport_fields=(rexport_fields)
|
91
|
+
@rexport_fields = if rexport_fields.respond_to?(:keys)
|
92
|
+
@set_position = false
|
93
|
+
rexport_fields.keys.map(&:to_s)
|
94
|
+
else
|
95
|
+
@set_position = true
|
96
|
+
rexport_fields.map(&:to_s)
|
124
97
|
end
|
98
|
+
end
|
125
99
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
100
|
+
def export_filter_attributes=(attributes)
|
101
|
+
attributes.each do |field, value|
|
102
|
+
if value.blank?
|
103
|
+
filter = export_filters.find_by(filter_field: field)
|
104
|
+
filter.destroy if filter
|
105
|
+
elsif new_record?
|
106
|
+
export_filters.build(filter_field: field, value: value)
|
130
107
|
else
|
131
|
-
|
132
|
-
|
108
|
+
filter = export_filters.find_or_create_by(filter_field: field)
|
109
|
+
filter.update_attribute(:value, value)
|
133
110
|
end
|
134
111
|
end
|
112
|
+
end
|
135
113
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
filter = export_filters.find_by(filter_field: field)
|
140
|
-
filter.destroy if filter
|
141
|
-
elsif new_record?
|
142
|
-
export_filters.build(:filter_field => field, :value => value)
|
143
|
-
else
|
144
|
-
filter = export_filters.find_or_create_by(filter_field: field)
|
145
|
-
filter.update_attribute(:value, value)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
114
|
+
def filter_value(filter_field)
|
115
|
+
export_filters.detect { |f| f.filter_field == filter_field }&.value
|
116
|
+
end
|
149
117
|
|
150
|
-
|
151
|
-
|
152
|
-
|
118
|
+
def copy
|
119
|
+
self.class.create(attributes_for_copy) do |new_export|
|
120
|
+
export_items.ordered.each { |item| new_export.export_items.build(item.attributes_for_copy) }
|
121
|
+
export_filters.each { |filter| new_export.export_filters.build(filter.attributes_for_copy) }
|
153
122
|
end
|
123
|
+
end
|
154
124
|
|
155
|
-
|
156
|
-
self.class.create(attributes_for_copy) do |new_export|
|
157
|
-
export_items.ordered.each { |item| new_export.export_items.build(item.attributes_for_copy) }
|
158
|
-
export_filters.each { |filter| new_export.export_filters.build(filter.attributes_for_copy) }
|
159
|
-
end
|
160
|
-
end
|
125
|
+
private
|
161
126
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
end
|
127
|
+
def get_records(limit = nil)
|
128
|
+
get_export_values(export_model.where(build_conditions).includes(build_include).limit(limit))
|
129
|
+
end
|
166
130
|
|
167
|
-
|
168
|
-
|
169
|
-
|
131
|
+
def seed_records(objects)
|
132
|
+
@records = get_export_values(objects)
|
133
|
+
end
|
170
134
|
|
171
|
-
|
172
|
-
|
173
|
-
|
135
|
+
def get_export_values(objects)
|
136
|
+
objects.map { |object| object.export(rexport_methods) }
|
137
|
+
end
|
174
138
|
|
175
|
-
|
176
|
-
|
139
|
+
def get_rexport_models(model, results = [], path = nil)
|
140
|
+
return unless model.include?(Rexport::DataFields)
|
141
|
+
results << RexportModel.new(model, path: path)
|
142
|
+
get_associations(model).each do |associated_model|
|
143
|
+
# prevent infinite loop by checking if this class is already in the results set
|
144
|
+
next if results.detect { |result| result.klass == associated_model.klass }
|
145
|
+
get_rexport_models(associated_model.klass, results, [path, associated_model.name].compact * '.')
|
177
146
|
end
|
147
|
+
return results
|
148
|
+
end
|
178
149
|
|
179
|
-
|
180
|
-
|
181
|
-
|
150
|
+
def get_associations(model)
|
151
|
+
%i(belongs_to has_one).map do |type|
|
152
|
+
model.reflect_on_all_associations(type)
|
153
|
+
end.flatten.reject(&:polymorphic?)
|
154
|
+
end
|
182
155
|
|
183
|
-
|
184
|
-
|
156
|
+
def build_include
|
157
|
+
root = Rexport::TreeNode.new('root')
|
158
|
+
(rexport_methods + filter_fields).select {|m| m.include?('.')}.each do |method|
|
159
|
+
root.add_child(method.split('.').values_at(0..-2))
|
185
160
|
end
|
161
|
+
root.to_include
|
162
|
+
end
|
186
163
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
# prevent infinite loop by checking if this class is already in the result set
|
192
|
-
unless result.detect { |rexport_model| rexport_model.klass == associated_model.klass }
|
193
|
-
get_rexport_models(associated_model.klass, result, [path, associated_model.name].compact * '.')
|
194
|
-
end
|
164
|
+
def build_conditions
|
165
|
+
Hash.new.tap do |conditions|
|
166
|
+
export_filters.each do |filter|
|
167
|
+
conditions[get_database_field(filter.filter_field)] = filter.value
|
195
168
|
end
|
196
|
-
return result
|
197
|
-
end
|
198
|
-
|
199
|
-
def get_associations(rexport_model)
|
200
|
-
(rexport_model.reflect_on_all_associations(:belongs_to) + rexport_model.reflect_on_all_associations(:has_one)).reject(&:polymorphic?)
|
201
169
|
end
|
170
|
+
end
|
202
171
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
root.to_include
|
209
|
-
end
|
172
|
+
def get_database_field(field)
|
173
|
+
path = field.split('.')
|
174
|
+
field = path.pop
|
175
|
+
"#{get_klass_from_path(path).table_name}.#{field}"
|
176
|
+
end
|
210
177
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
conditions[get_database_field(filter.filter_field)] = filter.value
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
178
|
+
def rexport_methods
|
179
|
+
@rexport_methods ||= rexport_model.get_rexport_methods(ordered_rexport_fields)
|
180
|
+
end
|
218
181
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
"#{get_klass_from_path(path).table_name}.#{field}"
|
223
|
-
end
|
182
|
+
def rexport_fields
|
183
|
+
@rexport_fields ||= export_items.map(&:rexport_field)
|
184
|
+
end
|
224
185
|
|
225
|
-
|
226
|
-
|
227
|
-
|
186
|
+
def ordered_rexport_fields
|
187
|
+
export_items.ordered.map(&:rexport_field)
|
188
|
+
end
|
228
189
|
|
229
|
-
|
230
|
-
|
231
|
-
|
190
|
+
def filter_fields
|
191
|
+
export_filters.map(&:filter_field)
|
192
|
+
end
|
232
193
|
|
233
|
-
|
234
|
-
|
194
|
+
def save_export_items
|
195
|
+
export_items.each do |export_item|
|
196
|
+
unless rexport_fields.include?(export_item.rexport_field)
|
197
|
+
export_item.destroy
|
198
|
+
end
|
235
199
|
end
|
236
200
|
|
237
|
-
|
238
|
-
|
201
|
+
position = 0
|
202
|
+
rexport_fields.each do |rexport_field|
|
203
|
+
position += 1
|
204
|
+
export_item = export_items.detect { |i| i.rexport_field == rexport_field } || export_items.create(rexport_field: rexport_field)
|
205
|
+
export_item.update_attribute(:position, position) if set_position
|
239
206
|
end
|
240
207
|
|
241
|
-
|
242
|
-
|
243
|
-
unless rexport_fields.include?(export_item.rexport_field)
|
244
|
-
export_item.destroy
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
export_items.reset
|
208
|
+
return true
|
209
|
+
end
|
249
210
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
export_item = export_items.detect {|i| i.rexport_field == rexport_field } || export_items.create(:rexport_field => rexport_field)
|
254
|
-
export_item.update_attribute(:position, position) if @set_position && export_item.position != position
|
255
|
-
end
|
211
|
+
def attributes_for_copy
|
212
|
+
attributes.slice('model_class_name', 'description').merge(name: find_unique_name(name))
|
213
|
+
end
|
256
214
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
def attributes_for_copy
|
263
|
-
attributes.slice('model_class_name', 'description').merge(name: find_unique_name(self.name))
|
264
|
-
end
|
215
|
+
def find_unique_name(original_name, suffix = 0)
|
216
|
+
new_name = suffix == 0 ? "#{original_name} Copy" : "#{original_name} Copy [#{suffix}]"
|
217
|
+
self.class.find_by(name: new_name) ? find_unique_name(original_name, suffix += 1) : new_name
|
218
|
+
end
|
265
219
|
|
266
|
-
|
267
|
-
|
268
|
-
self.class.find_by(name: new_name) ? find_unique_name(original_name, suffix += 1) : new_name
|
269
|
-
end
|
220
|
+
def set_position
|
221
|
+
@set_position ||= false
|
270
222
|
end
|
271
223
|
end
|
272
224
|
end
|