flexi_model 0.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.
- data/README.md +122 -0
- data/lib/discover.rb +11 -0
- data/lib/flexi_model/ar_models/collection.rb +15 -0
- data/lib/flexi_model/ar_models/field.rb +36 -0
- data/lib/flexi_model/ar_models/record.rb +31 -0
- data/lib/flexi_model/ar_models/value.rb +52 -0
- data/lib/flexi_model/ar_models.rb +10 -0
- data/lib/flexi_model/ar_persistence.rb +318 -0
- data/lib/flexi_model/ar_queryable.rb +239 -0
- data/lib/flexi_model/association.rb +303 -0
- data/lib/flexi_model/attachment_field.rb +20 -0
- data/lib/flexi_model/callbacks.rb +41 -0
- data/lib/flexi_model/fields.rb +290 -0
- data/lib/flexi_model/filter.rb +61 -0
- data/lib/flexi_model/stub_persistence.rb +24 -0
- data/lib/flexi_model/validations.rb +37 -0
- data/lib/flexi_model.rb +38 -0
- data/lib/generators/flexi_model/install/install_generator.rb +20 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_collections.rb +18 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_collections_fields.rb +11 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_fields.rb +20 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_records.rb +12 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_values.rb +17 -0
- metadata +92 -0
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
flexi-model
|
2
|
+
===========
|
3
|
+
|
4
|
+
[](https://codeclimate.com/github/we4tech/flexi-model)
|
5
|
+
|
6
|
+
Build flexible database model with dynamic fields (right now based on ActiveRecord soon it will work with mongoid too)
|
7
|
+
|
8
|
+
How to do ?
|
9
|
+
===========
|
10
|
+
|
11
|
+
Define your first model.
|
12
|
+
---------
|
13
|
+
```ruby
|
14
|
+
class User
|
15
|
+
include FlexiModel
|
16
|
+
_string :name, :email
|
17
|
+
_text :bio
|
18
|
+
validates_presence_of :name, :email
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
Create your new record.
|
23
|
+
------------
|
24
|
+
```ruby
|
25
|
+
User.create name: 'hasan', email: 'hasan@welltreat.us', bio: 'Ruby developer'
|
26
|
+
#=> #<User:...>
|
27
|
+
```
|
28
|
+
|
29
|
+
Find record by id.
|
30
|
+
-----------
|
31
|
+
```ruby
|
32
|
+
User.find(1)
|
33
|
+
```
|
34
|
+
|
35
|
+
Find records by name
|
36
|
+
--------
|
37
|
+
```ruby
|
38
|
+
User.where(name: 'hasan')
|
39
|
+
#=> #<...::Criteria...> # Instance of criteria object
|
40
|
+
```
|
41
|
+
|
42
|
+
Define belongs to and has many relationship
|
43
|
+
---------
|
44
|
+
```ruby
|
45
|
+
class Blog
|
46
|
+
include FlexiModel
|
47
|
+
_string :title
|
48
|
+
_text :content
|
49
|
+
belongs_to :user
|
50
|
+
end
|
51
|
+
|
52
|
+
class User
|
53
|
+
include FlexiModel
|
54
|
+
_string :name
|
55
|
+
has_many :blogs
|
56
|
+
end
|
57
|
+
|
58
|
+
# Create records
|
59
|
+
user = User.create(name: 'nafi')
|
60
|
+
Blog.create(title: 'Hello world', content: 'Hello content', user: user)
|
61
|
+
|
62
|
+
# Find all related blogs
|
63
|
+
user.blogs
|
64
|
+
|
65
|
+
# Find parent record
|
66
|
+
user.blogs.first.user
|
67
|
+
```
|
68
|
+
|
69
|
+
Define has and belongs to many relationships
|
70
|
+
-----------
|
71
|
+
```ruby
|
72
|
+
class User
|
73
|
+
inlude FlexiModel
|
74
|
+
_string :name
|
75
|
+
has_and_belongs_to_many :roles
|
76
|
+
end
|
77
|
+
|
78
|
+
class Role
|
79
|
+
include FlexiModel
|
80
|
+
_string :name
|
81
|
+
has_and_belongs_to_many :users
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create user with roles
|
85
|
+
User.create(name: 'khan', roles: [Role.create(name: 'admin'), Role.create(name: 'moderator')])
|
86
|
+
|
87
|
+
# Find user roles
|
88
|
+
user = User.where(name: 'khan').first
|
89
|
+
user.roles
|
90
|
+
```
|
91
|
+
|
92
|
+
Update attribute
|
93
|
+
---------
|
94
|
+
```ruby
|
95
|
+
user = User.where(...)
|
96
|
+
user.update_attribute :name, 'raju'
|
97
|
+
```
|
98
|
+
|
99
|
+
Update attributes
|
100
|
+
-----------
|
101
|
+
```ruby
|
102
|
+
user = User.where(...)
|
103
|
+
user.update_attributes name: 'raju', email: 'hola@hola.com'
|
104
|
+
```
|
105
|
+
|
106
|
+
Destroy record
|
107
|
+
-------
|
108
|
+
```ruby
|
109
|
+
user.destroy
|
110
|
+
User.where(...conditions...).destroy_all
|
111
|
+
```
|
112
|
+
|
113
|
+
Observers
|
114
|
+
--------
|
115
|
+
* Before, After and Around Create
|
116
|
+
* Before, After and Around Update
|
117
|
+
* Before, After and Around Destroy
|
118
|
+
|
119
|
+
TODOS
|
120
|
+
=====
|
121
|
+
|
122
|
+
* Write documentation
|
data/lib/discover.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Include plugins
|
2
|
+
require 'autotest/fsevent'
|
3
|
+
require 'autotest/growl'
|
4
|
+
|
5
|
+
Autotest.add_discovery { "rspec2" }
|
6
|
+
|
7
|
+
# Skip some paths
|
8
|
+
Autotest.add_hook :initialize do |autotest|
|
9
|
+
%w{.idea .git .DS_Store ._* vendor}.each { |exception| autotest.add_exception(exception) }
|
10
|
+
false
|
11
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FlexiModel
|
2
|
+
module ArModels
|
3
|
+
class Collection < ActiveRecord::Base
|
4
|
+
self.table_name = 'flexi_model_collections'
|
5
|
+
|
6
|
+
validates_presence_of :name
|
7
|
+
validates_uniqueness_of :name, :scope => :partition_id, :if => :partition_id
|
8
|
+
has_and_belongs_to_many :fields, :join_table => 'flexi_model_collections_fields'
|
9
|
+
has_many :records, :dependent => :destroy
|
10
|
+
|
11
|
+
attr_accessible :namespace, :name, :partition_id,
|
12
|
+
:singular_label, :plural_label, :fields
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module FlexiModel
|
2
|
+
module ArModels
|
3
|
+
class Field < ActiveRecord::Base
|
4
|
+
self.table_name = 'flexi_model_fields'
|
5
|
+
attr_accessible :name, :singular_label,:plural_label, :namespace,
|
6
|
+
:partition_id, :field_type, :default_value
|
7
|
+
|
8
|
+
COLUMNS_MAP = {
|
9
|
+
boolean: :bool_value,
|
10
|
+
integer: :int_value,
|
11
|
+
decimal: :dec_value,
|
12
|
+
float: :dec_value,
|
13
|
+
string: :str_value,
|
14
|
+
email: :str_value,
|
15
|
+
phone: :str_value,
|
16
|
+
location: :str_value,
|
17
|
+
address: :txt_value,
|
18
|
+
text: :txt_value,
|
19
|
+
multiple: :txt_value,
|
20
|
+
datetime: :dt_value,
|
21
|
+
date: :dt_value,
|
22
|
+
time: :dt_value
|
23
|
+
}
|
24
|
+
|
25
|
+
has_and_belongs_to_many :collections, :join_table => 'flexi_model_collections_fields'
|
26
|
+
has_many :values, :dependent => :destroy
|
27
|
+
|
28
|
+
validates_presence_of :name, :field_type
|
29
|
+
validates_uniqueness_of :name, :scope => [:namespace, :partition_id, :field_type]
|
30
|
+
|
31
|
+
def value_column
|
32
|
+
FlexiModel::ArModels::Field::COLUMNS_MAP[self.field_type.to_sym]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module FlexiModel
|
2
|
+
module ArModels
|
3
|
+
class Record < ActiveRecord::Base
|
4
|
+
self.table_name = 'flexi_model_records'
|
5
|
+
|
6
|
+
attr_accessible :collection_id, :namespace, :values, :values_attributes,
|
7
|
+
:collection
|
8
|
+
|
9
|
+
belongs_to :collection
|
10
|
+
has_many :values, :dependent => :destroy
|
11
|
+
has_many :fields, :through => :values
|
12
|
+
|
13
|
+
scope :by_namespace, lambda { |n| where(namespace: n) }
|
14
|
+
scope :recent, order('created_at DESC')
|
15
|
+
|
16
|
+
accepts_nested_attributes_for :values
|
17
|
+
|
18
|
+
def value_of(field_name)
|
19
|
+
values.select{|v| v.field.present? }.
|
20
|
+
select{|v| v.field.name.downcase == field_name.to_s.downcase}.first
|
21
|
+
end
|
22
|
+
|
23
|
+
def title
|
24
|
+
_value = value_of(:name) || value_of(:title)
|
25
|
+
return _value.value if _value.present?
|
26
|
+
|
27
|
+
self.collection.singular_label
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module FlexiModel
|
2
|
+
module ArModels
|
3
|
+
class Value < ActiveRecord::Base
|
4
|
+
self.table_name = 'flexi_model_values'
|
5
|
+
|
6
|
+
attr_accessible :record_id, :field_id, :bool_value, :int_value,
|
7
|
+
:dec_value, :str_value, :txt_value, :dt_value, :field,
|
8
|
+
:value
|
9
|
+
|
10
|
+
belongs_to :record
|
11
|
+
belongs_to :field
|
12
|
+
|
13
|
+
# Set value based on field type.
|
14
|
+
# ie. if it is `string` type it will store value in str_value
|
15
|
+
#
|
16
|
+
# List of field value mappings -
|
17
|
+
# Boolean 'bool_value'
|
18
|
+
# Integer 'int_value'
|
19
|
+
# Decimal 'dec_value'
|
20
|
+
# String 'str_value'
|
21
|
+
# Text 'txt_value'
|
22
|
+
# Datetime 'dt_value'
|
23
|
+
def value=(val)
|
24
|
+
self.send :"#{_mapped_value_column}=", val
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get value from corresponding column based on field type
|
28
|
+
def value
|
29
|
+
self.send :"#{_mapped_value_column}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def column_for_attribute(name)
|
33
|
+
if :value == name.to_sym
|
34
|
+
self.class.columns_hash[self.field.value_column.to_s]
|
35
|
+
else
|
36
|
+
self.class.columns_hash[name.to_s]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def _mapped_value_column
|
42
|
+
raise 'No field is set' if field.nil?
|
43
|
+
|
44
|
+
value_col =
|
45
|
+
FlexiModel::ArModels::Field::COLUMNS_MAP[field.field_type.to_sym]
|
46
|
+
raise "Unknown field type - #{field.field_type}" if value_col.nil?
|
47
|
+
|
48
|
+
value_col
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,318 @@
|
|
1
|
+
module FlexiModel
|
2
|
+
module ArPersistence
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
RECORD = FlexiModel::ArModels::Record
|
6
|
+
COLLECTION = FlexiModel::ArModels::Collection
|
7
|
+
FIELD = FlexiModel::ArModels::Field
|
8
|
+
VALUE = FlexiModel::ArModels::Value
|
9
|
+
|
10
|
+
included do
|
11
|
+
class_eval <<-RUBY
|
12
|
+
@@_flexi_collection = nil
|
13
|
+
cattr_accessor :_flexi_collection
|
14
|
+
|
15
|
+
@@_flexi_metadata = { }
|
16
|
+
cattr_accessor :_flexi_metadata
|
17
|
+
|
18
|
+
@@_flexi_fields_map = nil
|
19
|
+
cattr_accessor :_flexi_fields_map
|
20
|
+
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
# Set collection label
|
26
|
+
#
|
27
|
+
# singular - Set singular name for the collection
|
28
|
+
# plural - Set plural name for the collection
|
29
|
+
def set_flexi_label(singular, plural)
|
30
|
+
_flexi_metadata[:label_singular] = singular
|
31
|
+
_flexi_metadata[:label_plural] = plural
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return singular and plural collection label
|
35
|
+
# If not defined it will take class name as collection name
|
36
|
+
#
|
37
|
+
# Returns array of singular and plural labels
|
38
|
+
def get_flexi_label
|
39
|
+
labels = [_flexi_metadata[:label_singular],
|
40
|
+
_flexi_metadata[:label_plural]].compact
|
41
|
+
|
42
|
+
if labels.empty?
|
43
|
+
_f_name = _friendly_name(self.name)
|
44
|
+
[_f_name.singularize, _f_name.pluralize]
|
45
|
+
else
|
46
|
+
labels
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return collection name based on parametrized class name
|
51
|
+
def flexi_collection_name
|
52
|
+
self.name.parameterize
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_flexi_namespace
|
56
|
+
self.flexi_collection_name.parameterize
|
57
|
+
end
|
58
|
+
|
59
|
+
# Initialize new instance and set data from record
|
60
|
+
def initialize_with_record(record)
|
61
|
+
inst = self.new
|
62
|
+
inst.send(:_record=, record)
|
63
|
+
inst.send(:_id=, record.id)
|
64
|
+
inst
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return by default plural label
|
68
|
+
def flexi_label(singular = false)
|
69
|
+
if singular
|
70
|
+
self._flexi_collection.singular_label
|
71
|
+
else
|
72
|
+
self._flexi_collection.plural_label
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def flexi_collection;
|
77
|
+
_flexi_collection
|
78
|
+
end
|
79
|
+
|
80
|
+
delegate :id, :to => :_flexi_collection
|
81
|
+
|
82
|
+
def destroy_all;
|
83
|
+
RECORD.by_namespace(self.get_flexi_namespace).each do |record|
|
84
|
+
inst = initialize_with_record(record)
|
85
|
+
inst.destroy
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete_all;
|
90
|
+
RECORD.by_namespace(self.get_flexi_namespace).delete_all
|
91
|
+
end
|
92
|
+
|
93
|
+
# Create does exactly as `save`, but it initiates `:create` callbacks
|
94
|
+
def create(attributes = { })
|
95
|
+
inst = self.new(attributes)
|
96
|
+
inst.save
|
97
|
+
|
98
|
+
inst
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def _friendly_name(long_name)
|
103
|
+
long_name.to_s.split("::").last
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def initialize(*)
|
108
|
+
super
|
109
|
+
_find_or_update_or_build_collection!
|
110
|
+
end
|
111
|
+
|
112
|
+
# Ensure object with same _id returns true on equality check
|
113
|
+
def ==(another_instance)
|
114
|
+
self._id && self._id == another_instance._id
|
115
|
+
end
|
116
|
+
|
117
|
+
# Return true if record is not saved
|
118
|
+
def new_record?
|
119
|
+
!_id.present?
|
120
|
+
end
|
121
|
+
|
122
|
+
# Store record in persistent storage
|
123
|
+
def save
|
124
|
+
create_or_update
|
125
|
+
_id.present?
|
126
|
+
end
|
127
|
+
|
128
|
+
# Update stored attributes by give hash
|
129
|
+
def update_attributes(_params)
|
130
|
+
assign_attributes _params
|
131
|
+
save
|
132
|
+
end
|
133
|
+
|
134
|
+
# Update single attribute by key and value
|
135
|
+
def update_attribute(key, value)
|
136
|
+
self.update_attributes(key => value)
|
137
|
+
end
|
138
|
+
|
139
|
+
def destroy
|
140
|
+
if _id.present?
|
141
|
+
RECORD.delete(self._id)
|
142
|
+
else
|
143
|
+
false
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Reload object instance
|
148
|
+
def reload
|
149
|
+
self.class.find(self._id)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Forcefully load all attributes
|
153
|
+
def load_attributes!
|
154
|
+
self.flexi_fields.map { |f| self.send(f.name.to_sym) }
|
155
|
+
end
|
156
|
+
|
157
|
+
# Return existing or create new collection set
|
158
|
+
def get_flexi_collection
|
159
|
+
_find_or_update_or_build_collection!
|
160
|
+
|
161
|
+
self._flexi_collection
|
162
|
+
end
|
163
|
+
|
164
|
+
# Return flexi fields in name and field object map
|
165
|
+
def get_flexi_fields_map
|
166
|
+
self._flexi_fields_map ||=
|
167
|
+
Hash[get_flexi_collection.fields.
|
168
|
+
map { |_field| [_field.name.to_sym, _field] }]
|
169
|
+
end
|
170
|
+
|
171
|
+
delegate :created_at, :updated_at, :to => :_get_record, :prefix => :flexi
|
172
|
+
|
173
|
+
private
|
174
|
+
def create_or_update
|
175
|
+
_id.nil? ? create : update
|
176
|
+
end
|
177
|
+
|
178
|
+
def create(*)
|
179
|
+
# Initialize AR record and store
|
180
|
+
record = _get_record
|
181
|
+
record.save
|
182
|
+
|
183
|
+
# Set Id and errors to the parent host object
|
184
|
+
self._id = record.id
|
185
|
+
@errors = record.errors
|
186
|
+
|
187
|
+
record
|
188
|
+
end
|
189
|
+
|
190
|
+
def update(*)
|
191
|
+
record = _get_record
|
192
|
+
record.values.destroy_all
|
193
|
+
record.update_attributes(values: _get_values)
|
194
|
+
record
|
195
|
+
end
|
196
|
+
|
197
|
+
def _get_record
|
198
|
+
_load_record_instance!
|
199
|
+
self._record
|
200
|
+
end
|
201
|
+
|
202
|
+
def _load_record_instance!
|
203
|
+
self._record ||= _record_load_or_initialize
|
204
|
+
end
|
205
|
+
|
206
|
+
def _record_load_or_initialize
|
207
|
+
collection = _find_or_update_or_build_collection!
|
208
|
+
|
209
|
+
if self._id.nil?
|
210
|
+
RECORD.new(
|
211
|
+
namespace: self.class.get_flexi_namespace,
|
212
|
+
collection: collection,
|
213
|
+
values: self.send(:_get_values)
|
214
|
+
)
|
215
|
+
else
|
216
|
+
RECORD.find(self._id)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Return `Value` object based on flexi attributes
|
221
|
+
def _get_values
|
222
|
+
_fields_map = get_flexi_fields_map
|
223
|
+
|
224
|
+
@attributes.map do |k, v|
|
225
|
+
field = _fields_map[k]
|
226
|
+
raise "Field - #{k} not defined" if field.nil?
|
227
|
+
VALUE.new(:field => field, value: self.send(:"#{k}"))
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Find existing collection object
|
232
|
+
# If not found create new collection
|
233
|
+
# If found but schema is back dated
|
234
|
+
# update schema
|
235
|
+
def _find_or_update_or_build_collection!
|
236
|
+
return _flexi_collection if _flexi_collection.present?
|
237
|
+
|
238
|
+
# Find existing collection
|
239
|
+
self._flexi_collection = COLLECTION.where(
|
240
|
+
namespace: self.class.get_flexi_namespace,
|
241
|
+
name: self.class.flexi_collection_name,
|
242
|
+
partition_id: self.class.flexi_partition_id
|
243
|
+
).first
|
244
|
+
|
245
|
+
# Update if schema changed
|
246
|
+
if self._flexi_collection
|
247
|
+
_update_schema
|
248
|
+
else
|
249
|
+
_build_collection
|
250
|
+
end
|
251
|
+
|
252
|
+
self._flexi_collection
|
253
|
+
end
|
254
|
+
|
255
|
+
# Check whether update is back dated
|
256
|
+
# This update is verified through comparing stored collection
|
257
|
+
# and new definition
|
258
|
+
def _update_schema
|
259
|
+
singular_label, plural_label = self.class.get_flexi_label
|
260
|
+
existing = self._flexi_collection
|
261
|
+
|
262
|
+
# Check labels
|
263
|
+
if existing.singular_label != singular_label
|
264
|
+
existing.update_attribute :singular_label, singular_label
|
265
|
+
end
|
266
|
+
|
267
|
+
if existing.plural_label != plural_label
|
268
|
+
existing.update_attribute :plural_label, plural_label
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
# Check fields
|
273
|
+
fields = _build_fields
|
274
|
+
if _fields_changed? fields, existing
|
275
|
+
# TODO: Dangerous need to fix it up
|
276
|
+
existing.fields.destroy_all
|
277
|
+
existing.update_attribute :fields, fields
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def _fields_changed?(fields, existing)
|
282
|
+
added_or_removed = existing.fields.length != fields.length
|
283
|
+
name_changed = existing.fields.map(&:name).sort != fields.map(&:name).sort
|
284
|
+
type_changed = existing.fields.map(&:field_type).sort != fields.map(&:field_type).sort
|
285
|
+
|
286
|
+
added_or_removed || name_changed || type_changed
|
287
|
+
end
|
288
|
+
|
289
|
+
def _build_collection
|
290
|
+
singular_label, plural_label = self.class.get_flexi_label
|
291
|
+
|
292
|
+
self._flexi_collection = COLLECTION.create(
|
293
|
+
namespace: self.class.get_flexi_namespace,
|
294
|
+
name: self.class.flexi_collection_name,
|
295
|
+
partition_id: self.class.flexi_partition_id,
|
296
|
+
singular_label: singular_label,
|
297
|
+
plural_label: plural_label,
|
298
|
+
|
299
|
+
fields: _build_fields
|
300
|
+
)
|
301
|
+
end
|
302
|
+
|
303
|
+
def _build_fields
|
304
|
+
self.flexi_fields.map do |field|
|
305
|
+
params = {
|
306
|
+
namespace: self.class.get_flexi_namespace,
|
307
|
+
name: field.name.to_s,
|
308
|
+
partition_id: self.class.flexi_partition_id,
|
309
|
+
field_type: field.type,
|
310
|
+
singular_label: field.singular,
|
311
|
+
plural_label: field.plural
|
312
|
+
}
|
313
|
+
|
314
|
+
FIELD.send(:"find_or_create_by_#{params.keys.map(&:to_s).join('_and_')}", params)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|