needle_in_a_haystack 1.0.4 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af267c9afbbd079edbdcb7ac293721697491a7e47dac4d19963ad9af83fbd60d
4
- data.tar.gz: e100eff5dfe19e038ffb8c6e8086b96eb1a034f87d3de1b66861ac91a05493b6
3
+ metadata.gz: b329760e8ef018728c47465a1a0aacf1b83a3e89562f4a0e1ecfe703c01fc3e5
4
+ data.tar.gz: 2e6d30cdc898b73a9e05f7210b3dc3e5294bdb6bd844dbb7bbfeb5e02e0b4afc
5
5
  SHA512:
6
- metadata.gz: d2870fbe87246fe0e39b6818fcd2ebffb5767af2a39a1d0b3636c2f93b8fc069ebdda4a4b0c7f15ae4af878fa5507571db6d29f367213510857a8f64d0d5f214
7
- data.tar.gz: 6e49496b73f7d4bee5ee41e1bcc34e8e322eae66ac5af71419516c8532e7b79a2066827679dcce59680d3627cd9af4c2c968501cd9c14d07a299adb628fe72fa
6
+ metadata.gz: 429d11b80631e4b7a9cac61ad46f2c6655f74e599240d52f970cf83ac92269918756417bd58f2e2bb30cb0bc88eecf667395a82826599478b977b6765c6db034
7
+ data.tar.gz: ea62403765551a28022f267fc3d829fe86d0a28cc2afd5f9b43e4c049f1bcd8d497e41cc67b382c860dded4723c87786d3a94d5b2ce5208815dbee8e85ae0a0d
@@ -0,0 +1,255 @@
1
+ site:
2
+ description: Een geografische locatie in de gebouwde omgeving
3
+ children:
4
+ building:
5
+ description: Een structuur op een site
6
+ children:
7
+ floor:
8
+ description: Een verdieping in een gebouw
9
+ children:
10
+ area:
11
+ description: Een driedimensionale ruimte in de gebouwde omgeving
12
+ children:
13
+ room:
14
+ description: Een afgesloten ruimte binnen een gebouw
15
+ bathRoom:
16
+ description: Een ruimte met sanitaire voorzieningen
17
+ kitchen:
18
+ description: Een ruimte voor het bereiden van voedsel
19
+ bedRoom:
20
+ description: Een slaapkamer
21
+ openSpace:
22
+ description: Een open ruimte binnen een gebouw
23
+ corridor:
24
+ description: Een gang die verschillende ruimtes verbindt
25
+ lobby:
26
+ description: Een ontvangstruimte of hal in een gebouw
27
+ office:
28
+ description: Een werkruimte binnen een gebouw
29
+ conferenceRoom:
30
+ description: Een vergaderruimte binnen een gebouw
31
+ storage:
32
+ description: Een opslagruimte binnen een gebouw
33
+ mechanicalRoom:
34
+ description: Een ruimte voor mechanische apparatuur en installaties
35
+ electricalRoom:
36
+ description: Een ruimte voor elektrische apparatuur en installaties
37
+
38
+ equip:
39
+ description: Apparatuur asset
40
+ children:
41
+ meter:
42
+ description: Meetapparaat voor verbruik
43
+ children:
44
+ elecMeter:
45
+ description: Elektriciteitsmeter
46
+ children:
47
+ smartMeter:
48
+ description: Slimme meter voor elektriciteit
49
+ intervalMeter:
50
+ description: Intervalmeter voor elektriciteit
51
+ meterbeheer:
52
+ description: Meterbeheer elektriciteitsmeter
53
+ fudura:
54
+ description: Fudura elektriciteitsmeter
55
+ gasMeter:
56
+ description: Gasmeter
57
+ children:
58
+ smartMeter:
59
+ description: Slimme meter voor gas
60
+ intervalMeter:
61
+ description: Intervalmeter voor gas
62
+ meterbeheer:
63
+ description: Meterbeheer gasmeter
64
+ fudura:
65
+ description: Fudura gasmeter
66
+ waterMeter:
67
+ description: Watermeter
68
+ climateMeter:
69
+ description: Klimaatmeter
70
+ children:
71
+ tempMeter:
72
+ description: Temperatuurmeter
73
+ co2Meter:
74
+ description: CO2-meter
75
+ humidityMeter:
76
+ description: Luchtvochtigheidsmeter
77
+ loraMeter:
78
+ description: LoRa klimaatmeter voor temperatuur, luchtvochtigheid en CO2
79
+
80
+ weatherStation:
81
+ description: Weerstation voor meteorologische gegevens
82
+ children:
83
+ onlineWeather:
84
+ description: Online weerstation via api of website
85
+ hvac:
86
+ description: Verwarming, ventilatie en airconditioning
87
+ children:
88
+ ahu:
89
+ description: Luchtbehandelingskast
90
+ vav:
91
+ description: Variable Air Volume box
92
+ fcu:
93
+ description: Fan Coil Unit
94
+ chiller:
95
+ description: Koelmachine
96
+ boiler:
97
+ description: Verwarmingsketel
98
+ heatPump:
99
+ description: Warmtepomp
100
+ lighting:
101
+ description: Verlichtingssystemen
102
+ children:
103
+ luminaire:
104
+ description: Armatuur
105
+ lightSensor:
106
+ description: Lichtsensor
107
+ occupancySensor:
108
+ description: Aanwezigheidssensor
109
+ security:
110
+ description: Beveiligingssystemen
111
+ children:
112
+ accessControl:
113
+ description: Toegangscontrolesysteem
114
+ cctv:
115
+ description: Camerabewakingssysteem
116
+
117
+ # Datapunten
118
+ point:
119
+ description: Datapunt zoals een sensor of actuator
120
+ children:
121
+ sensor:
122
+ description: Meetpunt
123
+ children:
124
+ temp:
125
+ description: Temperatuursensor
126
+ children:
127
+ tempIndoor:
128
+ description: Binnentemperatuursensor
129
+ tempOutdoor:
130
+ description: Buitentemperatuursensor
131
+ co2:
132
+ description: CO2-sensor
133
+ humidity:
134
+ description: Luchtvochtigheidssensor
135
+ pressure:
136
+ description: Druksensor
137
+ flow:
138
+ description: Stromingssensor
139
+ power:
140
+ description: Vermogenssensor
141
+ energy:
142
+ description: Energiesensor
143
+ occupancy:
144
+ description: Bezettingssensor
145
+ cmd:
146
+ description: Commandopunt
147
+ children:
148
+ onOff:
149
+ description: Aan/uit commando
150
+ setpoint:
151
+ description: Instelpunt
152
+ sp:
153
+ description: Setpoint
154
+ children:
155
+ tempSp:
156
+ description: Temperatuur setpoint
157
+ humiditySp:
158
+ description: Luchtvochtigheid setpoint
159
+ pressureSp:
160
+ description: Druk setpoint
161
+ status:
162
+ description: Statuspunt
163
+ children:
164
+ alarm:
165
+ description: Alarmpunt
166
+ fault:
167
+ description: Foutpunt
168
+
169
+ # Energiebronnen
170
+ substance:
171
+ description: Energiebron of medium
172
+ children:
173
+ elec:
174
+ description: Elektriciteit
175
+ gas:
176
+ description: Gas
177
+ water:
178
+ description: Water
179
+ steam:
180
+ description: Stoom
181
+ oil:
182
+ description: Olie
183
+
184
+ # Metingen en eenheden
185
+ measurement:
186
+ description: Meetbare eigenschappen
187
+ children:
188
+ temp:
189
+ description: Temperatuur
190
+ humidity:
191
+ description: Luchtvochtigheid
192
+ co2:
193
+ description: Koolstofdioxide concentratie
194
+ pressure:
195
+ description: Druk
196
+ flow:
197
+ description: Stroming
198
+ power:
199
+ description: Vermogen
200
+ energy:
201
+ description: Energie
202
+ voltage:
203
+ description: Spanning
204
+ current:
205
+ description: Stroom
206
+ frequency:
207
+ description: Frequentie
208
+ luminosity:
209
+ description: Lichtsterkte
210
+
211
+ # Tijdgerelateerde tags
212
+ occupied:
213
+ description: Bezettingsstatus
214
+ schedule:
215
+ description: Tijdschema
216
+ timezone:
217
+ description: Tijdzone
218
+
219
+ # Netwerkgerelateerde tags
220
+ network:
221
+ description: Netwerkgerelateerde informatie
222
+ children:
223
+ protocol:
224
+ description: Communicatieprotocol
225
+ children:
226
+ bacnet:
227
+ description: BACnet protocol
228
+ modbus:
229
+ description: Modbus protocol
230
+ knx:
231
+ description: KNX protocol
232
+ lonworks:
233
+ description: LonWorks protocol
234
+ ipAddr:
235
+ description: IP-adres
236
+ mac:
237
+ description: MAC-adres
238
+
239
+ # Metadata tags
240
+ id:
241
+ description: Unieke identifier
242
+ dis:
243
+ description: Weergavenaam
244
+ area:
245
+ description: Oppervlakte
246
+ vol:
247
+ description: Volume
248
+ manufacturer:
249
+ description: Fabrikant
250
+ model:
251
+ description: Model
252
+ serialNum:
253
+ description: Serienummer
254
+ installationDate:
255
+ description: Installatiedatum
@@ -1,9 +1,6 @@
1
- module Taggable
2
- extend ActiveSupport::Concern
3
-
4
- included do
5
- serialize :tags, JSON
6
- end
1
+ class Taggable < ApplicationRecord
2
+ has_many :haystack_taggings, as: :taggable, dependent: :destroy
3
+ has_many :haystack_tags, through: :haystack_taggings
7
4
 
