• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MushroomObserver / mushroom-observer / 14217149209

02 Apr 2025 10:14AM UTC coverage: 93.77% (-0.04%) from 93.809%
14217149209

Pull #2856

github

nimmolo
Merge branch 'main' into query-scopes-am
Pull Request #2856: Query AR - final round PR branch

154 of 162 new or added lines in 29 files covered. (95.06%)

19 existing lines in 4 files now uncovered.

26492 of 28252 relevant lines covered (93.77%)

613.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.75
/app/models/location_description.rb
1
# frozen_string_literal: true
2

3
#
4
#  = Location Descriptions
5
#
6
#  == Version
7
#
8
#  Changes are kept in the "location_description_versions" table using
9
#  ActiveRecord::Acts::Versioned.
10
#
11
#  == Attributes
12
#
13
#  id::               (-) Locally unique numerical id, starting at 1.
14
#  created_at::       (-) Date/time it was first created.
15
#  updated_at::       (V) Date/time it was last updated.
16
#  user::             (V) User that created it.
17
#  version::          (V) Version number.
18
#
19
#  ==== Statistics
20
#  num_views::        (-) Number of times it has been viewed.
21
#  last_view::        (-) Last time it was viewed.
22
#
23
#  ==== Description Fields
24
#  license::          (V) License description info is kept under.
25
#  gen_desc::         (V) General description of geographic location.
26
#  ecology::          (V) Description of climate, geology, habitat, etc.
27
#  species::          (V) Notes on dominant or otherwise interesting species.
28
#  notes::            (V) Other notes.
29
#  refs::             (V) References
30
#
31
#  ('V' indicates that this attribute is versioned in
32
#  location_description_versions table.)
33
#
34
#  == Class Methods
35
#
36
#  all_note_fields::     NameDescriptive text fields: all.
37
#
38
#  == Instance Methods
39
#
40
#  versions::            Old versions.
41
#  comments::            Comments about this NameDescription. (not used yet)
42
#  interests::           Interest in this NameDescription
43
#
44
#  == Callbacks
45
#
46
#  notify_users::       Notify authors, etc. of changes.
47
#
48
############################################################################
49

50
class LocationDescription < Description
1✔
51
  require("acts_as_versioned")
1✔
52

53
  include Description::Scopes
1✔
54

55
  # Do not change the integer associated with a value
56
  enum :source_type,
1✔
57
       { public: 1, foreign: 2, project: 3, source: 4, user: 5 },
58
       suffix: :source, instance_methods: false
59

60
  belongs_to :license
1✔
61
  belongs_to :location
1✔
62
  belongs_to :project
1✔
63
  belongs_to :user
1✔
64

65
  has_many :comments,  as: :target, dependent: :destroy, inverse_of: :target
1✔
66
  has_many :interests, as: :target, dependent: :destroy, inverse_of: :target
1✔
67

68
  has_many :location_description_admins, dependent: :destroy
1✔
69
  has_many :admin_groups, through: :location_description_admins,
1✔
70
                          source: :user_group
71

72
  has_many :location_description_writers, dependent: :destroy
1✔
73
  has_many :writer_groups, through: :location_description_writers,
1✔
74
                           source: :user_group
75

76
  has_many :location_description_readers, dependent: :destroy
1✔
77
  has_many :reader_groups, through: :location_description_readers,
1✔
78
                           source: :user_group
79

80
  has_many :location_description_authors, dependent: :destroy
1✔
81
  has_many :authors, through: :location_description_authors,
1✔
82
                     source: :user
83

84
  has_many :location_description_editors, dependent: :destroy
1✔
85
  has_many :editors, through: :location_description_editors,
1✔
86
                     source: :user
87

88
  scope :order_by_default,
1✔
89
        -> { order_by(::Query::LocationDescriptions.default_order) }
32✔
90

91
  scope :is_public, lambda { |bool = true|
1✔
92
    where(public: bool)
9✔
93
  }
