rokaki 0.10.0 → 0.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5dac3a2881b83e34f6e0ee5717c4103212b3c4606b0ca05420338544a56cdffd
4
- data.tar.gz: 594b1e1ff90e0a86674ed06e0de962a3cf622814cc87f02317a1da4ddcceb437
3
+ metadata.gz: a8fb8c022307112af51183df513130d6ad467142320a4db9be178870583c2394
4
+ data.tar.gz: 611539f7d9500f30c5a847a89a7548119c14d4eac47761e9c08b5e706ae9f77c
5
5
  SHA512:
6
- metadata.gz: 1246c456cd8c613d8288a5d6bc69c65eedd67545b854b2185f512b071a04e1341c9bffe9f86a713ab9106842a8b015a73b0f8f55e9d0fecf8741b47e824c015b
7
- data.tar.gz: 2429fb0148ca0705edcf02bb434541968db87a7bda6cd26a0945d1ccec660b6a9ca45ff9f5798aeeedfd4f89371f3c1575f2d0f79d1914a695b4f898d35bf4b4
6
+ metadata.gz: 3648caca4052f03440da996d1aed083c3ba9a29a5f14f06e9e9b2757d4d95f3356e793e22f1b1ebe0a149536a001367e6006d26d8521ce518885e32c36502130
7
+ data.tar.gz: ca064a797447597677bd5b2d2e00f6a2836bc5e69341990ac7da0742ccdc41383834f7a8c9bb6c4089a37e0293786c2536727b5c79d1dabf05a4c9df20f02b77
@@ -25,8 +25,24 @@ jobs:
25
25
  - 5432:5432
26
26
  # needed because the postgres container does not provide a healthcheck
27
27
  options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
28
+
29
+ sqlserver:
30
+ image: mcr.microsoft.com/mssql/server:2022-latest
31
+ env:
32
+ ACCEPT_EULA: "Y"
33
+ MSSQL_SA_PASSWORD: "5QL5£rv£r"
34
+ ports:
35
+ - 1433:1433
36
+ # No built-in healthcheck; we'll wait in a step using nc
37
+
28
38
  steps:
29
39
  - uses: actions/checkout@v2
40
+
41
+ - name: Install system dependencies
42
+ run: |
43
+ sudo apt-get update
44
+ sudo apt-get install -y build-essential libpq-dev default-libmysqlclient-dev freetds-dev netcat-openbsd
45
+
30
46
  - name: Set up Ruby
31
47
  uses: ruby/setup-ruby@v1
32
48
  with:
@@ -34,6 +50,20 @@ jobs:
34
50
  ruby-version: 3.3.0
35
51
  # runs 'bundle install' and caches installed gems automatically
36
52
  bundler-cache: true
53
+
54
+ - name: Wait for databases to be ready
55
+ shell: bash
56
+ run: |
57
+ for i in {1..60}; do
58
+ nc -z 127.0.0.1 3306 && echo "MySQL up" && break || sleep 1
59
+ done
60
+ for i in {1..60}; do
61
+ nc -z 127.0.0.1 5432 && echo "Postgres up" && break || sleep 1
62
+ done
63
+ for i in {1..120}; do
64
+ nc -z 127.0.0.1 1433 && echo "SQL Server up" && break || sleep 1
65
+ done
66
+
37
67
  - name: Run tests
38
68
  run: |
