rails_stuff 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +24 -0
- data/.travis.yml +8 -0
- data/Gemfile +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +350 -0
- data/Rakefile +22 -0
- data/bin/console +7 -0
- data/bin/git-hooks/pre-commit +14 -0
- data/bin/install_git_hooks +8 -0
- data/bin/setup +8 -0
- data/lib/net/http/debug.rb +26 -0
- data/lib/rails_stuff/helpers/all.rb +12 -0
- data/lib/rails_stuff/helpers/bootstrap.rb +34 -0
- data/lib/rails_stuff/helpers/forms.rb +21 -0
- data/lib/rails_stuff/helpers/links.rb +38 -0
- data/lib/rails_stuff/helpers/resource_form.rb +49 -0
- data/lib/rails_stuff/helpers/text.rb +28 -0
- data/lib/rails_stuff/helpers/translation.rb +29 -0
- data/lib/rails_stuff/helpers.rb +14 -0
- data/lib/rails_stuff/nullify_blank_attrs.rb +23 -0
- data/lib/rails_stuff/params_parser.rb +121 -0
- data/lib/rails_stuff/railtie.rb +54 -0
- data/lib/rails_stuff/random_uniq_attr.rb +48 -0
- data/lib/rails_stuff/redis_storage.rb +119 -0
- data/lib/rails_stuff/resources_controller/actions.rb +31 -0
- data/lib/rails_stuff/resources_controller/basic_helpers.rb +161 -0
- data/lib/rails_stuff/resources_controller/resource_helper.rb +31 -0
- data/lib/rails_stuff/resources_controller/responder.rb +21 -0
- data/lib/rails_stuff/resources_controller/sti_helpers.rb +62 -0
- data/lib/rails_stuff/resources_controller.rb +42 -0
- data/lib/rails_stuff/sort_scope.rb +71 -0
- data/lib/rails_stuff/statusable.rb +130 -0
- data/lib/rails_stuff/test_helpers/rails.rb +6 -0
- data/lib/rails_stuff/test_helpers/response.rb +34 -0
- data/lib/rails_stuff/types_tracker.rb +50 -0
- data/lib/rails_stuff/version.rb +14 -0
- data/lib/rails_stuff.rb +19 -0
- data/rails_stuff.gemspec +25 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 82159ba1a8b42ef1cea7d901d966408ae47dc832
|
4
|
+
data.tar.gz: c4d212a0f28c39142139945488c73c7c5eb10eb4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 767e814c2d06cc0ec03988d0a5a510edeba5407310a3d72c1592ff6e947fb4ee58adba0ad0efa6ee2d0e33a8fbd0d58c5a250a900d2fd5bbb766c7b067028443
|
7
|
+
data.tar.gz: 49ce30b733a8a28ab71dcb6a7cafd496f74f391000f52ae9597be8605810564b781bfc838dff3f92ad8f60d922d6f8ecbf00a99d77390c929caf1a8d4bae3f60
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
AllCops:
|
2
|
+
RunRailsCops: true
|
3
|
+
|
4
|
+
Style/AlignParameters:
|
5
|
+
# Disable, till rubocop supports combination of styles.
|
6
|
+
# Use one of this styles where appropriate, keep it clean, compact and readable.
|
7
|
+
Enabled: false
|
8
|
+
EnforcedStyle:
|
9
|
+
- aligned
|
10
|
+
- with_fixed_indentation
|
11
|
+
Style/ClosingParenthesisIndentation: {Enabled: false}
|
12
|
+
Style/Documentation: {Enabled: false}
|
13
|
+
Style/DotPosition: {EnforcedStyle: trailing}
|
14
|
+
Style/IfUnlessModifier: {Enabled: false}
|
15
|
+
Style/ModuleFunction: {Enabled: false}
|
16
|
+
Style/MultilineOperationIndentation: {EnforcedStyle: indented}
|
17
|
+
Style/PredicateName: {Enabled: false}
|
18
|
+
Style/SignalException: {EnforcedStyle: only_raise}
|
19
|
+
Style/SpaceInsideHashLiteralBraces: {EnforcedStyle: no_space}
|
20
|
+
Style/TrailingComma: {Enabled: false}
|
21
|
+
|
22
|
+
Metrics/AbcSize: {Max: 19}
|
23
|
+
Metrics/LineLength: {Max: 100}
|
24
|
+
Metrics/MethodLength: {Max: 30}
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
group :development do
|
5
|
+
gem 'sdoc', '~> 0.4.1'
|
6
|
+
gem 'pry', '~> 0.10.1'
|
7
|
+
|
8
|
+
gem 'sqlite3', '~> 1.3.10'
|
9
|
+
gem 'database_cleaner', '~> 1.5.0'
|
10
|
+
gem 'pooled_redis', '~> 0.2.1'
|
11
|
+
gem 'activemodel_translation', '~> 0.1.0'
|
12
|
+
gem 'has_scope', '~> 0.6.0'
|
13
|
+
gem 'responders', '~> 2.1.0'
|
14
|
+
gem 'kaminari', '~> 0.16.3'
|
15
|
+
|
16
|
+
gem 'rspec', '~> 3.3.0'
|
17
|
+
gem 'rspec-its', '~> 1.1.0'
|
18
|
+
gem 'rspec-rails', '~> 3.3.3'
|
19
|
+
|
20
|
+
gem 'rubocop', '~> 0.33.0'
|
21
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Max Melentiev
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,350 @@
|
|
1
|
+
# RailsStuff
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/rails_stuff.svg)](http://badge.fury.io/rb/rails_stuff)
|
3
|
+
[![Code Climate](https://codeclimate.com/github/printercu/rails_stuff/badges/gpa.svg)](https://codeclimate.com/github/printercu/rails_stuff)
|
4
|
+
[![Build Status](https://travis-ci.org/printercu/rails_stuff.svg)](https://travis-ci.org/printercu/rails_stuff)
|
5
|
+
|
6
|
+
Collection of useful modules for Rails.
|
7
|
+
|
8
|
+
#### Controllers:
|
9
|
+
|
10
|
+
- __[ResourcesController](#resourcescontroller)__
|
11
|
+
DRY! Keep your controllers clean.
|
12
|
+
- __[SortScope](#sortscope)__
|
13
|
+
Helper for `has_scope` to sort collections safely.
|
14
|
+
|
15
|
+
#### Models:
|
16
|
+
|
17
|
+
- __[NullifyBlankAttrs](#nullifyblankattrs)__
|
18
|
+
Proxies writers to replace empty values with `nil`.
|
19
|
+
- __[RandomUniqAttr](#randomuniqattr)__
|
20
|
+
You generate random values for attributes, it'll ensure they are uniq.
|
21
|
+
- __[Statusable](#statusable)__
|
22
|
+
`ActiveRecord::Enum` with more features.
|
23
|
+
- __[TypesTracker](#typestracker)__
|
24
|
+
Advanced descendants tracker.
|
25
|
+
|
26
|
+
#### Misc:
|
27
|
+
|
28
|
+
- __[ParamsParser](#paramsparser)__
|
29
|
+
Type-cast params outside of `ActiveRecord`.
|
30
|
+
- __[RedisStorage](#redisstorage)__
|
31
|
+
Simple way to store collections in key-value storage. With scoping and
|
32
|
+
key generation.
|
33
|
+
|
34
|
+
#### Helpers:
|
35
|
+
|
36
|
+
- __TranslationHelper__
|
37
|
+
`translate_action`, `translate_confirmation` helpers to translate
|
38
|
+
action names and confirmations in the same way all over you app.
|
39
|
+
- __LinksHelper__
|
40
|
+
Keep your links for basic actions consistent.
|
41
|
+
- __Bootstrap__
|
42
|
+
For bootstrap-formatted flash messages.
|
43
|
+
- __Forms__
|
44
|
+
`hidden_params_fields` to bypass query params in GET-forms.
|
45
|
+
|
46
|
+
__[Helpers usage](#helpers)__
|
47
|
+
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
Add this line to your application's Gemfile:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
gem 'rails_stuff'
|
54
|
+
```
|
55
|
+
|
56
|
+
And then execute:
|
57
|
+
|
58
|
+
$ bundle
|
59
|
+
|
60
|
+
Or install it yourself as:
|
61
|
+
|
62
|
+
$ gem install rails_stuff
|
63
|
+
|
64
|
+
## Usage
|
65
|
+
|
66
|
+
All modules are lazy loaded, so it's ok to require whole gem at once.
|
67
|
+
There is railtie which will include some of modules into `ActiveRecord::Base`
|
68
|
+
and `ActionController::Base` by default. You can disable this behavior in
|
69
|
+
initializer:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
# Disable auto-setup:
|
73
|
+
RailsStuff.load_modules = []
|
74
|
+
|
75
|
+
# Enable particular modules:
|
76
|
+
RailsStuff.load_modules = %i(sort_scope statusable)
|
77
|
+
```
|
78
|
+
|
79
|
+
You can override base classes for controller/model with `.base_controller=`,
|
80
|
+
`.base_model=`.
|
81
|
+
|
82
|
+
Works only with ruby 2.0+, tested with Rails 4.2.
|
83
|
+
|
84
|
+
There can be lack of documentation in README. Please navigate to module and
|
85
|
+
check docs & code (press `t` on github) if you miss something.
|
86
|
+
|
87
|
+
### ResourcesController
|
88
|
+
|
89
|
+
Similar to [InheriteResource](https://github.com/josevalim/inherited_resources)
|
90
|
+
but much simpler. It adds implementations for basic actions and
|
91
|
+
accessors for collection and resource. There is no options for almost everything,
|
92
|
+
but it's easy to extend.
|
93
|
+
|
94
|
+
It's main purpose is to ged rid of `@user ||= User.find params[:id]`, and keep
|
95
|
+
controllers clean:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
class ApplicationController < ActionController::Base
|
99
|
+
extend RailsStuff::ResourcesController # when using without railtie
|
100
|
+
end
|
101
|
+
|
102
|
+
class UsersController < ApplicationController
|
103
|
+
resources_controller
|
104
|
+
permit_attrs :name, :email
|
105
|
+
end
|
106
|
+
|
107
|
+
class ProjectsController < ApplicationController
|
108
|
+
resources_controller sti: true,
|
109
|
+
after_save_action: :index,
|
110
|
+
source_relation: -> { user.projects }
|
111
|
+
resource_helper :user
|
112
|
+
permit_attrs :name
|
113
|
+
permit_attrs_for Project::External, :company
|
114
|
+
permit_attrs_for Project::Internal, :department
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
There is built-in support for pagination with Kaminari.
|
119
|
+
It's enabled automatically if `kaminari` gem is loaded.
|
120
|
+
|
121
|
+
Currently depends on `gem 'responders', '> 2.0'`.
|
122
|
+
|
123
|
+
### SortScope
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
# in controller
|
127
|
+
extend RailsStuff::SortScope # when using without railtie
|
128
|
+
|
129
|
+
sort_scope by: [:name, :created_at, :balance], default: [:name]
|
130
|
+
|
131
|
+
# this scope will accept
|
132
|
+
# - `sort=name`
|
133
|
+
# - `sort=name&sort_desc=true`
|
134
|
+
# - `sort[name]&sort[created_at]`
|
135
|
+
# - `sort[name]&sort[created_at]=desc
|
136
|
+
```
|
137
|
+
|
138
|
+
Requires `gem 'has_scope'`.
|
139
|
+
|
140
|
+
### NullifyBlankAttrs
|
141
|
+
|
142
|
+
Defines proxies for writers to replace empty values with `nil`.
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
# in model
|
146
|
+
extend RailsStuff::NullifyBlankAttrs # when using without railtie
|
147
|
+
|
148
|
+
nullify_blank_attrs :email, :title
|
149
|
+
```
|
150
|
+
|
151
|
+
### RandomUniqAttr
|
152
|
+
|
153
|
+
Uses database's UNIQUE constraints and transactions to generate uniq random values.
|
154
|
+
You need to make field nullable and add unique index on it.
|
155
|
+
The way it works:
|
156
|
+
|
157
|
+
- Instance is saved as usual
|
158
|
+
- If random fields are not empty, it does nothing
|
159
|
+
- Generates random value and tries to update instance
|
160
|
+
- If `RecordNotUnique` is occurred, it keeps trying to generate new values.
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
# in model
|
164
|
+
extend RailsStuff::RandomUniqAttr # when using without railtie
|
165
|
+
|
166
|
+
# Uses DEFAULT_GENERATOR which is SecureRandom(32)
|
167
|
+
random_uniq_attr :token
|
168
|
+
|
169
|
+
# Uses custom generator, which takes template from settings
|
170
|
+
random_uniq_attr(:code) do |instance|
|
171
|
+
MyGenerator.generate(instance.parent.code_template)
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
### Statusable
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
class User < ActiveRecord::Base
|
179
|
+
extend RailsStuff::RandomUniqAttr # when using without railtie
|
180
|
+
|
181
|
+
STATUSES = %i(confirmed banned)
|
182
|
+
has_status_field # uses #status field and STATUSES as values
|
183
|
+
|
184
|
+
# Or pass everything explicitly
|
185
|
+
has_status_field :subscription_status, %i(expired active), prefix: :subs_
|
186
|
+
# :prefix is used for methods that are build
|
187
|
+
end
|
188
|
+
|
189
|
+
user = User.first
|
190
|
+
|
191
|
+
# And you get:
|
192
|
+
# Scopes
|
193
|
+
User.confirmed.subs_active
|
194
|
+
User.not_banned.not_subs_expired
|
195
|
+
# Useful with has_scope
|
196
|
+
User.with_status(param[:status]).with_subscription_status(params[:subs_status])
|
197
|
+
|
198
|
+
# Translation & select helpers (requires activemodel_translation gem)
|
199
|
+
User.status_name(:active)
|
200
|
+
user.subscription_status_name # translates current status
|
201
|
+
User.status_select_options
|
202
|
+
User.subscription_status_select_options except: [:expired]
|
203
|
+
|
204
|
+
# Accessors
|
205
|
+
user.status = 'confirmed' or user.confirmed!
|
206
|
+
user.status_sym # :confirmed
|
207
|
+
user.subscription_status = :active or user.subs_active!
|
208
|
+
user.subscription_status # 'active'
|
209
|
+
user.banned? or user.subs_expired?
|
210
|
+
|
211
|
+
# ... and inclusion validator
|
212
|
+
```
|
213
|
+
|
214
|
+
### TypesTracker
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
class Project
|
218
|
+
extend RailsStuff::TypesTracker
|
219
|
+
# you can also override default list class (Array) with:
|
220
|
+
self.types_list_class = FilterableArray
|
221
|
+
# smth ...
|
222
|
+
|
223
|
+
# If you want to show all available descendants in development
|
224
|
+
# (ex. in dropdown/select), you definitely want this:
|
225
|
+
eager_load_types! # will load all files in app/models/project
|
226
|
+
# or pass folder explicitly:
|
227
|
+
eager_load_types!('lib/path/to/projects')
|
228
|
+
end
|
229
|
+
|
230
|
+
class Project::Big < Project
|
231
|
+
unregister_type # remove this class from types_list
|
232
|
+
|
233
|
+
# Or add options for custom list.
|
234
|
+
# Following will call types_list.add Project::Big, :arg, option: :example
|
235
|
+
register_type :arg, option: :example
|
236
|
+
end
|
237
|
+
|
238
|
+
class Project::Internal < Project::Big; end
|
239
|
+
class Project::External < Project::Big; end
|
240
|
+
class Project::Small < Project; end
|
241
|
+
|
242
|
+
Project.types_list # [Internal, External, Small]
|
243
|
+
```
|
244
|
+
|
245
|
+
### ParamsParser
|
246
|
+
|
247
|
+
Have you missed type-casting outside of `ActiveRecord::Base`? Here is it:
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
ParamsParser.parse_int(params[:field]) # _float, _string, _boolean, _datetime
|
251
|
+
ParamsParser.parse_int_array(params[:field_with_array])
|
252
|
+
ParamsParser.parse_json(json_string)
|
253
|
+
|
254
|
+
# There is basic .parse method. It runs block only if input is not nil
|
255
|
+
# and reraises all errors with ParamsParser::Error
|
256
|
+
ParamsParser.parse(input) { |x| this_can_raise_exception(x) }
|
257
|
+
|
258
|
+
# So you can handle all errors in controller with
|
259
|
+
rescue_from ParamsParser::Error, with: -> { head :bad_request }
|
260
|
+
```
|
261
|
+
|
262
|
+
### RedisStorage
|
263
|
+
|
264
|
+
Simple module to organize data in key-value store. Uses `ConnectionPool`
|
265
|
+
and works good in multi-threaded environments.
|
266
|
+
Best used with [PooledRedis](https://github.com/printercu/pooled_redis).
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
class Model
|
270
|
+
extend RailsStuff::SedisStorage
|
271
|
+
|
272
|
+
self.redis_prefix = :other_prefix # default to underscored model name
|
273
|
+
|
274
|
+
# override .dump, .load for custom serialization. Default to Marshal
|
275
|
+
|
276
|
+
# It uses Rails.redis_pool by default. Override it with
|
277
|
+
self.redis_pool = ConnectionPool.new { Redis.new(my_options) }
|
278
|
+
end
|
279
|
+
|
280
|
+
Model.get('key') # GET other_prefix:key
|
281
|
+
Model.get(['composite', 'key']) # GET other_prefix:composite:key
|
282
|
+
# .delete works the same way
|
283
|
+
|
284
|
+
Model.set('key', data) or Model.set(['composite', 'key'], data)
|
285
|
+
next_id = Model.set(nil, data) # auto-incremented per-model id
|
286
|
+
next_id = Model.set(['composite', nil], data) # auto-incremented per-scope id
|
287
|
+
Model.set(id, data, ex: 10) # pass options for redis
|
288
|
+
# Or set per-model options for all .set requests:
|
289
|
+
Model.redis_set_options = {ex: 10}
|
290
|
+
|
291
|
+
# generate ids:
|
292
|
+
Model.next_id or Model.next_id(['composite', 'scope'])
|
293
|
+
Model.reset_id_seq or Model.reset_id_seq(['composite', 'scope'])
|
294
|
+
```
|
295
|
+
|
296
|
+
### Helpers
|
297
|
+
|
298
|
+
Include helper module into `ApplicationHelper`.
|
299
|
+
Or use `RailsStuff::Helpers::All` to include all helpers together.
|
300
|
+
|
301
|
+
Add this sections to your translations ymls:
|
302
|
+
|
303
|
+
```yml
|
304
|
+
helpers:
|
305
|
+
actions:
|
306
|
+
edit: Change
|
307
|
+
delete: Forget about it
|
308
|
+
confirm: Really?
|
309
|
+
confirmations:
|
310
|
+
delete: Will you miss it?
|
311
|
+
```
|
312
|
+
|
313
|
+
And use helpers:
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
translate_action(:edit) or translate_action(:delete)
|
317
|
+
link_to 'x', url_for(resource),
|
318
|
+
method: :delete, data: {confirm: translate_confirmation(:delete)}
|
319
|
+
translate_confirmation(:purge_all) # Fallback to default: 'Really?'
|
320
|
+
|
321
|
+
# There are helpers for basic links, take a look on helpers/links.rb to know
|
322
|
+
# how to tune it:
|
323
|
+
link_to_edit or link_to_edit('url') or link_to_edit([:scope, resource])
|
324
|
+
link_to_destroy or link_to_destroy('url') or link_to_destroy([:scope, resource])
|
325
|
+
```
|
326
|
+
|
327
|
+
Translation helpers are cached, so there is no need to cache it by yourself in
|
328
|
+
template if you want to decrease computations. And be aware of it if you
|
329
|
+
switch locales while rendering single view.
|
330
|
+
|
331
|
+
## Development
|
332
|
+
|
333
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
334
|
+
Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
335
|
+
|
336
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
337
|
+
To release a new version, update the version number in `version.rb`,
|
338
|
+
and then run `bundle exec rake release` to create a git tag for the version,
|
339
|
+
push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
340
|
+
|
341
|
+
## Contributing
|
342
|
+
|
343
|
+
1. Fork it ( https://github.com/printercu/rails_stuff/fork )
|
344
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
345
|
+
3. Implement your feature:
|
346
|
+
- Write failing spec for your feature
|
347
|
+
- Write code
|
348
|
+
- Commit your changes (`git commit -am 'Add some feature'`)
|
349
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
350
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task default: :spec
|
7
|
+
|
8
|
+
require 'sdoc'
|
9
|
+
RDoc::Task.new(:doc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'doc'
|
11
|
+
|
12
|
+
rdoc.title = 'RailsStuff'
|
13
|
+
|
14
|
+
rdoc.options << '--markup' << 'markdown'
|
15
|
+
rdoc.options << '-e' << 'UTF-8'
|
16
|
+
rdoc.options << '--format' << 'sdoc'
|
17
|
+
rdoc.options << '--template' << 'rails'
|
18
|
+
rdoc.options << '--all'
|
19
|
+
|
20
|
+
rdoc.rdoc_files.include('README.md')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
pattern=$(echo -n '\.rb
|
4
|
+
\.gemspec
|
5
|
+
\.jbuilder
|
6
|
+
\.rake
|
7
|
+
config\.ru
|
8
|
+
Gemfile
|
9
|
+
Rakefile' | tr "\\n" '|')
|
10
|
+
|
11
|
+
files=`git diff --cached --name-status | grep -E "^[AM].*($pattern)$" | cut -f2-`
|
12
|
+
if [ -n "$files" ]; then
|
13
|
+
bundle exec rubocop $files --force-exclusion
|
14
|
+
fi
|
data/bin/setup
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
class << Net::HTTP
|
4
|
+
# Redefines `.new` to set debug device for all new instances.
|
5
|
+
def debug!(out = $stderr)
|
6
|
+
return if respond_to?(:__new__)
|
7
|
+
class << self
|
8
|
+
alias_method :__new__, :new
|
9
|
+
end
|
10
|
+
|
11
|
+
define_singleton_method :new do |*args, &blk|
|
12
|
+
instance = __new__(*args, &blk)
|
13
|
+
instance.set_debug_output(out)
|
14
|
+
instance
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Restores original `.new`.
|
19
|
+
def disable_debug!
|
20
|
+
return unless respond_to?(:__new__)
|
21
|
+
class << self
|
22
|
+
alias_method :new, :__new__
|
23
|
+
remove_method :__new__
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
require 'active_support/core_ext/hash/transform_values'
|
3
|
+
|
4
|
+
module RailsStuff
|
5
|
+
module Helpers
|
6
|
+
module Bootstrap
|
7
|
+
BOOTSTRAP_FLASH_TYPE = {
|
8
|
+
success: 'alert-success',
|
9
|
+
error: 'alert-danger',
|
10
|
+
alert: 'alert-warning',
|
11
|
+
notice: 'alert-info',
|
12
|
+
}.stringify_keys.freeze
|
13
|
+
|
14
|
+
def flash_messages
|
15
|
+
flash.map do |type, message|
|
16
|
+
content_tag :div, class: [:alert, BOOTSTRAP_FLASH_TYPE[type] || type] do
|
17
|
+
content_tag(:button, '×'.html_safe, class: :close, data: {dismiss: :alert}) +
|
18
|
+
simple_format(message)
|
19
|
+
end
|
20
|
+
end.join.html_safe
|
21
|
+
end
|
22
|
+
|
23
|
+
ICONS = {
|
24
|
+
destroy: %(<span class='glyphicon icon-destroy'></span>),
|
25
|
+
edit: %(<span class='glyphicon icon-edit'></span>),
|
26
|
+
new: %(<span class='glyphicon icon-add'></span>),
|
27
|
+
}.tap { |x| x.transform_values!(&:html_safe) if ''.respond_to?(:html_safe) }
|
28
|
+
|
29
|
+
def basic_link_icons
|
30
|
+
ICONS
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RailsStuff
|
2
|
+
module Helpers
|
3
|
+
module Forms
|
4
|
+
# Returns hidden field tags for requested fields when they are present in params.
|
5
|
+
# Usually used to bypass params in GET-forms.
|
6
|
+
def hidden_params_fields(*fields)
|
7
|
+
inputs = fields.flat_map do |field|
|
8
|
+
next unless params.key?(field)
|
9
|
+
val = params[field]
|
10
|
+
if val.is_a?(Array)
|
11
|
+
name = "#{field}[]"
|
12
|
+
val.map { |str| [name, str] }
|
13
|
+
else
|
14
|
+
[[field, val]]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
safe_join inputs.map { |(name, val)| hidden_field_tag name, val if name }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module RailsStuff
|
2
|
+
module Helpers
|
3
|
+
# Link helpers for basic actions.
|
4
|
+
module Links
|
5
|
+
ICONS = {
|
6
|
+
destroy: -> { translate_action(:destroy) },
|
7
|
+
edit: -> { translate_action(:edit) },
|
8
|
+
new: -> { translate_action(:new) },
|
9
|
+
}
|
10
|
+
|
11
|
+
def basic_link_icons
|
12
|
+
ICONS
|
13
|
+
end
|
14
|
+
|
15
|
+
def basic_link_icon(action)
|
16
|
+
val = basic_link_icons[action]
|
17
|
+
val.is_a?(Proc) ? instance_exec(&val) : val
|
18
|
+
end
|
19
|
+
|
20
|
+
def link_to_destroy(url, **options)
|
21
|
+
link_to basic_link_icon(:destroy), url, {
|
22
|
+
title: translate_action(:delete),
|
23
|
+
method: :delete,
|
24
|
+
data: {confirm: translate_confirmation(:delete)},
|
25
|
+
}.merge!(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def link_to_edit(url = nil, **options)
|
29
|
+
link_to basic_link_icon(:edit), (url || url_for(action: :edit)),
|
30
|
+
{title: translate_action(:edit)}.merge!(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def link_to_new(url = nil, **options)
|
34
|
+
link_to basic_link_icon(:new), (url || url_for(action: :new)), options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|