diff --git a/app/models/custom_attributes/custom_attribute_definition.rb b/app/models/custom_attributes/custom_attribute_definition.rb index 324ae3a..b5de77d 100644 --- a/app/models/custom_attributes/custom_attribute_definition.rb +++ b/app/models/custom_attributes/custom_attribute_definition.rb @@ -5,11 +5,16 @@ module CustomAttributeDefinition scope :by_sort_order, -> { order('sort_order ASC') } validates :attr_name, presence: true, format: { with: /^[a-zA-Z\_\s]+$/, multiline: true, message: 'cannot contain special characters.' } validates :default_value, format: { with: /^[\+\-]?\d*\.?\d*$/, multiline: true, message: 'should be a number.' }, if: :number_type? + validate :can_be_marked_as_unique def number_type? [CustomAttributes::CustomAttribute::TYPE_NUMBER, CustomAttributes::CustomAttribute::TYPE_DECIMAL].include?(attr_type) end + def text_type? + attr_type == CustomAttributes::CustomAttribute::TYPE_TEXT + end + def boolean_type? attr_type == CustomAttributes::CustomAttribute::TYPE_BOOLEAN end @@ -30,6 +35,7 @@ def save_custom_attribute(selected_option_label) begin transaction do self.custom_attribute_options = [] unless has_options? + default_value = "" if unique? save! if has_options? update! default_value: custom_attribute_options.find_by(label: selected_option_label).try(:id) @@ -44,6 +50,7 @@ def save_custom_attribute(selected_option_label) def update_custom_attribute(custom_attribute_params, selected_option_label) begin transaction do + custom_attribute_params[:default_value] = "" if unique? update!(custom_attribute_params) if has_options? update! default_value: custom_attribute_options.find_by(label: selected_option_label).try(:id) @@ -58,6 +65,32 @@ def update_custom_attribute(custom_attribute_params, selected_option_label) def default_option custom_attribute_options.find_by(id: default_value) end + + def can_be_marked_as_unique + if unique? + if !can_be_unique? + errors.add :base, 'Can not be made as unique!' + elsif has_duplicate_values? + errors.add :base, 'Remove duplicate values first to make is unique.' + end + end + errors.blank? + end + + def can_be_unique? + text_type? || number_type? + end + + def has_duplicate_values? + column = { + CustomAttributes::CustomAttribute::TYPE_TEXT => 'string_value', + CustomAttributes::CustomAttribute::TYPE_NUMBER => 'integer_value', + CustomAttributes::CustomAttribute::TYPE_DECIMAL => 'double_value', + }[attr_type] + return false if column.blank? + duplicate_cavs = custom_attribute_values.where("#{column} IS NOT NULL").select("#{column}, count(*) as values_count").group(column).having("count(*) > 1") + duplicate_cavs.present? + end end end end \ No newline at end of file diff --git a/app/models/custom_attributes/custom_attributes_utilities.rb b/app/models/custom_attributes/custom_attributes_utilities.rb new file mode 100644 index 0000000..7f7d19c --- /dev/null +++ b/app/models/custom_attributes/custom_attributes_utilities.rb @@ -0,0 +1,24 @@ +module CustomAttributes + module CustomAttributesUtilities + extend ActiveSupport::Concern + + included do + after_save :check_duplicate_custom_attributes + end + + def check_duplicate_custom_attributes + return unless self.custom_attribute_defn.unique? + column_maping = { + "#{self.owner.class.name}CustomAttributeStringValue" => 'string_value', + "#{self.owner.class.name}CustomAttributeIntegerValue" => 'integer_value', + "#{self.owner.class.name}CustomAttributeDoubleValue" => 'double_value', + } + + return if column_maping[self.class.name].blank? + if self.value.present? + duplicate_count = self.class.where("#{column_maping[self.class.name]} = ?", self.value).count + raise StandardError.new("Duplicate value for '#{self.custom_attribute_defn.attr_name}'") if duplicate_count > 1 + end + end + end +end \ No newline at end of file diff --git a/app/views/custom_attributes/custom_attribute_definitions/_form_fields_only.html.erb b/app/views/custom_attributes/custom_attribute_definitions/_form_fields_only.html.erb index f6462e6..05f38b0 100644 --- a/app/views/custom_attributes/custom_attribute_definitions/_form_fields_only.html.erb +++ b/app/views/custom_attributes/custom_attribute_definitions/_form_fields_only.html.erb @@ -57,4 +57,17 @@ <% if new_record %> <%= f.hidden_field :sort_order %> -<% end %> \ No newline at end of file +<% end %> + +
+