8
5
  def add_haystack_marker(marker)
9
6
  self.tags ||= {}
@@ -0,0 +1,39 @@
1
+ class HaystackFactory < BaseFactory
2
+ attr_accessor :tag_strategy
3
+
4
+ def initialize(tag_strategy = DefaultTagStrategy.new)
5
+ super()
6
+ @tag_strategy = tag_strategy
7
+ end
8
+
9
+ def create_tag(name, description)
10
+ @tag_strategy.create_tag(name, description)
11
+ end
12
+
13
+ def create_tagging(tag, taggable)
14
+ HaystackTagging.create(haystack_tag: tag, taggable: taggable)
15
+ end
16
+
17
+ def find_or_create_tag(name, attributes = {})
18
+ tag = HaystackTag.find_or_create_by(name: name)
19
+ if tag.persisted?
20
+ @tag_strategy.update_tag(tag, attributes)
21
+ else
22
+ tag.update(attributes)
23
+ end
24
+ tag
25
+ end
26
+
27
+ def create_tags(tag_hash, parent_tag = nil)
28
+ tag_hash.each do |name, data|
29
+ next if %w[description children].include?(name)
30
+
31
+ tag = find_or_create_tag(name, description: data["description"], haystack_marker: data["marker"])
32
+ tag.update(parent_tag_id: parent_tag&.id)
33
+
34
+ Rails.logger.info("Created tag: #{tag.name}, Parent: #{parent_tag&.name}, Parent ID: #{parent_tag&.id}")
35
+
36
+ create_tags(data["children"], tag) if data["children"]
37
+ end
38
+ end
39
+ end
@@ -38,27 +38,12 @@ class HaystackOntology < ApplicationRecord
38
38
  end
