Class: Serial
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Serial
- Includes:
- Housekeeping::Timestamps, Housekeeping::Users, Shared::AlternateValues, Shared::DataAttributes, Shared::HasPapertrail, Shared::Identifiers, Shared::IsData, Shared::Notes, Shared::SharedAcrossProjects, Shared::Tags, SoftValidation
- Defined in:
- app/models/serial.rb
Overview
Serial - represents a journal or other serial (repeated) publication. It follows the ISSN model for serials.
TODO handle translations (which are simultaneous)
Constant Summary collapse
- ALTERNATE_VALUES_FOR =
[:name, :publisher, :place_published].freeze
Constants included from SoftValidation
SoftValidation::ANCESTORS_WITH_SOFT_VALIDATIONS
Instance Attribute Summary collapse
-
#first_year_of_issue ⇒ Integer
The first year this serial was published.
-
#last_year_of_issue ⇒ Integer
The last year this serial was published.
-
#name ⇒ String
The name of the serial.
-
#place_published ⇒ String
The name of the place(s) where the serial is published.
-
#primary_language_id ⇒ Integer
The id of the Language - language of this serial.
-
#publisher ⇒ String
The serial publisher.
-
#translated_from_serial_id ⇒ Integer
The id of the serial that this serial is a direct translation of.
Attributes included from Housekeeping::Users
Class Method Summary collapse
Instance Method Summary collapse
- #all_previous(start_serial = self) ⇒ Array
- #all_succeeding(start_serial = self) ⇒ Array
-
#duplicate? ⇒ Boolean
Is there another serial with the same name? Also checkes alternate values.
-
#nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) ⇒ Scope
Levenshtein calculated related records per supplied column.
- #sv_duplicate? ⇒ Boolean protected
-
#unify_relations ⇒ Object
Force self-referential relations to be included in unify(), These would otherwise all be excluded because they reference ‘class_name’, which triggers their elimination in the unify code base.
Methods included from Shared::HasPapertrail
#attribute_updated, #attribute_updater
Methods included from SoftValidation
#clear_soft_validations, #fix_for, #fix_soft_validations, #soft_fixed?, #soft_valid?, #soft_validate, #soft_validated?, #soft_validations, #soft_validators
Methods included from Shared::IsData
#errors_excepting, #full_error_messages_excepting, #identical, #is_community?, #is_destroyable?, #is_editable?, #is_in_use?, #is_in_users_projects?, #metamorphosize, #similar
Methods included from Shared::Tags
#reject_tags, #tag_with, #tagged?, #tagged_with?
Methods included from Shared::Identifiers
#dwc_occurrence_id, #identified?, #next_by_identifier, #previous_by_identifier, #reject_identifiers, #uri, #uuid
Methods included from Shared::Notes
#concatenated_notes_string, #reject_notes
Methods included from Shared::DataAttributes
#import_attributes, #internal_attributes, #keyword_value_hash, #reject_data_attributes
Methods included from Shared::AlternateValues
#all_values_for, #alternate_valued?
Methods included from Housekeeping::Users
#set_created_by_id, #set_updated_by_id
Methods inherited from ApplicationRecord
Instance Attribute Details
#first_year_of_issue ⇒ Integer
Returns the first year this serial was published.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/serial.rb', line 33 class Serial < ApplicationRecord include Housekeeping::Users include Housekeeping::Timestamps include Shared::AlternateValues include Shared::DataAttributes include Shared::Notes include Shared::Identifiers include Shared::Tags include Shared::IsData include SoftValidation include Shared::SharedAcrossProjects include Shared::HasPapertrail ALTERNATE_VALUES_FOR = [:name, :publisher, :place_published].freeze belongs_to :translated_from_serial, foreign_key: :translated_from_serial_id, class_name: 'Serial' belongs_to :language, foreign_key: :primary_language_id, inverse_of: :serials has_many :sources, class_name: 'Source::Bibtex', inverse_of: :serial, dependent: :restrict_with_error has_many :translations, foreign_key: :translated_from_serial_id, class_name: 'Serial', dependent: :destroy has_many :succeeding_serial_chronologies, foreign_key: :succeeding_serial_id, inverse_of: :succeeding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error has_many :preceding_serial_chronologies, foreign_key: :preceding_serial_id, inverse_of: :preceding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error # Single preceding chronology will be multiple serials if there is a merge has_many :immediately_preceding_serials, through: :succeeding_serial_chronologies, source: :preceding_serial # Single succeeding chronology will be multiple serials if there is a split has_many :immediately_succeeding_serials, through: :preceding_serial_chronologies, source: :succeeding_serial accepts_nested_attributes_for :alternate_values, reject_if: lambda { |av| av[:value].blank? }, allow_destroy: true validates_presence_of :name soft_validate(:sv_duplicate?) # Force self-referential relations to be included in unify(), # These would otherwise all be excluded because they reference 'class_name', # which triggers their elimination in the unify code base def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end # @param [String] compared_string # @param [String] column # @param [Integer] limit # @return [Scope] # Levenshtein calculated related records per supplied column def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end # @return [Boolean] # is there another serial with the same name? Also checkes alternate values. def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end # @param [Serial] start_serial # @return [Array] def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end # @param [Serial] start_serial # @return [Array] def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end protected # @return [Boolean] def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end end |
#last_year_of_issue ⇒ Integer
Returns the last year this serial was published.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/serial.rb', line 33 class Serial < ApplicationRecord include Housekeeping::Users include Housekeeping::Timestamps include Shared::AlternateValues include Shared::DataAttributes include Shared::Notes include Shared::Identifiers include Shared::Tags include Shared::IsData include SoftValidation include Shared::SharedAcrossProjects include Shared::HasPapertrail ALTERNATE_VALUES_FOR = [:name, :publisher, :place_published].freeze belongs_to :translated_from_serial, foreign_key: :translated_from_serial_id, class_name: 'Serial' belongs_to :language, foreign_key: :primary_language_id, inverse_of: :serials has_many :sources, class_name: 'Source::Bibtex', inverse_of: :serial, dependent: :restrict_with_error has_many :translations, foreign_key: :translated_from_serial_id, class_name: 'Serial', dependent: :destroy has_many :succeeding_serial_chronologies, foreign_key: :succeeding_serial_id, inverse_of: :succeeding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error has_many :preceding_serial_chronologies, foreign_key: :preceding_serial_id, inverse_of: :preceding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error # Single preceding chronology will be multiple serials if there is a merge has_many :immediately_preceding_serials, through: :succeeding_serial_chronologies, source: :preceding_serial # Single succeeding chronology will be multiple serials if there is a split has_many :immediately_succeeding_serials, through: :preceding_serial_chronologies, source: :succeeding_serial accepts_nested_attributes_for :alternate_values, reject_if: lambda { |av| av[:value].blank? }, allow_destroy: true validates_presence_of :name soft_validate(:sv_duplicate?) # Force self-referential relations to be included in unify(), # These would otherwise all be excluded because they reference 'class_name', # which triggers their elimination in the unify code base def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end # @param [String] compared_string # @param [String] column # @param [Integer] limit # @return [Scope] # Levenshtein calculated related records per supplied column def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end # @return [Boolean] # is there another serial with the same name? Also checkes alternate values. def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end # @param [Serial] start_serial # @return [Array] def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end # @param [Serial] start_serial # @return [Array] def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end protected # @return [Boolean] def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end end |
#name ⇒ String
Returns the name of the serial.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/serial.rb', line 33 class Serial < ApplicationRecord include Housekeeping::Users include Housekeeping::Timestamps include Shared::AlternateValues include Shared::DataAttributes include Shared::Notes include Shared::Identifiers include Shared::Tags include Shared::IsData include SoftValidation include Shared::SharedAcrossProjects include Shared::HasPapertrail ALTERNATE_VALUES_FOR = [:name, :publisher, :place_published].freeze belongs_to :translated_from_serial, foreign_key: :translated_from_serial_id, class_name: 'Serial' belongs_to :language, foreign_key: :primary_language_id, inverse_of: :serials has_many :sources, class_name: 'Source::Bibtex', inverse_of: :serial, dependent: :restrict_with_error has_many :translations, foreign_key: :translated_from_serial_id, class_name: 'Serial', dependent: :destroy has_many :succeeding_serial_chronologies, foreign_key: :succeeding_serial_id, inverse_of: :succeeding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error has_many :preceding_serial_chronologies, foreign_key: :preceding_serial_id, inverse_of: :preceding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error # Single preceding chronology will be multiple serials if there is a merge has_many :immediately_preceding_serials, through: :succeeding_serial_chronologies, source: :preceding_serial # Single succeeding chronology will be multiple serials if there is a split has_many :immediately_succeeding_serials, through: :preceding_serial_chronologies, source: :succeeding_serial accepts_nested_attributes_for :alternate_values, reject_if: lambda { |av| av[:value].blank? }, allow_destroy: true validates_presence_of :name soft_validate(:sv_duplicate?) # Force self-referential relations to be included in unify(), # These would otherwise all be excluded because they reference 'class_name', # which triggers their elimination in the unify code base def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end # @param [String] compared_string # @param [String] column # @param [Integer] limit # @return [Scope] # Levenshtein calculated related records per supplied column def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end # @return [Boolean] # is there another serial with the same name? Also checkes alternate values. def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end # @param [Serial] start_serial # @return [Array] def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end # @param [Serial] start_serial # @return [Array] def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end protected # @return [Boolean] def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end end |
#place_published ⇒ String
Returns The name of the place(s) where the serial is published.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/serial.rb', line 33 class Serial < ApplicationRecord include Housekeeping::Users include Housekeeping::Timestamps include Shared::AlternateValues include Shared::DataAttributes include Shared::Notes include Shared::Identifiers include Shared::Tags include Shared::IsData include SoftValidation include Shared::SharedAcrossProjects include Shared::HasPapertrail ALTERNATE_VALUES_FOR = [:name, :publisher, :place_published].freeze belongs_to :translated_from_serial, foreign_key: :translated_from_serial_id, class_name: 'Serial' belongs_to :language, foreign_key: :primary_language_id, inverse_of: :serials has_many :sources, class_name: 'Source::Bibtex', inverse_of: :serial, dependent: :restrict_with_error has_many :translations, foreign_key: :translated_from_serial_id, class_name: 'Serial', dependent: :destroy has_many :succeeding_serial_chronologies, foreign_key: :succeeding_serial_id, inverse_of: :succeeding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error has_many :preceding_serial_chronologies, foreign_key: :preceding_serial_id, inverse_of: :preceding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error # Single preceding chronology will be multiple serials if there is a merge has_many :immediately_preceding_serials, through: :succeeding_serial_chronologies, source: :preceding_serial # Single succeeding chronology will be multiple serials if there is a split has_many :immediately_succeeding_serials, through: :preceding_serial_chronologies, source: :succeeding_serial accepts_nested_attributes_for :alternate_values, reject_if: lambda { |av| av[:value].blank? }, allow_destroy: true validates_presence_of :name soft_validate(:sv_duplicate?) # Force self-referential relations to be included in unify(), # These would otherwise all be excluded because they reference 'class_name', # which triggers their elimination in the unify code base def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end # @param [String] compared_string # @param [String] column # @param [Integer] limit # @return [Scope] # Levenshtein calculated related records per supplied column def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end # @return [Boolean] # is there another serial with the same name? Also checkes alternate values. def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end # @param [Serial] start_serial # @return [Array] def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end # @param [Serial] start_serial # @return [Array] def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end protected # @return [Boolean] def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end end |
#primary_language_id ⇒ Integer
The id of the Language - language of this serial. According to the ISSN a new ISSN is minted for a journal that
changes languages.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/serial.rb', line 33 class Serial < ApplicationRecord include Housekeeping::Users include Housekeeping::Timestamps include Shared::AlternateValues include Shared::DataAttributes include Shared::Notes include Shared::Identifiers include Shared::Tags include Shared::IsData include SoftValidation include Shared::SharedAcrossProjects include Shared::HasPapertrail ALTERNATE_VALUES_FOR = [:name, :publisher, :place_published].freeze belongs_to :translated_from_serial, foreign_key: :translated_from_serial_id, class_name: 'Serial' belongs_to :language, foreign_key: :primary_language_id, inverse_of: :serials has_many :sources, class_name: 'Source::Bibtex', inverse_of: :serial, dependent: :restrict_with_error has_many :translations, foreign_key: :translated_from_serial_id, class_name: 'Serial', dependent: :destroy has_many :succeeding_serial_chronologies, foreign_key: :succeeding_serial_id, inverse_of: :succeeding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error has_many :preceding_serial_chronologies, foreign_key: :preceding_serial_id, inverse_of: :preceding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error # Single preceding chronology will be multiple serials if there is a merge has_many :immediately_preceding_serials, through: :succeeding_serial_chronologies, source: :preceding_serial # Single succeeding chronology will be multiple serials if there is a split has_many :immediately_succeeding_serials, through: :preceding_serial_chronologies, source: :succeeding_serial accepts_nested_attributes_for :alternate_values, reject_if: lambda { |av| av[:value].blank? }, allow_destroy: true validates_presence_of :name soft_validate(:sv_duplicate?) # Force self-referential relations to be included in unify(), # These would otherwise all be excluded because they reference 'class_name', # which triggers their elimination in the unify code base def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end # @param [String] compared_string # @param [String] column # @param [Integer] limit # @return [Scope] # Levenshtein calculated related records per supplied column def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end # @return [Boolean] # is there another serial with the same name? Also checkes alternate values. def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end # @param [Serial] start_serial # @return [Array] def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end # @param [Serial] start_serial # @return [Array] def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end protected # @return [Boolean] def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end end |
#publisher ⇒ String
Returns the serial publisher.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/serial.rb', line 33 class Serial < ApplicationRecord include Housekeeping::Users include Housekeeping::Timestamps include Shared::AlternateValues include Shared::DataAttributes include Shared::Notes include Shared::Identifiers include Shared::Tags include Shared::IsData include SoftValidation include Shared::SharedAcrossProjects include Shared::HasPapertrail ALTERNATE_VALUES_FOR = [:name, :publisher, :place_published].freeze belongs_to :translated_from_serial, foreign_key: :translated_from_serial_id, class_name: 'Serial' belongs_to :language, foreign_key: :primary_language_id, inverse_of: :serials has_many :sources, class_name: 'Source::Bibtex', inverse_of: :serial, dependent: :restrict_with_error has_many :translations, foreign_key: :translated_from_serial_id, class_name: 'Serial', dependent: :destroy has_many :succeeding_serial_chronologies, foreign_key: :succeeding_serial_id, inverse_of: :succeeding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error has_many :preceding_serial_chronologies, foreign_key: :preceding_serial_id, inverse_of: :preceding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error # Single preceding chronology will be multiple serials if there is a merge has_many :immediately_preceding_serials, through: :succeeding_serial_chronologies, source: :preceding_serial # Single succeeding chronology will be multiple serials if there is a split has_many :immediately_succeeding_serials, through: :preceding_serial_chronologies, source: :succeeding_serial accepts_nested_attributes_for :alternate_values, reject_if: lambda { |av| av[:value].blank? }, allow_destroy: true validates_presence_of :name soft_validate(:sv_duplicate?) # Force self-referential relations to be included in unify(), # These would otherwise all be excluded because they reference 'class_name', # which triggers their elimination in the unify code base def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end # @param [String] compared_string # @param [String] column # @param [Integer] limit # @return [Scope] # Levenshtein calculated related records per supplied column def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end # @return [Boolean] # is there another serial with the same name? Also checkes alternate values. def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end # @param [Serial] start_serial # @return [Array] def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end # @param [Serial] start_serial # @return [Array] def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end protected # @return [Boolean] def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end end |
#translated_from_serial_id ⇒ Integer
Returns the id of the serial that this serial is a direct translation of.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/models/serial.rb', line 33 class Serial < ApplicationRecord include Housekeeping::Users include Housekeeping::Timestamps include Shared::AlternateValues include Shared::DataAttributes include Shared::Notes include Shared::Identifiers include Shared::Tags include Shared::IsData include SoftValidation include Shared::SharedAcrossProjects include Shared::HasPapertrail ALTERNATE_VALUES_FOR = [:name, :publisher, :place_published].freeze belongs_to :translated_from_serial, foreign_key: :translated_from_serial_id, class_name: 'Serial' belongs_to :language, foreign_key: :primary_language_id, inverse_of: :serials has_many :sources, class_name: 'Source::Bibtex', inverse_of: :serial, dependent: :restrict_with_error has_many :translations, foreign_key: :translated_from_serial_id, class_name: 'Serial', dependent: :destroy has_many :succeeding_serial_chronologies, foreign_key: :succeeding_serial_id, inverse_of: :succeeding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error has_many :preceding_serial_chronologies, foreign_key: :preceding_serial_id, inverse_of: :preceding_serial, class_name: 'SerialChronology', dependent: :restrict_with_error # Single preceding chronology will be multiple serials if there is a merge has_many :immediately_preceding_serials, through: :succeeding_serial_chronologies, source: :preceding_serial # Single succeeding chronology will be multiple serials if there is a split has_many :immediately_succeeding_serials, through: :preceding_serial_chronologies, source: :succeeding_serial accepts_nested_attributes_for :alternate_values, reject_if: lambda { |av| av[:value].blank? }, allow_destroy: true validates_presence_of :name soft_validate(:sv_duplicate?) # Force self-referential relations to be included in unify(), # These would otherwise all be excluded because they reference 'class_name', # which triggers their elimination in the unify code base def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end # @param [String] compared_string # @param [String] column # @param [Integer] limit # @return [Scope] # Levenshtein calculated related records per supplied column def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end # @return [Boolean] # is there another serial with the same name? Also checkes alternate values. def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end # @param [Serial] start_serial # @return [Array] def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end # @param [Serial] start_serial # @return [Array] def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end protected # @return [Boolean] def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end end |
Class Method Details
.select_optimized(user_id, project_id) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'app/models/serial.rb', line 174 def self.select_optimized(user_id, project_id) r = used_recently(user_id) h = { recent: ( Serial.where('"serials"."id" IN (?)', r.first(10) ).order(:name).to_a + Serial.where(created_by_id: user_id, created_at: 3.hours.ago..Time.now).limit(5).to_a).uniq, pinboard: Serial.pinned_by(user_id).pinned_in_project(project_id).to_a } h[:quick] = (Serial.pinned_by(user_id).pinboard_inserted.pinned_in_project(project_id).to_a + Serial.where('"serials"."id" IN (?)', r.first(4) ).order(:name).to_a).uniq h end |
.used_recently(user_id) ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'app/models/serial.rb', line 156 def self.used_recently(user_id) t = Source.arel_table p = Serial.arel_table # i is a select manager i = t.project(t['serial_id'], t['updated_at']).from(t) .where(t['updated_at'].gt(1.months.ago)) .where(t['updated_by_id'].eq(user_id)) .order(t['updated_at'].desc) # z is a table alias z = i.as('recent_t') Serial.joins( Arel::Nodes::InnerJoin.new(z, Arel::Nodes::On.new(z['serial_id'].eq(p['id']))) ).pluck(:serial_id).uniq end |
Instance Method Details
#all_previous(start_serial = self) ⇒ Array
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'app/models/serial.rb', line 129 def all_previous(start_serial = self) # provides an array of all previous incarnations of me out_array = [] start_serial.immediately_preceding_serials.order(:name).each do |serial| out_array.push(serial) prev = all_previous(serial) out_array.push(prev) unless prev.empty? end return out_array end |
#all_succeeding(start_serial = self) ⇒ Array
144 145 146 147 148 149 150 151 152 153 154 |
# File 'app/models/serial.rb', line 144 def all_succeeding(start_serial = self) # provides an array of all succeeding incarnations of me out_array = [] start_serial.immediately_succeeding_serials.order(:name).each do |serial| out_array.push(serial) succeeding = all_succeeding(serial) out_array.push(succeeding) unless succeeding.empty? end out_array end |
#duplicate? ⇒ Boolean
Returns is there another serial with the same name? Also checkes alternate values.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'app/models/serial.rb', line 103 def duplicate? # ret_val = false if self.new_record? ret_val = Serial.exists?(name: self.name) else name_str = ActiveRecord::Base.send( :sanitize_sql_array, ['name = ? AND NOT (id = ?)', Utilities::Strings.escape_single_quote(self.name), self.id]) ret_val = Serial.where(name_str).to_a.size > 0 end if ret_val == false # check if there is another alternate value with the same name a = Serial.with_alternate_value_on(:name, self.name) # select alternate value based on alternate_value_object class, alternate_value_object_attribute(column) & value if a.count > 0 ret_val = true end end ret_val end |
#nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) ⇒ Scope
Returns Levenshtein calculated related records per supplied column.
87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'app/models/serial.rb', line 87 def nearest_by_levenshtein(compared_string = nil, column = 'name', limit = 10) return Serial.none if compared_string.blank? # Levenshtein in postgres requires all strings be 255 or fewer order_str = Serial.send( :sanitize_sql_for_conditions, ["levenshtein(Substring(serials.#{column} from 0 for 250), ?)", compared_string[0..250]]) Serial.where('id <> ?', self.to_param) .order(Arel.sql(order_str)) .limit(limit) end |
#sv_duplicate? ⇒ Boolean (protected)
191 192 193 194 195 196 |
# File 'app/models/serial.rb', line 191 def sv_duplicate? if self.duplicate? soft_validations.add(:name, 'There is another serial with this name in the database.') end # TODO soft validation of name matching an alternate value for name of a different serial end |
#unify_relations ⇒ Object
Force self-referential relations to be included in unify(), These would otherwise all be excluded because they reference ‘class_name’, which triggers their elimination in the unify code base
72 73 74 75 76 77 78 79 80 |
# File 'app/models/serial.rb', line 72 def unify_relations ApplicationEnumeration.klass_reflections(self.class).select{|a| [ :translations, :sources, :succeeding_serial_chronologies, :preceding_serial_chronologies ].include?(a.name) } end |