Preferences

+
+ +
+ <%= f.check_box :required, class: "ca_required ca_required_field", disabled: f.object.try(:boolean_type?) %> Make this mandatory
+
+ +
+ <% unique_restricted = !f.object.try(:can_be_unique?) || f.object.try(:has_duplicate_values?) %> + <%= f.check_box :unique, class: "ca_unique ca_unique_field", id: 'make_unique_checkbox', disabled: unique_restricted %> Make this unique
+
diff --git a/lib/custom_attributes/version.rb b/lib/custom_attributes/version.rb index 5d205c0..c25737b 100644 --- a/lib/custom_attributes/version.rb +++ b/lib/custom_attributes/version.rb @@ -1,3 +1,3 @@ module CustomAttributes - VERSION = "0.1.18" + VERSION = "0.1.19" end \ No newline at end of file diff --git a/lib/generators/custom_attributes/templates/custom_attribute_definition_model.rb b/lib/generators/custom_attributes/templates/custom_attribute_definition_model.rb index b003314..5b612eb 100644 --- a/lib/generators/custom_attributes/templates/custom_attribute_definition_model.rb +++ b/lib/generators/custom_attributes/templates/custom_attribute_definition_model.rb @@ -1,5 +1,6 @@ class <%= name %>CustomAttributeDefinition < ActiveRecord::Base include CustomAttributes::CustomAttributeDefinition + has_many :custom_attribute_values, dependent: :destroy, class_name: "<%= name %>CustomAttributeValue", foreign_key: "<%= singular_name %>_custom_attribute_definition_id" has_many :custom_attribute_options, dependent: :destroy, class_name: "<%= name %>CustomAttributeOption", foreign_key: "<%= singular_name %>_custom_attribute_definition_id" <% if options.tenant %> validates :attr_name, uniqueness: { scope: :<%= options.tenant %>_id, message: " has already been taken." } diff --git a/lib/generators/custom_attributes/templates/custom_attribute_definitions_controller.rb b/lib/generators/custom_attributes/templates/custom_attribute_definitions_controller.rb index 94e97c9..f530f3d 100644 --- a/lib/generators/custom_attributes/templates/custom_attribute_definitions_controller.rb +++ b/lib/generators/custom_attributes/templates/custom_attribute_definitions_controller.rb @@ -34,6 +34,8 @@ def custom_attribute_params :attr_name, :attr_type, :sort_order, + :required, + :unique, custom_attribute_options_attributes: [ :id, :label, diff --git a/lib/generators/custom_attributes/templates/custom_attribute_value_model.rb b/lib/generators/custom_attributes/templates/custom_attribute_value_model.rb index e3ac1bc..5c5b7ef 100644 --- a/lib/generators/custom_attributes/templates/custom_attribute_value_model.rb +++ b/lib/generators/custom_attributes/templates/custom_attribute_value_model.rb @@ -1,5 +1,5 @@ class <%= name %>CustomAttributeValue < ActiveRecord::Base - include CustomAttributes::CustomAttributeValue + include CustomAttributes::CustomAttributeValue, CustomAttributes::CustomAttributesUtilities belongs_to :custom_attribute_defn, class_name: "<%= name %>CustomAttributeDefinition", foreign_key: "<%= singular_name %>_custom_attribute_definition_id" belongs_to :owner, class_name: "<%= name %>", foreign_key: "<%= singular_name %>_id" has_many :custom_attribute_options, through: :custom_attribute_defn diff --git a/lib/generators/custom_attributes/templates/migration.rb b/lib/generators/custom_attributes/templates/migration.rb index 5b34e96..13b7e8c 100644 --- a/lib/generators/custom_attributes/templates/migration.rb +++ b/lib/generators/custom_attributes/templates/migration.rb @@ -8,6 +8,7 @@ def change t.string :placeholder t.integer :sort_order t.boolean :required, default: false + t.boolean :unique, default: false end <% if options.tenant %> t.integer :<%= options.tenant.underscore %>_id, foreign_key: true