39
39
 
40
40
  def self.create_tags
41
- create_tag_hierarchy(tags)
42
- end
43
-
44
- def self.create_tag_hierarchy(tag_hash, parent_tag = nil)
45
- tag_hash.each do |name, data|
46
- next if %w[description children].include?(name)
47
-
48
- tag = HaystackTag.find_or_create_by(name: name.to_s)
49
- tag.update(description: data["description"], parent_tag_id: parent_tag&.id, haystack_marker: data["marker"])
50
-
51
- Rails.logger.info("Created tag: #{tag.name}, Parent: #{parent_tag&.name}, Parent ID: #{parent_tag&.id}")
52
-
53
- if data["children"]
54
- Rails.logger.info("Processing children for tag: #{tag.name}")
55
- create_tag_hierarchy(data["children"], tag)
56
- end
57
- end
41
+ factory = HaystackFactory.new(OntologyTagStrategy.new)
42
+ factory.create_tags(tags)
58
43
  end
59
44
 
60
45
  def self.find_or_create_tag(name)
61
- factory = HaystackFactory.new
46
+ factory = HaystackFactory.new(OntologyTagStrategy.new)
62
47
  tag_data = find_tag(name)
63
48
  return nil if tag_data.nil?
64
49
 
@@ -1,17 +1,24 @@
1
+ require "yaml"
2
+
1
3
  class HaystackTag < BaseTag
2
4
  belongs_to :parent_tag, class_name: "HaystackTag", optional: true
3
5
  has_many :children, class_name: "HaystackTag", foreign_key: "parent_tag_id", dependent: :destroy, inverse_of: :parent_tag
4
6
  has_many :haystack_taggings, dependent: :destroy
5
- has_many :taggables, through: :haystack_taggings
7
+ has_many :taggables, through: :haystack_taggings, source: :taggable, source_type: "Taggable"
6
8
 
7
- validates :name, presence: true, uniqueness: true
9
+ validates :name, presence: true, uniqueness: { scope: :parent_tag_id, message: "Moet uniek zijn binnen dezelfde categorie" }
8
10
  validates :description, presence: true
9
11
  validate :prevent_circular_reference
