hashtags 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 33fc78eb48ce5269728d1563af3c3b11ee111bef
4
+ data.tar.gz: 0058045a7c502225c75d5aed8ff55d9a5877f99a
5
+ SHA512:
6
+ metadata.gz: bcaaf2905df844fd53b1924e48a600e08a3fbcf35d32d961fedcb876fc2c761d86a52db3cf7fd2d07277ab9f029478f3bb358457f046a3ef43bd8eec729e9aab
7
+ data.tar.gz: cf7962a04cf7bbae1281f4fb8426471d62d85d32d645c120f1fd650472dde90bf606d6e58da938ada8c32b1056cb845dec8330e5a768cf94bb8a40525cc44ffb
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,25 @@
1
+ sudo: false
2
+ language: ruby
3
+ dist: trusty
4
+ services:
5
+ - mongodb
6
+ before_install:
7
+ - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa
8
+ - sudo apt-get update -qq
9
+ - sudo apt-get install -qq libqt5webkit5-dev qtdeclarative5-dev
10
+ - export QMAKE=/usr/lib/x86_64-linux-gnu/qt5/bin/qmake
11
+ before_script:
12
+ - "export DISPLAY=:99.0"
13
+ - "sh -e /etc/init.d/xvfb start"
14
+ - sleep 3 # give xvfb some time to start
15
+ script: 'xvfb-run -a bundle exec rake'
16
+ rvm:
17
+ - 2.2.5
18
+ before_install:
19
+ - gem install bundler -v 1.12.5
20
+ notifications:
21
+ email:
22
+ recipients:
23
+ - tomas.celizna@gmail.com
24
+ on_failure: change
25
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,33 @@
1
+ source 'https://rubygems.org'
2
+ source 'https://rails-assets.org'
3
+
4
+ # Specify your gem's dependencies in hashtags.gemspec
5
+ gemspec
6
+
7
+ group :test do
8
+ gem 'rails'
9
+ gem 'sassc'
10
+ gem 'sassc-rails', '~> 1.3'
11
+ gem 'uglifier'
12
+ gem 'coffee-rails'
13
+ gem 'jquery-rails'
14
+ gem 'jbuilder', '~> 2.0'
15
+
16
+ source 'https://rails-assets.org' do
17
+ gem 'rails-assets-jquery-textcomplete'
18
+ gem 'rails-assets-handlebars'
19
+ end
20
+
21
+ gem 'capybara-screenshot'
22
+ gem 'capybara-webkit'
23
+ gem 'database_cleaner'
24
+ gem 'launchy'
25
+ gem 'mongoid'
26
+ gem 'mongoid-minitest'
27
+ gem 'minitest-around'
28
+ gem 'minitest-fail-fast'
29
+ gem 'minitest-matchers_vaccine'
30
+ gem 'minitest-rails'
31
+ gem 'minitest-rails-capybara'
32
+ gem 'minitest-reporters'
33
+ end
@@ -0,0 +1,5 @@
1
+ guard :minitest do
2
+ watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
3
+ watch(%r{^test/.+_test\.rb$})
4
+ watch(%r{^test/test_helper\.rb$}) { 'test' }
5
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Tomas Celizna
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,253 @@
1
+ # Hashtags
2
+
3
+ [![Build Status](https://travis-ci.org/tomasc/hashtags.svg)](https://travis-ci.org/tomasc/hashtags) [![Gem Version](https://badge.fury.io/rb/hashtags.svg)](http://badge.fury.io/rb/hashtags) [![Coverage Status](https://img.shields.io/coveralls/tomasc/hashtags.svg)](https://coveralls.io/r/tomasc/hashtags)
4
+
5
+ Rails engine to facilitate inline text hashtags.
6
+
7
+ - hashtags are entered inline in text, for example as `@tomasc`, `#location:Home(12345)` or `$my_variable`
8
+ - when rendered, they are replaced by actual values, for example HTML tags, images, links etc.
9
+
10
+ Additionally:
11
+
12
+ - the user can be assisted with a dropdown triggered by a special character (`#`, `@`, `$`, ...)
13
+ - a Mongoid field option add support for `.to_markup` and `.to_hashtag` methods and more
14
+ - hashtags typically have `cache_key` defined on class so corresponding fragment cache can be easily expired
15
+
16
+ TODOs:
17
+
18
+ - There's an implicit support for Mongoid, but it should be very easy to make that conditional ev. add support for other ORMs or libs such as Virtus etc.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ ```ruby
25
+ gem 'hashtags'
26
+ ```
27
+
28
+ And then execute:
29
+
30
+ ```
31
+ $ bundle
32
+ ```
33
+
34
+ Or install it yourself as:
35
+
36
+ ```
37
+ $ gem install hashtags
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ The three following types are included in this gem, however the gem's design allows for definition of new types and their subclassing.
43
+
44
+ ### Hash tag types
45
+
46
+ #### User hash tag
47
+
48
+ ```
49
+ @tomasc
50
+ ```
51
+
52
+ #### Resource hash tag
53
+
54
+ These typically include human-readable version of the resource (in the example below it would be `Home`).
55
+
56
+ ```
57
+ #location:Home(12345)
58
+ ```
59
+
60
+ #### Variable hash tag
61
+
62
+ ```
63
+ $number_of_users
64
+ ```
65
+
66
+ ### Adding new hash tags in your application
67
+
68
+ The following are quick examples. It is advised to read the source code of `Hashtags::User`, `Hashtags::Resource` and `Hashtags::Variable` and their superclass `Hashtags::Builder` in order to fully understand the possibilities and flexibility of this gem.
69
+
70
+ #### User
71
+
72
+ See `Hashtags::User` and override its methods on your subclass as necessary. Typically it would be at least the following:
73
+
74
+ ```ruby
75
+ class UserTag < Hashtags::User
76
+ def self.resource_class
77
+ # User
78
+ end
79
+
80
+ def self.tag_attribute
81
+ # name of attribute to be used in the tag
82
+ # @<tag_attribute>
83
+ # for example :username
84
+ end
85
+
86
+ def self.result_attribute
87
+ # the tags will be replaced by this attribute
88
+ # for example :full_name
89
+ end
90
+
91
+ def self.resources_for_query(query)
92
+ # return resources matching query
93
+ # this will be called from the controller as user types
94
+ end
95
+
96
+ def resource(tag_attribute_value)
97
+ # this should find and return resource object
98
+ # self.class.resource_class.find(value)
99
+ end
100
+ end
101
+ ```
102
+
103
+ Implement the `values` class method instead of the `resources_for_query` to preload values.
104
+
105
+ #### Resource
106
+
107
+ See `Hashtags::Resource` and override its methods on your subclass as necessary. Typically it would be at least the following:
108
+
109
+ ```ruby
110
+ class LocationTag < Hashtags::Resource
111
+ def self.resource_class
112
+ # Location
113
+ end
114
+
115
+ def self.tag_attribute
116
+ # name of attribute to be used in the tag
117
+ # #<tag_attribute>(id)
118
+ # for example :to_s
119
+ end
120
+
121
+ def self.result_attribute
122
+ # the tags will be replaced by this attribute
123
+ # for example :to_s
124
+ end
125
+
126
+ def self.resources_for_query(query)
127
+ # return resources matching query
128
+ # this will be called from the controller as user types
129
+ end
130
+
131
+ def resource(value)
132
+ # this should find and return resource object
133
+ # self.class.resource_class.find(value)
134
+ end
135
+ end
136
+ ```
137
+
138
+ Implement the `values` class method instead of the `resources_for_query` to preload values.
139
+
140
+ #### Variable
141
+
142
+ See `Hashtags::Variable` and override its methods on your subclass as necessary. Typically it would be at least the following:
143
+
144
+ ```ruby
145
+ class VariableTag < Hashtags::Resource
146
+ def self.values(hashtag_classes = Hashtags::Variable.descendants)
147
+ # %w(
148
+ # variable_1
149
+ # variable_2
150
+ # )
151
+ end
152
+
153
+ def markup(match)
154
+ # case name(match)
155
+ # when 'variable_1' then 'foo'
156
+ # when 'variable_2' then 'bar'
157
+ # end
158
+ end
159
+ end
160
+ ```
161
+
162
+ ### Usage in an app
163
+
164
+ #### Core
165
+
166
+ ```ruby
167
+ str = 'Current document: #doc:Foo(123).'
168
+ Hashtags::Builder.to_markup(str) # => 'Current document: Foo.'
169
+ ```
170
+
171
+ Since the hashtags might contain human-readable values (as in the `Resource` tags), it is often helpful to update them:
172
+
173
+ ```ruby
174
+ doc.title = 'Bar'
175
+ Hashtags::Builder.to_hashtag(str) # => 'Current document: #doc:Bar(123).'
176
+ ```
177
+
178
+ Optionally, a list of only/except classes can be specified, useful for example for limiting available hashtags in certain situations.
179
+
180
+ ```ruby
181
+ Hashtags::Builder.to_markup(str, only: [LocationTag])
182
+ Hashtags::Builder.to_hashtag(str, except: [UserTag])
183
+ ```
184
+
185
+ #### With Mongoid Extension
186
+
187
+ In case you are using Mongoid, you can use the `hashtags` options to enable hashtags processing and additional helpers. The hashtags will be also automatically processed whenever you save your data to the database (using the above-mentioned `to_hashtag` method).
188
+
189
+ ```ruby
190
+ class MyDoc
191
+ include Mongoid::Document
192
+ field :text, type: String, hashtags: true # or { only: … } or # { except: … }
193
+ end
194
+
195
+ my_doc.text.to_markup # => field value with hashtags converted to markup
196
+ my_doc.text.to_hashtag # => field value with hashtags updated
197
+ ```
198
+
199
+ Next to that the following helper class methods will be defined:
200
+
201
+ ```ruby
202
+ MyDoc.hashtags['text'].dom_data # => outcome of builder's dom_data method
203
+ MyDoc.hashtags['text'].help # => outcome of builder's help method
204
+ MyDoc.hashtags['text'].options # => hashtags builder options { only: … } or { except: … }
205
+ ```
206
+
207
+ #### With JS textcomplete plugin
208
+
209
+ Finally, it is fairly straightforward to add support for JS textcomplete that assists the user when inserting tags.
210
+
211
+ Require the `hashtags` javascript.
212
+
213
+ ```javascript
214
+ // application.js
215
+ //= require hashtags
216
+ ```
217
+
218
+ In routes:
219
+
220
+ ```ruby
221
+ mount Hashtags::Engine => '/'
222
+ ```
223
+
224
+ Optionally add default CSS.
225
+
226
+ ```css
227
+ /* application.css */
228
+ /*
229
+ *= require hashtags
230
+ */
231
+ ```
232
+
233
+ In a form:
234
+
235
+ ```slim
236
+ fieldset
237
+ = form.text_area :text, data: form.object.class.hashtags['text'].dom_data
238
+ = render_help_for(form.object.class, :text)
239
+ ```
240
+
241
+ ## Development
242
+
243
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
244
+
245
+ 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).
246
+
247
+ ## Contributing
248
+
249
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/tomasc/hashtags>.
250
+
251
+ ## License
252
+
253
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,19 @@
1
+ # begin
2
+ # require 'bundler/setup'
3
+ # rescue LoadError
4
+ # puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ # end
6
+
7
+ require 'bundler/gem_tasks'
8
+ require 'rake/testtask'
9
+
10
+ # APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
11
+ # load 'rails/tasks/engine.rake'
12
+
13
+ Rake::TestTask.new(:test) do |t|
14
+ t.libs << 'test'
15
+ t.libs << 'lib'
16
+ t.test_files = FileList['test/**/*_test.rb']
17
+ end
18
+
19
+ task default: :test
@@ -0,0 +1,28 @@
1
+ module Hashtags
2
+ class ResourcesController < ApplicationController
3
+ def index
4
+ respond_to do |format|
5
+ format.json { render json: resources_as_json, root: false }
6
+ end
7
+ end
8
+
9
+ private
10
+
11
+ def resources_as_json
12
+ return unless hashtag_class.present?
13
+ @resources_as_json ||= hashtag_class.resources_for_query(query)
14
+ end
15
+
16
+ def query
17
+ URI.decode(params.fetch(:q, nil).to_s)
18
+ end
19
+
20
+ def hashtag_class
21
+ class_name.safe_constantize
22
+ end
23
+
24
+ def class_name
25
+ params[:class_name]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,8 @@
1
+ module Hashtags
2
+ module ViewHelper
3
+ def render_help_for(cls, field_name)
4
+ return unless help = cls.hashtags[field_name.to_s].help
5
+ render 'hashtags/help', help: help
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ div.hashtags.help
2
+ - help.each do |item|
3
+ span.trigger_group
4
+ => I18n.t(:type, scope: %i(hashtags/builders help))
5
+ span.trigger => item.trigger
6
+ => I18n.t(:for, scope: %i(hashtags/builders help))
7
+ - item.help_values.each_with_index do |value, index|
8
+ span.item = value
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "hashtags"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start