39
69
  ./spec/ordered_run.sh
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rokaki (0.10.0)
4
+ rokaki (0.11.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -13,6 +13,9 @@ GEM
13
13
  activemodel (= 8.0.3)
14
14
  activesupport (= 8.0.3)
15
15
  timeout (>= 0.4.0)
16
+ activerecord-sqlserver-adapter (8.0.9)
17
+ activerecord (~> 8.0.0)
18
+ tiny_tds
16
19
  activesupport (8.0.3)
17
20
  base64
18
21
  benchmark (>= 0.3)
@@ -132,6 +135,16 @@ GEM
132
135
  sqlite3 (2.7.4-x86_64-linux-musl)
133
136
  thor (1.4.0)
134
137
  timeout (0.4.3)
138
+ tiny_tds (3.3.0)
139
+ bigdecimal (~> 3)
140
+ tiny_tds (3.3.0-aarch64-linux-gnu)
141
+ bigdecimal (~> 3)
142
+ tiny_tds (3.3.0-aarch64-linux-musl)
143
+ bigdecimal (~> 3)
144
+ tiny_tds (3.3.0-x86_64-linux-gnu)
145
+ bigdecimal (~> 3)
146
+ tiny_tds (3.3.0-x86_64-linux-musl)
147
+ bigdecimal (~> 3)
135
148
  tzinfo (2.0.6)
136
149
  concurrent-ruby (~> 1.0)
137
150
  uri (1.0.3)
@@ -152,6 +165,7 @@ PLATFORMS
152
165
 
153
166
  DEPENDENCIES
154
167
  activerecord
168
+ activerecord-sqlserver-adapter
155
169
  bundler (~> 2.0)
156
170
  database_cleaner-active_record
157
171
  factory_bot
@@ -165,6 +179,7 @@ DEPENDENCIES
165
179
  rokaki!
166
180
  rspec (~> 3.0)
167
181
  sqlite3
182
+ tiny_tds
168
183
 
169
184
  BUNDLED WITH
170
185
  2.5.3
data/README.md CHANGED
@@ -1,10 +1,15 @@
1
1
  # Rokaki
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rokaki.svg)](https://badge.fury.io/rb/rokaki)
4
+ [![Run RSpec tests](https://github.com/tevio/rokaki/actions/workflows/spec.yml/badge.svg)](https://github.com/tevio/rokaki/actions/workflows/spec.yml)
4
5
 
5
- This gem was born out of a desire to dry up filtering services in Rails apps or any Ruby app that uses the concept of "filters" or "facets".
6
+ This gem was written to dry up filtering services in ActiveRecord based Rails apps or any plain Ruby app looking to implement "filters" or "faceted" search.
6
7
 
7
- There are two modes of use `Filterable` and `FilterModel` that can be activated through the use of two mixins respectively, `include Rokaki::Filterable` or `include Rokaki::FilterModel`.
8
+ The overall vision is to abstract away all of the lower level repetitive SQL and relational code to allow you to write model filters in a simple, relatively intuitive way, using ruby hashes and arrays mostly.
9
+
10
+ The DSL allows you to construct complex search models to filter results through without writing any SQL. I would recommend the reader to consult the specs in order to understand the features and syntax in detail, an intermediate understanding of Ruby and rspec TDD, and basic relational logic are recommended.
11
+
12
+ There are two modes of use, `Filterable` (designed for plain Ruby) and `FilterModel` (designed for Rails) that can be activated through the use of two mixins respectively, `include Rokaki::Filterable` or `include Rokaki::FilterModel`.
8
13
  ## Installation
9
14
 
10
15
  Add this line to your application's Gemfile:
@@ -137,7 +142,7 @@ You can specify several configuration options, for example a `filter_key_prefix`
137
142
  ## `Rokaki::FilterModel` - Usage
138
143
 
139
144
  ### ActiveRecord
140
- Include `Rokaki::FilterModel` in any ActiveRecord model (only AR >= 6.0.0 tested so far) you can generate the filter keys and the actual filter lookup code using the `filters` keyword on a model like so:-
145
+ Include `Rokaki::FilterModel` in any ActiveRecord model (only AR >= 8.0.3 tested so far) you can generate the filter keys and the actual filter lookup code using the `filters` keyword on a model like so:-
141
146
 
142
147
  ```ruby
143
148
  # Given the models
@@ -173,7 +178,7 @@ You can also filter collections of fields, simply pass an array of filter values
173
178
 
174
179
 
175
180
  ### Partial matching
176
- You can use `like` (or, if you use postgres, the case insensitive `ilike`) to perform a partial match on a specific field, there are 3 options:- `:prefix`, `:circumfix` and `:suffix`. There are two syntaxes you can use for this:-
181
+ You can use `like` or the case insensitive `ilike` to perform a partial match on a specific field, there are 3 options:- `:prefix`, `:circumfix` and `:suffix`. There are two syntaxes you can use for this:-
177
182
 
178
183
  #### 1. The `filter` command syntax
179
184
 
@@ -183,7 +188,7 @@ class ArticleFilter
183
188
  include Rokaki::FilterModel
184
189
 
185
190
  filter :article,
186
- like: { # you can use ilike here instead if you use postgres and want case insensitive results
191
+ like: { # you can use ilike here instead if you want case insensitive results
187
192
  author: {
188
193
  first_name: :circumfix,
189
194
  last_name: :circumfix
@@ -323,7 +328,7 @@ class ArticleFilter
323
328
 
324
329
  filters :date, :title, author: [:first_name, :last_name]
325
330
  like title: :circumfix
326
- # ilike title: :circumfix # case insensitive postgres mode
331
+ # ilike title: :circumfix # case insensitive mode
327
332
 
328
333
  attr_accessor :filters
329
334
 
@@ -436,7 +441,13 @@ docker pull mysql
436
441
  docker run --name rokaki-mysql -e MYSQL_ROOT_PASSWORD=rokaki -e MYSQL_PASSWORD=rokaki -e MYSQL_DATABASE=rokaki -e MYSQL_USER=rokaki -d -p 3306:3306 mysql:latest mysqld
437
442
  ```
438
443
 
439
- Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
444
+ ### Specialised test runner
445
+ The test suite is designed to run against all supported database backends, since this can cause problems with timing and connection pools, the recommended way to run the tests is via a shell script.
446
+
447
+ From the rokaki root directory run: `./spec/ordered_run.sh`. This is the same script that runs on the Github CI here: [![Run RSpec tests](https://github.com/tevio/rokaki/actions/workflows/spec.yml/badge.svg)](https://github.com/tevio/rokaki/actions/workflows/spec.yml)
448
+
449
+ ### Standard test runner (only recommended for development cycles)
450
+ You can still run `rake spec` to run the tests, there's no guarantee they will all pass due to race conditions from using multiple db backends (see above), but this mode is recommended for focusing on specific backends or tests during development (comment out what you don't want). You can also run `bin/console` for an interactive prompt that will allow you to experiment.
440
451
 
441
452
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
442
453
 
@@ -38,6 +38,10 @@ module Rokaki
38
38
  'LIKE'
39
39
  elsif db == :mysql
40
40
  'LIKE BINARY'
41
+ elsif db == :sqlserver
42
+ 'LIKE'
43
+ else
44
+ 'LIKE'
41
45
  end
42
46
  end
43
47
 
@@ -46,6 +50,10 @@ module Rokaki
46
50
  'ILIKE'
47
51
  elsif db == :mysql
48
52
  'LIKE'
53
+ elsif db == :sqlserver
54
+ 'LIKE'
55
+ else
56
+ 'LIKE'
49
57
  end
50
58
  end
51
59
 
@@ -94,6 +102,9 @@ module Rokaki
94
102
  if db == :postgres
95
103
  query = "@model.where(\"#{key} #{type} ANY (ARRAY[?])\", "
96
104
  query += "prepare_terms(#{filter}, :#{mode}))"
105
+ elsif db == :sqlserver
106
+ # Delegate to helper that supports arrays and escaping with ESCAPE
107
+ query = "sqlserver_like(@model, \"#{key}\", \"#{type}\", #{filter}, :#{mode})"
97
108
  else
98
109
  query = "@model.where(\"#{key} #{type} :query\", "
99
110
  query += "query: \"%\#{#{filter}}%\")" if mode == :circumfix
@@ -70,6 +70,10 @@ module Rokaki
70
70
  'LIKE'
71
71
  elsif db == :mysql
72
72
  'LIKE BINARY'
73
+ elsif db == :sqlserver
74
+ 'LIKE'
75
+ else
76
+ 'LIKE'
73
77
  end
74
78
  end
75
79
 
@@ -78,6 +82,10 @@ module Rokaki
78
82
  'ILIKE'
79
83
  elsif db == :mysql
80
84
  'LIKE'
85
+ elsif db == :sqlserver
86
+ 'LIKE'
87
+ else
88
+ 'LIKE'
81
89
  end
82
90
  end
83
91
 
@@ -131,19 +139,27 @@ module Rokaki
131
139
  where = where.join
132
140
 
133
141
  if search_mode
134
- query = build_like_query(
135
- type: type,
136
- query: '',
137
- filter: "#{prefix}#{name}",
138
- search_mode: search_mode,
139
- key: keys.last.to_s.pluralize,
140
- leaf: leaf
141
- )
142
+ if db == :sqlserver
143
+ key_leaf = "#{keys.last.to_s.pluralize}.#{leaf}"
144
+ @filter_methods << "def #{prefix}filter#{infix}#{name};"\
145
+ "sqlserver_like(@model.joins(#{joins}), \"#{key_leaf}\", \"#{type}\", #{prefix}#{name}, :#{search_mode}); end;"
142
146
 
143
- @filter_methods << "def #{prefix}filter#{infix}#{name};"\
144
- "@model.joins(#{joins}).#{query}; end;"
145
-
146
- @filter_templates << "@model = #{prefix}filter#{infix}#{name} if #{prefix}#{name};"
147
+ @filter_templates << "@model = #{prefix}filter#{infix}#{name} if #{prefix}#{name};"
148
+ else
149
+ query = build_like_query(
150
+ type: type,
151
+ query: '',
152
+ filter: "#{prefix}#{name}",
153
+ search_mode: search_mode,
154
+ key: keys.last.to_s.pluralize,
155
+ leaf: leaf
156
+ )
157
+
158
+ @filter_methods << "def #{prefix}filter#{infix}#{name};"\
159
+ "@model.joins(#{joins}).#{query}; end;"
160
+
161
+ @filter_templates << "@model = #{prefix}filter#{infix}#{name} if #{prefix}#{name};"
162
+ end
147
163
  else
148
164
  @filter_methods << "def #{prefix}filter#{infix}#{name};"\
149
165
  "@model.joins(#{joins}).where(#{where}); end;"
@@ -194,22 +194,37 @@ module Rokaki
194
194
  leaf = nil
195
195
  leaf = keys.pop
196
196
 
197
+ # Compute key_leaf (qualified column) like other branches
198
+ key_leaf = keys.last ? "#{keys.last.to_s.pluralize}.#{leaf}" : leaf
199
+
200
+ if db == :sqlserver
201
+ # Build relation base with joins
202
+ if join_map.empty?
203
+ rel_expr = "@model"
204
+ elsif join_map.is_a?(Array)
205
+ rel_expr = "@model.joins(*#{join_map})"
206
+ else
207
+ rel_expr = "@model.joins(**#{join_map})"
208
+ end
197
209
 
198
- query = build_like_query(
199
- type: type,
200
- query: '',
201
- filter: filter_name,
202
- search_mode: search_mode,
203
- key: keys.last,
204
- leaf: leaf
205
- )
206
-
207
- if join_map.empty?
208
- filter_query = "@model.#{query}"
209
- elsif join_map.is_a?(Array)
210
- filter_query = "@model.joins(*#{join_map}).#{query}"
210
+ filter_query = "sqlserver_like(#{rel_expr}, \"#{key_leaf}\", \"#{type.to_s.upcase}\", #{filter_name}, :#{search_mode})"
211
211
  else
212
- filter_query = "@model.joins(**#{join_map}).#{query}"
212
+ query = build_like_query(
213
+ type: type,
214
+ query: '',
215
+ filter: filter_name,
216
+ search_mode: search_mode,
217
+ key: keys.last,
218
+ leaf: leaf
219
+ )
220
+
221
+ if join_map.empty?
222
+ filter_query = "@model.#{query}"
223
+ elsif join_map.is_a?(Array)
224
+ filter_query = "@model.joins(*#{join_map}).#{query}"
225
+ else
226
+ filter_query = "@model.joins(**#{join_map}).#{query}"
227
+ end
213
228
  end
214
229
 
215
230
  if mode == or_key
@@ -225,9 +240,20 @@ module Rokaki
225
240
  if db == :postgres
226
241
  query = "where(\"#{key_leaf} #{type.to_s.upcase} ANY (ARRAY[?])\", "
227
242
  query += "prepare_terms(#{filter}, :#{search_mode}))"
228
- else
243
+ elsif db == :mysql
229
244
  query = "where(\"#{key_leaf} #{type.to_s.upcase} :query\", "
230
245
  query += "query: prepare_regex_terms(#{filter}, :#{search_mode}))"
246
+ else # :sqlserver and others
247
+ query = "where(\"#{key_leaf} #{type.to_s.upcase} :query\", "
248
+ if search_mode == :circumfix
249
+ query += "query: \"%\#{#{filter}}%\")"
250
+ elsif search_mode == :prefix
251
+ query += "query: \"%\#{#{filter}}\")"
252
+ elsif search_mode == :suffix
253
+ query += "query: \"\#{#{filter}}%\")"
254
+ else
255
+ query += "query: \"%\#{#{filter}}%\")"
256
+ end
231
257
  end
232
258
 
233
259
  query
@@ -19,6 +19,56 @@ module Rokaki
19
19
  end
20
20
  end
21
21
 
22
+ # Escape special LIKE characters in SQL Server patterns: %, _, [ and \\
23
+ def escape_like(term)
24
+ term.to_s.gsub(/[\\%_\[]/) { |m| "\\#{m}" }
25
+ end
26
+
27
+ # Build LIKE patterns with proper prefix/suffix/circumfix and escaping for SQL Server
28
+ # Returns a String when param is scalar, or an Array of Strings when param is an Array
29
+ def prepare_like_terms(param, mode)
30
+ if Array === param
31
+ case mode
32
+ when :circumfix
33
+ param.map { |t| "%#{escape_like(t)}%" }
34
+ when :prefix
35
+ param.map { |t| "%#{escape_like(t)}" }
36
+ when :suffix
37
+ param.map { |t| "#{escape_like(t)}%" }
38
+ else
39
+ param.map { |t| "%#{escape_like(t)}%" }
40
+ end
41
+ else
42
+ case mode
43
+ when :circumfix
44
+ "%#{escape_like(param)}%"
45
+ when :prefix
46
+ "%#{escape_like(param)}"
47
+ when :suffix
48
+ "#{escape_like(param)}%"
49
+ else
50
+ "%#{escape_like(param)}%"
51
+ end
52
+ end
53
+ end
54
+
55
+ # Compose a SQL Server LIKE relation supporting arrays of terms (OR chained)
56
+ # column should be a fully qualified column expression, e.g., "authors.first_name" or "cs.title"
57
+ # type is usually "LIKE"
58
+ def sqlserver_like(model, column, type, value, mode)
59
+ terms = prepare_like_terms(value, mode)
60
+ if terms.is_a?(Array)
61
+ return model.none if terms.empty?
62
+ rel = model.where("#{column} #{type} :q0 ESCAPE '\\'", q0: terms[0])
63
+ terms[1..-1]&.each_with_index do |t, i|
64
+ rel = rel.or(model.where("#{column} #{type} :q#{i + 1} ESCAPE '\\'", "q#{i + 1}".to_sym => t))
65
+ end
66
+ rel
67
+ else
68
+ model.where("#{column} #{type} :q ESCAPE '\\'", q: terms)
69
+ end
70
+ end
71
+
22
72
  def prepare_regex_terms(param, mode)
23
73
  if Array === param
24
74
  param_map = param.map { |term| ".*#{term}.*" } if mode == :circumfix
@@ -187,6 +237,10 @@ module Rokaki
187
237
  elsif @_filter_db == :mysql
188
238
  # 'LIKE BINARY'
189
239
  'REGEXP'
240
+ elsif @_filter_db == :sqlserver
241
+ 'LIKE'
242
+ else
243
+ 'LIKE'
190
244
  end
191
245
  end
192
246
 
@@ -196,6 +250,10 @@ module Rokaki
196
250
  elsif @_filter_db == :mysql
197
251
  # 'LIKE'
198
252
  'REGEXP'
253
+ elsif @_filter_db == :sqlserver
254
+ 'LIKE'
255
+ else
256
+ 'LIKE'
199
257
  end
200
258
  end
201
259
 
@@ -1,3 +1,3 @@
1
1
  module Rokaki
2
- VERSION = "0.10.0"
2
+ VERSION = "0.11.0"
3
3
  end
data/rokaki.gemspec CHANGED
@@ -47,5 +47,8 @@ Gem::Specification.new do |spec|
47
47
  spec.add_development_dependency 'mysql2'
48
48
  spec.add_development_dependency 'sqlite3'
49
49
  spec.add_development_dependency 'database_cleaner-active_record'
50
+ # For SQL Server testing
51
+ spec.add_development_dependency 'tiny_tds'
52
+ spec.add_development_dependency 'activerecord-sqlserver-adapter'
50
53
 
51
54
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rokaki
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Martin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-10-02 00:00:00.000000000 Z
11
+ date: 2025-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -206,6 +206,34 @@ dependencies:
206
206
  - - ">="
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: tiny_tds
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: activerecord-sqlserver-adapter
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
209
237
  description: A dsl for filtering data in web requests
210
238
  email:
211
239
  - steve@martian.media
@@ -219,7 +247,6 @@ files:
219
247
  - ".rspec"
220
248
  - ".ruby-version"
221
249
  - ".travis.yml"
222
- - CODE_OF_CONDUCT.md
223
250
  - Gemfile
224
251
  - Gemfile.lock
225
252
  - Guardfile
data/CODE_OF_CONDUCT.md DELETED
@@ -1,74 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at steve@martian.media. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/