12
+ validate :ensure_identity
13
+
14
+ CATEGORIES = YAML.load_file("lib/haystack_ontology.yml")
10
15
 
11
16
  def ancestors
12
17
  ancestors = []
13
18
  current = self
14
19
  while current.parent_tag
20
+ break if ancestors.include?(current.parent_tag) # Voorkom oneindige lus
21
+
15
22
  ancestors << current.parent_tag
16
23
  current = current.parent_tag
17
24
  end
@@ -19,7 +26,7 @@ class HaystackTag < BaseTag
19
26
  end
20
27
 
21
28
  def full_path
22
- ancestors.reverse.map(&:name).join(" > ") + " > " + name
29
+ "#{ancestors.reverse.map(&:name).join(' > ')} > #{name}"
23
30
  end
24
31
 
25
32
  def self.find_by_path(path)
@@ -52,9 +59,24 @@ class HaystackTag < BaseTag
52
59
  ancestors.size
53
60
  end
54
61
 
62
+ def category
63
+ ancestors.empty? ? name : parent_tag.category
64
+ end
65
+
66
+ private
67
+
55
68
  def prevent_circular_reference
56
69
  return unless parent_tag == self || ancestors.include?(self)
57
70
 
58
- errors.add(:parent_tag, "cannot contain a circular reference")
71
+ errors.add(:parent_tag, "Kan geen circulaire referentie bevatten")
72
+ end
73
+
74
+ def ensure_identity
75
+ return if root? && name == category
76
+
77
+ return unless HaystackTag.where(name: name).any? { |tag| tag.category == category }
78
+
79
+ Rails.logger.error("Duplicate tag found: #{name} within category: #{category}")
80
+ errors.add(:name, "Moet uniek zijn binnen dezelfde categorie")
59
81
  end
60
82
  end
@@ -0,0 +1,9 @@
1
+ class DefaultTagStrategy < TagStrategy
2
+ def create_tag(name, description)
3
+ HaystackTag.create(name: name, description: description)
4
+ end
5
+
6
+ def update_tag(tag, attributes)
7
+ tag.update(attributes)
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ class FindByTagsStrategy < QueryStrategy
2
+ def initialize(model, tags)
3
+ super()
4
+ @model = model
5
+ @tags = tags
6
+ end
7
+
8
+ def execute
9
+ @model.joins(:haystack_tags).where(haystack_tags: { id: @tags.map(&:id) })
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class FindPointsWithTagStrategy < QueryStrategy
2
+ def initialize(model, tag)
3
+ super()
4
+ @model = model
5
+ @tag = tag
6
+ end
7
+
8
+ def execute
9
+ @model.joins(:haystack_tags).where(haystack_tags: { id: @tag.id })
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ class FindPointsWithMultipleTagsStrategy < QueryStrategy
2
+ def initialize(model, tags)
3
+ super()
4
+ @model = model
5
+ @tags = tags
6
+ end
7
+
8
+ def execute
9
+ @model.joins(:haystack_tags)
10
+ .where(haystack_tags: { id: @tags.map(&:id) })
11
+ .group("#{@model.table_name}.id")
12
+ .having("COUNT(haystack_tags.id) = ?", @tags.size)
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ class OntologyTagStrategy < TagStrategy
2
+ def create_tag(name, description)
3
+ HaystackTag.find_or_create_by(name: name).tap do |tag|
4
+ tag.update(description: description)
5
+ end
6
+ end
7
+
8
+ def update_tag(tag, attributes)
9
+ tag.update(attributes)
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class QueryContext
2
+ def initialize(strategy)
3
+ @strategy = strategy
4
+ end
5
+
6
+ def execute
7
+ @strategy.execute
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class QueryStrategy
2
+ def execute
3
+ raise NotImplementedError, "Subclasses must implement the execute method"
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class TagStrategy
2
+ def create_tag(name, description)
3
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
4
+ end
5
+
6
+ def update_tag(tag, attributes)
7
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
8
+ end
9
+ end
@@ -1 +1 @@
1
- VERSION = "1.0.4".freeze
1
+ VERSION = "1.0.6".freeze
@@ -4,12 +4,21 @@ require "needle_in_a_haystack/application_record"
4
4
  require "needle_in_a_haystack/configuration"
5
5
  require "needle_in_a_haystack/concerns/base_tagging"
6
6
  require "needle_in_a_haystack/concerns/base_tag"
7
- require "needle_in_a_haystack/concerns/base_factory"
7
+ require "needle_in_a_haystack/factories/base_factory"
8
8
 
9
9
  require "needle_in_a_haystack/models/haystack_ontology"