94
  scope :by_author, lambda { |user|
1✔
95
    ids = lookup_users_by_name(user)
13✔
96
    joins(:location_description_authors).
13✔
97
      where(location_description_authors: { user_id: ids })
98
  }
99
  scope :by_editor, lambda { |user|
1✔
100
    ids = lookup_users_by_name(user)
12✔
101
    joins(:location_description_editors).
12✔
102
      where(location_description_editors: { user_id: ids })
103
  }
104
  scope :locations, lambda { |loc|
1✔
105
    ids = lookup_locations_by_name(loc)
3✔
106
    where(location: ids)
3✔
107
  }
108

109
  scope :location_query, lambda { |hash|
1✔
NEW
110
    joins(:location).subquery(:Location, hash)
×
111
  }
112

113
  scope :show_includes, lambda {
1✔
114
    strict_loading.includes(
9✔
115
      :authors,
116
      { comments: :user },
117
      :editors,
118
      :interests,
119
      { location: [:descriptions, :interests, :rss_log] },
120
      :project,
121
      :user,
122
      :versions
123
    )
124
  }
125

126
  ALL_NOTE_FIELDS = [:gen_desc, :ecology, :species, :notes, :refs].freeze
1✔
127
  SEARCHABLE_FIELDS = ALL_NOTE_FIELDS
1✔
128

129
  acts_as_versioned(
1✔
130
    if_changed: ALL_NOTE_FIELDS,
131
    association_options: { dependent: :nullify }
132
  )
133
  non_versioned_columns.push(
1✔
134
    "created_at",
135
    "updated_at",
136
    "location_id",
137
    "num_views",
138
    "last_view",
139
    "ok_for_export",
140
    "source_type",
141
    "source_name",
142
    "project_id",
143
    "public",
144
    "locale"
145
  )
146

147
  versioned_class.before_save { |x| x.user_id = User.current_id }
19✔
148
  after_update :notify_users
1✔
149

150
  ##############################################################################
151
  #
152
  #  :section: Descriptions
153
  #
154
  ##############################################################################
155
  def self.show_controller
1✔
156
    # Not the generated default in AbstractModel, because controller namespaced.
157
    "/locations/descriptions"
108✔
158
  end
159

160
  # Returns an Array of all the descriptive text fields (Symbol's).
161
  def self.all_note_fields
1✔
162
    ALL_NOTE_FIELDS
45✔
163
  end
164

165
  # This is called after saving potential changes to a Location.  It will
166
  # determine if the changes are important enough to notify people, and do so.
167
  def notify_users
1✔
168
    return unless saved_version_changes?
34✔
169

170
    sender = User.current
11✔
171
    recipients = []
11✔
172

173
    # Tell admins of the change.
174
    admins.each do |user|
11✔
175
      recipients.push(user) if user.email_locations_admin
8✔
176
    end
177

178
    # Tell authors of the change.
179
    authors.each do |user|
11✔
180
      recipients.push(user) if user.email_locations_author
10✔
181
    end
182

183
    # Tell editors of the change.
184
    editors.each do |user|
11✔
185
      recipients.push(user) if user.email_locations_editor
13✔
186
    end
187

188
    # Send to people who have registered interest.
189
    # Also remove everyone who has explicitly said they are NOT interested.
190
    location.interests.each do |interest|
11✔
191
      if interest.state
×
192
        recipients.push(interest.user)
×
193
      else
194
        recipients.delete(interest.user)
×
195
      end
196
    end
197

198
    # Remove users who have opted out of all emails.
199
    recipients.reject!(&:no_emails)
11✔
200

201
    # Send notification to all except the person who triggered the change.
202
    (recipients.uniq - [sender]).each do |recipient|
11✔
203
      QueuedEmail::LocationChange.create_email(
6✔
204
        sender, recipient, location, self
205
      )
206
    end
207
  end
208
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc