rails_stuff 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +24 -0
  5. data/.travis.yml +8 -0
  6. data/Gemfile +21 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +350 -0
  9. data/Rakefile +22 -0
  10. data/bin/console +7 -0
  11. data/bin/git-hooks/pre-commit +14 -0
  12. data/bin/install_git_hooks +8 -0
  13. data/bin/setup +8 -0
  14. data/lib/net/http/debug.rb +26 -0
  15. data/lib/rails_stuff/helpers/all.rb +12 -0
  16. data/lib/rails_stuff/helpers/bootstrap.rb +34 -0
  17. data/lib/rails_stuff/helpers/forms.rb +21 -0
  18. data/lib/rails_stuff/helpers/links.rb +38 -0
  19. data/lib/rails_stuff/helpers/resource_form.rb +49 -0
  20. data/lib/rails_stuff/helpers/text.rb +28 -0
  21. data/lib/rails_stuff/helpers/translation.rb +29 -0
  22. data/lib/rails_stuff/helpers.rb +14 -0
  23. data/lib/rails_stuff/nullify_blank_attrs.rb +23 -0
  24. data/lib/rails_stuff/params_parser.rb +121 -0
  25. data/lib/rails_stuff/railtie.rb +54 -0
  26. data/lib/rails_stuff/random_uniq_attr.rb +48 -0
  27. data/lib/rails_stuff/redis_storage.rb +119 -0
  28. data/lib/rails_stuff/resources_controller/actions.rb +31 -0
  29. data/lib/rails_stuff/resources_controller/basic_helpers.rb +161 -0
  30. data/lib/rails_stuff/resources_controller/resource_helper.rb +31 -0
  31. data/lib/rails_stuff/resources_controller/responder.rb +21 -0
  32. data/lib/rails_stuff/resources_controller/sti_helpers.rb +62 -0
  33. data/lib/rails_stuff/resources_controller.rb +42 -0
  34. data/lib/rails_stuff/sort_scope.rb +71 -0
  35. data/lib/rails_stuff/statusable.rb +130 -0
  36. data/lib/rails_stuff/test_helpers/rails.rb +6 -0
  37. data/lib/rails_stuff/test_helpers/response.rb +34 -0
  38. data/lib/rails_stuff/types_tracker.rb +50 -0
  39. data/lib/rails_stuff/version.rb +14 -0
  40. data/lib/rails_stuff.rb +19 -0
  41. data/rails_stuff.gemspec +25 -0
  42. 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
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
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
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.2.3
5
+ services:
6
+ - redis
7
+ notifications:
8
+ email: false
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,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'rails_stuff'
5
+
6
+ require 'pry'
7
+ Pry.start
@@ -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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ root = File.expand_path('../../', __FILE__)
4
+ hooks_dir = "#{root}/bin/git-hooks"
5
+
6
+ `ls -1 #{hooks_dir}`.each_line.map(&:strip).each do |file|
7
+ `ln -sf #{hooks_dir}/#{file} #{root}/.git/hooks/#{file}`
8
+ end
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+ bin/install_git_hooks
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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,12 @@
1
+ module RailsStuff
2
+ module Helpers
3
+ # Collection of all helper modules.
4
+ module All
5
+ include Translation
6
+ include Links
7
+ include Bootstrap
8
+ include Text
9
+ include Forms
10
+ end
11
+ end
12
+ 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, '&times;'.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