10
+ require "needle_in_a_haystack/concerns/taggable"
10
11
  require "needle_in_a_haystack/models/haystack_tag"
11
12
  require "needle_in_a_haystack/models/haystack_tagging"
12
- require "needle_in_a_haystack/services/haystack_factory"
13
+ require "needle_in_a_haystack/factories/haystack_factory"
14
+ require "needle_in_a_haystack/strategies/query_context"
15
+ require "needle_in_a_haystack/strategies/query_strategy"
16
+ require "needle_in_a_haystack/strategies/find_by_tags_strategy"
17
+ require "needle_in_a_haystack/strategies/find_point_by_tag_strategy"
18
+ require "needle_in_a_haystack/strategies/find_points_with_multiple_tags_strategy"
19
+ require "needle_in_a_haystack/strategies/tag_strategy"
20
+ require "needle_in_a_haystack/strategies/default_tag_strategy"
21
+ require "needle_in_a_haystack/strategies/ontology_tag_strategy"
13
22
 
14
23
  module NeedleInAHaystack
15
24
  class << self
@@ -1,5 +1,5 @@
1
1
  FactoryBot.define do
2
- factory :haystack_tag, class: "NeedleInAHaystack::HaystackTag" do
2
+ factory :haystack_tag, class: "HaystackTag" do
3
3
  sequence(:name) { |n| "Tag #{n}" }
4
4
  sequence(:description) { |n| "Description #{n}" }
5
5
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: needle_in_a_haystack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frans Verberne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-28 00:00:00.000000000 Z
11
+ date: 2024-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcrypt_pbkdf
@@ -275,18 +275,27 @@ files:
275
275
  - config/initializers/redis.rb
276
276
  - config/initializers/wrap_parameters.rb
277
277
  - config/locales/en.yml
278
+ - lib/haystack_ontology.yml
278
279
  - lib/needle_in_a_haystack.rb
279
280
  - lib/needle_in_a_haystack/application_record.rb
280
- - lib/needle_in_a_haystack/concerns/base_factory.rb
281
281
  - lib/needle_in_a_haystack/concerns/base_tag.rb
282
282
  - lib/needle_in_a_haystack/concerns/base_tagging.rb
283
283
  - lib/needle_in_a_haystack/concerns/taggable.rb
284
284
  - lib/needle_in_a_haystack/configuration.rb
285
285
  - lib/needle_in_a_haystack/engine.rb
286
+ - lib/needle_in_a_haystack/factories/base_factory.rb
287
+ - lib/needle_in_a_haystack/factories/haystack_factory.rb
286
288
  - lib/needle_in_a_haystack/models/haystack_ontology.rb
287
289
  - lib/needle_in_a_haystack/models/haystack_tag.rb
288
290
  - lib/needle_in_a_haystack/models/haystack_tagging.rb
289
- - lib/needle_in_a_haystack/services/haystack_factory.rb
291
+ - lib/needle_in_a_haystack/strategies/default_tag_strategy.rb
292
+ - lib/needle_in_a_haystack/strategies/find_by_tags_strategy.rb
293
+ - lib/needle_in_a_haystack/strategies/find_point_by_tag_strategy.rb
294
+ - lib/needle_in_a_haystack/strategies/find_points_with_multiple_tags_strategy.rb
295
+ - lib/needle_in_a_haystack/strategies/ontology_tag_strategy.rb
296
+ - lib/needle_in_a_haystack/strategies/query_context.rb
297
+ - lib/needle_in_a_haystack/strategies/query_strategy.rb
298
+ - lib/needle_in_a_haystack/strategies/tag_strategy.rb
290
299
  - lib/needle_in_a_haystack/version.rb
291
300
  - lib/tasks/location_create.rake
292
301
  - spec/factories/haystack_tags.rb
@@ -310,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
310
319
  - !ruby/object:Gem::Version
311
320
  version: '0'
312
321
  requirements: []
313
- rubygems_version: 3.5.22
322
+ rubygems_version: 3.5.18
314
323
  signing_key:
315
324
  specification_version: 4
316
325
  summary: Models and dependencies shared across our projects.
@@ -1,15 +0,0 @@
1
- class HaystackFactory < BaseFactory
2
- def create_tag(name, description)
3
- HaystackTag.create(name: name, description: description)
4
- end
5
-
6
- def create_tagging(tag, taggable)
7
- HaystackTagging.create(haystack_tag: tag, taggable: taggable)
8
- end
9
-
10
- def find_or_create_tag(name, attributes = {})
11
- tag = HaystackTag.find_or_create_by(name: name)
12
- tag.update(attributes)
13
- tag
14
- end
15
- end