rails_stuff 0.6.0.rc1 → 0.6.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 56cd33390b1d0c5cce251aba39698ef115de3c6c
4
- data.tar.gz: 8e7032d8717fae0d1fa44c5f6ea308a150a2e73f
3
+ metadata.gz: 8d4bbc5a4f7134f1f2d424f3657a959fadc156f7
4
+ data.tar.gz: 02c9c3a91387da5b74b651db8170485e2e3f32b9
5
5
  SHA512:
6
- metadata.gz: 9abf798f564088d2bb174e955efdf0cce9b47528b8f0dac7095516a35fcd11752772cd3d691266235698fd5281622db8ce9f5f9d32a3d66a75c8efde2c5da87c
7
- data.tar.gz: 3dbbc5a6052014726fba018811d5615d9e9527e913fb14a492d615527f4bbe6bb5312815d55549e613e38c6103728447e7b558c8f1bbf630c18d65eb897bfc13
6
+ metadata.gz: 546ed27d8f2dfae81802312f33ffc53783e428eab45355334460e9efeb7e75e55b6a59c492290ee1519f535c747ac965647cb118c5c093e26f5b3f9f4eb80e42
7
+ data.tar.gz: 809b2cff8da75c31810e4f1d5bd78fa4e344d1931d898d7627bccf51d5d48a0ae82cdf7508390138e87c15e5b5b0978c55ad56025b10fccfdd4997c55e1bbcb9
@@ -4,29 +4,53 @@ AllCops:
4
4
  - tmp/**/*
5
5
  Rails: {Enabled: true}
6
6
 
7
- Style/Alias: {Enabled: false}
8
- Style/AlignParameters:
7
+ Layout/AlignParameters:
9
8
  # Disable, till rubocop supports combination of styles.
10
9
  # Use one of this styles where appropriate, keep it clean, compact and readable.
11
10
  Enabled: false
12
11
  # EnforcedStyle:
13
12
  # - with_first_parameter
14
13
  # - with_fixed_indentation
15
- Style/ClosingParenthesisIndentation: {Enabled: false}
14
+
15
+ # Breaks
16
+ #
17
+ # I18n.t(key,
18
+ # param: val,
19
+ # # ...
20
+ # )
21
+ Layout/ClosingParenthesisIndentation: {Enabled: false}
22
+ Layout/DotPosition: {EnforcedStyle: trailing}
23
+ # Same as Layout/ClosingParenthesisIndentation
24
+ Layout/MultilineMethodCallBraceLayout: {Enabled: false}
25
+ Layout/MultilineMethodCallIndentation: {EnforcedStyle: indented}
26
+ Layout/MultilineOperationIndentation: {EnforcedStyle: indented}
27
+ Layout/SpaceInsideHashLiteralBraces: {EnforcedStyle: no_space}
28
+
29
+ # Offences named scopes and `expect {}.to change {}`.
30
+ Lint/AmbiguousBlockAssociation: {Enabled: false}
31
+
32
+ # We use it in describe messages.
33
+ Lint/InterpolationCheck:
34
+ Exclude:
35
+ - spec/**/*
36
+
37
+ Naming/PredicateName: {Enabled: false}
38
+ Naming/VariableNumber: {EnforcedStyle: snake_case}
39
+
40
+ Style/Alias: {Enabled: false}
16
41
  Style/Documentation: {Enabled: false}
17
- Style/DotPosition: {EnforcedStyle: trailing}
18
42
  Style/IfUnlessModifier: {Enabled: false}
43
+ Style/GuardClause: {Enabled: false}
19
44
  Style/Lambda: {Enabled: false}
20
45
  Style/ModuleFunction: {Enabled: false}
21
- Style/MultilineMethodCallIndentation: {EnforcedStyle: indented}
22
- Style/MultilineOperationIndentation: {EnforcedStyle: indented}
23
46
  Style/NestedParenthesizedCalls: {Enabled: false}
24
- Style/PredicateName: {Enabled: false}
25
47
  Style/SignalException: {EnforcedStyle: only_raise}
26
- Style/SpaceInsideHashLiteralBraces: {EnforcedStyle: no_space}
27
48
  Style/TrailingCommaInArguments: {Enabled: false}
28
49
  Style/TrailingCommaInLiteral: {EnforcedStyleForMultiline: comma}
29
50
 
30
51
  Metrics/AbcSize: {Max: 21}
52
+ # Other metrics are just enough.
53
+ # This one offences all specs, routes and some initializers.
54
+ Metrics/BlockLength: {Enabled: false}
31
55
  Metrics/LineLength: {Max: 100}
32
56
  Metrics/MethodLength: {Max: 30}
@@ -4,7 +4,8 @@ rvm:
4
4
  - 2.2.3
5
5
  gemfile:
6
6
  - gemfiles/rails_4.gemfile
7
- - gemfiles/rails_5.gemfile
7
+ - gemfiles/rails_5_0.gemfile
8
+ - gemfiles/rails_5_1.gemfile
8
9
  services:
9
10
  - redis
10
11
  notifications:
data/Appraisals CHANGED
@@ -4,9 +4,16 @@ appraise 'rails-4' do
4
4
  end
5
5
  end
6
6
 
7
- appraise 'rails-5' do
7
+ appraise 'rails-5_0' do
8
8
  group :development do
9
- gem 'rails', '~> 5.0'
9
+ gem 'rails', '~> 5.0.0'
10
+ gem 'rails-controller-testing', '~> 0.1.1'
11
+ end
12
+ end
13
+
14
+ appraise 'rails-5_1' do
15
+ group :development do
16
+ gem 'rails', '~> 5.1'
10
17
  gem 'rails-controller-testing', '~> 0.1.1'
11
18
  end
12
19
  end
@@ -1,5 +1,22 @@
1
1
  ## Unreleased
2
2
 
3
+ ### Controllers
4
+
5
+ - `resource_params` returns permited hash when resource key is not present in `params`.
6
+ - `use_resource_class_for_invalid_type` option for STI helpers,
7
+ and `RailsStuff::ResourcesController::StiHelpers::InvalidType` error instead of
8
+ `ActiveRecord::NotFound` for invalid type.
9
+
10
+ ### Models
11
+
12
+ - `TransformAttrs` in favour of `NullifyBlankAttrs` (deprecated).
13
+
14
+ ### Misc
15
+
16
+ - Parse BigDecimals with ParamsParser.
17
+ - ParamsParser parses empty strings to `nil` (except `parse_string`).
18
+
19
+
3
20
  ## 0.6.0.rc1
4
21
 
5
22
  ### Controllers
data/Gemfile CHANGED
@@ -2,26 +2,26 @@ source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
4
  group :development do
5
- gem 'rails'
6
5
  gem 'appraisal', '~> 2.1.0'
6
+ gem 'rails'
7
7
 
8
- gem 'sdoc', '~> 0.4.1'
9
8
  gem 'pry', '~> 0.10.1'
10
9
  gem 'pry-byebug', '~> 3.2.0'
10
+ gem 'sdoc', '~> 0.4.1'
11
11
 
12
- gem 'sqlite3', '~> 1.3.10'
13
- gem 'database_cleaner', '~> 1.5.0'
14
- gem 'pooled_redis', '~> 0.2.1'
15
12
  gem 'activemodel_translation', '~> 0.1.0'
13
+ gem 'database_cleaner', '~> 1.5.0'
16
14
  gem 'has_scope', '~> 0.7.0'
17
- gem 'responders', '~> 2.1.0'
18
- gem 'kaminari', '~> 0.16.3'
19
15
  gem 'hashie', '~> 3.4.0'
16
+ gem 'kaminari', '~> 0.16.3'
17
+ gem 'pooled_redis', '~> 0.2.1'
18
+ gem 'responders', '~> 2.1'
19
+ gem 'sqlite3', '~> 1.3.10'
20
20
 
21
- gem 'rspec-rails', '~> 3.5.2'
22
21
  gem 'rspec-its', '~> 1.2.0'
22
+ gem 'rspec-rails', '~> 3.5'
23
23
 
24
- gem 'rubocop', '~> 0.37.2'
24
+ gem 'rubocop', '~> 0.51.0'
25
25
 
26
26
  gem 'coveralls', '~> 0.8.2', require: false
27
27
  end
data/README.md CHANGED
@@ -3,7 +3,15 @@
3
3
  [![Code Climate](https://codeclimate.com/github/printercu/rails_stuff/badges/gpa.svg)](https://codeclimate.com/github/printercu/rails_stuff)
4
4
  [![Build Status](https://travis-ci.org/printercu/rails_stuff.svg)](https://travis-ci.org/printercu/rails_stuff)
5
5
 
6
- Collection of useful modules for Rails.
6
+ Collection of useful modules for ruby projects to provide great DRY, TDD experience.
7
+ While some of them are Rails-specific, most will work in any environment
8
+ ignoring gem's name.
9
+
10
+ All modules are lazy loaded, so it's ok to require whole gem at once.
11
+ Some of them are activated by default for best experience,
12
+ but this can be configured or turned off (see [usage](#usage)).
13
+
14
+ Works with ruby 2.0+, Rails 4.2+, 5+.
7
15
 
8
16
  #### Controllers:
9
17
 
@@ -89,7 +97,6 @@ Or install it yourself as:
89
97
 
90
98
  ## Usage
91
99
 
92
- All modules are lazy loaded, so it's ok to require whole gem at once.
93
100
  There is railtie which will include some of modules into `ActiveRecord::Base`
94
101
  and `ActionController::Base` by default. You can disable this behavior in
95
102
  initializer:
@@ -105,8 +112,6 @@ RailsStuff.load_modules = %i(sort_scope statusable)
105
112
  You can override base classes for controller/model with `.base_controller=`,
106
113
  `.base_model=`.
107
114
 
108
- Works only with ruby 2.0+, tested with Rails 4.2.
109
-
110
115
  There can be lack of documentation in README. Please navigate to module and
111
116
  check docs & code (press `t` on github) if you miss something.
112
117
 
@@ -305,7 +310,7 @@ Project.internal or Project.big
305
310
  Have you missed type-casting outside of `ActiveRecord::Base`? Here is it:
306
311
 
307
312
  ```ruby
308
- ParamsParser.parse_int(params[:field]) # _float, _string, _boolean, _datetime
313
+ ParamsParser.parse_int(params[:field]) # _float, _decimal, _string, _boolean, _datetime
309
314
  ParamsParser.parse_int_array(params[:field_with_array])
310
315
  ParamsParser.parse_json(json_string)
311
316
 
@@ -13,10 +13,10 @@ group :development do
13
13
  gem "pooled_redis", "~> 0.2.1"
14
14
  gem "activemodel_translation", "~> 0.1.0"
15
15
  gem "has_scope", "~> 0.7.0"
16
- gem "responders", "~> 2.1.0"
16
+ gem "responders", "~> 2.1"
17
17
  gem "kaminari", "~> 0.16.3"
18
18
  gem "hashie", "~> 3.4.0"
19
- gem "rspec-rails", "~> 3.5.2"
19
+ gem "rspec-rails", "~> 3.5"
20
20
  gem "rspec-its", "~> 1.2.0"
21
21
  gem "rubocop", "~> 0.37.2"
22
22
  gem "coveralls", "~> 0.8.2", :require => false
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  group :development do
6
- gem "rails", "~> 5.0"
6
+ gem "rails", "~> 5.0.0"
7
7
  gem "appraisal", "~> 2.1.0"
8
8
  gem "sdoc", "~> 0.4.1"
9
9
  gem "pry", "~> 0.10.1"
@@ -13,10 +13,10 @@ group :development do
13
13
  gem "pooled_redis", "~> 0.2.1"
14
14
  gem "activemodel_translation", "~> 0.1.0"
15
15
  gem "has_scope", "~> 0.7.0"
16
- gem "responders", "~> 2.1.0"
16
+ gem "responders", "~> 2.1"
17
17
  gem "kaminari", "~> 0.16.3"
18
18
  gem "hashie", "~> 3.4.0"
19
- gem "rspec-rails", "~> 3.5.2"
19
+ gem "rspec-rails", "~> 3.5"
20
20
  gem "rspec-its", "~> 1.2.0"
21
21
  gem "rubocop", "~> 0.37.2"
22
22
  gem "coveralls", "~> 0.8.2", :require => false
@@ -0,0 +1,26 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ group :development do
6
+ gem "rails", "~> 5.1"
7
+ gem "appraisal", "~> 2.1.0"
8
+ gem "sdoc", "~> 0.4.1"
9
+ gem "pry", "~> 0.10.1"
10
+ gem "pry-byebug", "~> 3.2.0"
11
+ gem "sqlite3", "~> 1.3.10"
12
+ gem "database_cleaner", "~> 1.5.0"
13
+ gem "pooled_redis", "~> 0.2.1"
14
+ gem "activemodel_translation", "~> 0.1.0"
15
+ gem "has_scope", "~> 0.7.0"
16
+ gem "responders", "~> 2.1"
17
+ gem "kaminari", "~> 0.16.3"
18
+ gem "hashie", "~> 3.4.0"
19
+ gem "rspec-rails", "~> 3.5"
20
+ gem "rspec-its", "~> 1.2.0"
21
+ gem "rubocop", "~> 0.37.2"
22
+ gem "coveralls", "~> 0.8.2", :require => false
23
+ gem "rails-controller-testing", "~> 0.1.1"
24
+ end
25
+
26
+ gemspec :path => "../"
@@ -19,6 +19,7 @@ module RailsStuff
19
19
  autoload :SortScope
20
20
  autoload :Statusable
21
21
  autoload :TestHelpers, 'rails_stuff/test_helpers'
22
+ autoload :TransformAttrs
22
23
  autoload :TypesTracker
23
24
 
24
25
  module_function
@@ -30,6 +31,13 @@ module RailsStuff
30
31
  def rails4?
31
32
  rails_version::MAJOR == 4
32
33
  end
34
+
35
+ def deprecation_07
36
+ @deprecation ||= begin
37
+ require 'active_support/deprecation'
38
+ ActiveSupport::Deprecation.new('0.7', 'RailsStuff')
39
+ end
40
+ end
33
41
  end
34
42
 
35
43
  require 'rails_stuff/engine' if defined?(Rails::Engine)
@@ -7,6 +7,7 @@ module RailsStuff
7
7
  nullify_blank_attrs: :model,
8
8
  random_uniq_attr: :model,
9
9
  statusable: :model,
10
+ transform_attrs: :model,
10
11
  resources_controller: [
11
12
  -> { defined?(::Responders) && :controller },
12
13
  -> { ResourcesController.use_kaminari! if defined?(::Kaminari) },
@@ -59,5 +60,9 @@ module RailsStuff
59
60
  generators do
60
61
  require 'rails_stuff/generators/concern/concern_generator'
61
62
  end
63
+
64
+ config.action_dispatch.rescue_responses.merge!(
65
+ 'RailsStuff::ResourcesController::StiHelpers::InvalidType' => :unprocessable_entity,
66
+ )
62
67
  end
63
68
  end
@@ -11,13 +11,16 @@ module RailsStuff
11
11
  notice: 'alert-info',
12
12
  }.stringify_keys.freeze
13
13
 
14
+ CROSS = '×'.html_safe.freeze # rubocop:disable Rails/OutputSafety
15
+
14
16
  def flash_messages
15
- flash.map do |type, message|
17
+ messages = flash.map do |type, message|
16
18
  content_tag :div, class: [:alert, BOOTSTRAP_FLASH_TYPE[type] || type] do
17
- content_tag(:button, '×'.html_safe, class: :close, data: {dismiss: :alert}) +
19
+ content_tag(:button, cross, class: :close, data: {dismiss: :alert}) +
18
20
  simple_format(message)
19
21
  end
20
- end.join.html_safe
22
+ end
23
+ safe_join(messages)
21
24
  end
22
25
 
23
26
  ICONS = {
@@ -8,6 +8,7 @@ module RailsStuff
8
8
  # # ...
9
9
  module NullifyBlankAttrs
10
10
  def nullify_blank_attrs(*attrs)
11
+ RailsStuff.deprecation_07.warn('Use transform_attrs *attrs, with: :nullify')
11
12
  nullify_blank_attrs_methods.class_eval do
12
13
  attrs.each do |attr|
13
14
  define_method("#{attr}=") { |val| super(val.presence) }
@@ -44,16 +44,24 @@ module RailsStuff
44
44
  extend self
45
45
 
46
46
  # Parses value with specified block. Reraises occured error with Error.
47
- def parse(val)
48
- yield(val) unless val.nil?
49
- rescue => e
47
+ def parse(val, *args, &block)
48
+ parse_not_blank(val, *args, &block)
49
+ rescue => e # rubocop:disable Lint/RescueWithoutErrorClass
50
50
  raise Error.new(e.message, val), nil, e.backtrace
51
51
  end
52
52
 
53
53
  # Parses each value in array with specified block.
54
54
  # Returns `nil` if `val` is not an array.
55
- def parse_array(val)
56
- parse(val) { val.map { |x| yield x unless x.nil? } } if val.is_a?(Array)
55
+ def parse_array(array, *args, &block)
56
+ return unless array.is_a?(Array)
57
+ parse(array) { array.map { |val| parse_not_blank(val, *args, &block) } }
58
+ end
59
+
60
+ # Parses value with given block only when it is not nil.
61
+ # Empty string is converted to nil. Pass `allow_blank: true` to return it as is.
62
+ def parse_not_blank(val, allow_blank: false)
63
+ return if val.nil? || !allow_blank && val.is_a?(String) && val.blank?
64
+ yield(val)
57
65
  end
58
66
 
59
67
  # :method: parse_int
@@ -76,19 +84,9 @@ module RailsStuff
76
84
  #
77
85
  # Parses array of floats. Returns `nil` if `val` is not an array.
78
86
 
79
- # :method: parse_string
80
- # :call-seq: parse_string(val)
81
- #
82
- # Parse string value.
83
-
84
- # :method: parse_string_array
85
- # :call-seq: parse_string_array(val)
86
- #
87
- # Parses array of strings. Returns `nil` if `val` is not an array.
88
-
89
87
  # Parsers for generic types, which are implemented with #to_i, #to_f & #to_s
90
88
  # methods.
91
- %w(string int float).each do |type|
89
+ %w[int float].each do |type|
92
90
  block = :"to_#{type[0]}".to_proc
93
91
 
94
92
  define_method "parse_#{type}" do |val|
@@ -100,6 +98,26 @@ module RailsStuff
100
98
  end
101
99
  end
102
100
 
101
+ # Parse string value.
102
+ def parse_string(val)
103
+ parse(val, allow_blank: true, &:to_s)
104
+ end
105
+
106
+ # Parses array of strings. Returns `nil` if `val` is not an array.
107
+ def parse_string_array(val)
108
+ parse_array(val, allow_blank: true, &:to_s)
109
+ end
110
+
111
+ # Parse decimal value.
112
+ def parse_decimal(val)
113
+ parse(val) { |x| BigDecimal.new(x) }
114
+ end
115
+
116
+ # Parses array of decimals. Returns `nil` if `val` is not an array.
117
+ def parse_decimal_array(val)
118
+ parse_array(val) { |x| BigDecimal.new(x) }
119
+ end
120
+
103
121
  # Parse boolean using ActiveResord's parser.
104
122
  def parse_boolean(val)
105
123
  parse(val) do
@@ -125,7 +143,7 @@ module RailsStuff
125
143
 
126
144
  # Parse JSON string.
127
145
  def parse_json(val)
128
- parse(val) { JSON.parse(val) if val.present? }
146
+ parse(val) { JSON.parse(val) }
129
147
  end
130
148
  end
131
149
  end
@@ -40,7 +40,8 @@ module RailsStuff
40
40
  begin
41
41
  raise 'Available only for persisted record' unless persisted?
42
42
  transaction(requires_new: true) do
43
- update_column field, self.class.send(generate_method, self)
43
+ new_value = self.class.send(generate_method, self)
44
+ update_column field, new_value # rubocop:disable Rails/SkipsModelValidations
44
45
  end
45
46
  rescue ActiveRecord::RecordNotUnique
46
47
  attempt += 1
@@ -43,7 +43,7 @@ module RailsStuff
43
43
  # Set redis_set_options.
44
44
 
45
45
  # Setters that overrides methods, so new values are inherited without recursive `super`.
46
- [:redis_pool, :redis_set_options].each do |name|
46
+ %i[redis_pool redis_set_options].each do |name|
47
47
  define_method "#{name}=" do |val|
48
48
  singleton_class.class_eval do
49
49
  remove_possible_method(name)
@@ -119,7 +119,7 @@ module RailsStuff
119
119
  def resource_params
120
120
  @_resource_params ||= begin
121
121
  key = self.class.resource_param_name
122
- params.permit(key => permitted_attrs)[key] || params.class.new
122
+ params.permit(key => permitted_attrs)[key] || params.class.new.permit!
123
123
  end
124
124
  end
125
125
 
@@ -2,15 +2,6 @@ module RailsStuff
2
2
  module ResourcesController
3
3
  # Defines resource helper and finder method.
4
4
  module ResourceHelper
5
- class << self
6
- def deprecation
7
- @deprecation ||= begin
8
- require 'active_support/deprecation'
9
- ActiveSupport::Deprecation.new('0.7', 'RailsStuff')
10
- end
11
- end
12
- end
13
-
14
5
  # Defines protected helper method. Ex. for `:user`
15
6
  #
16
7
  # helper_method :user
@@ -26,7 +17,7 @@ module RailsStuff
26
17
  #
27
18
  # rubocop:disable CyclomaticComplexity, PerceivedComplexity, AbcSize
28
19
  def resource_helper(name, param: nil, source: nil, **options)
29
- ResourceHelper.deprecation.warn('use :source instead of :class') if options.key?(:class)
20
+ RailsStuff.deprecation_07.warn('use :source instead of :class') if options.key?(:class)
30
21
 
31
22
  param ||= name.to_s.foreign_key.to_sym
32
23
  define_method("#{name}?") { params.key?(param) }
@@ -4,6 +4,8 @@ module RailsStuff
4
4
  module ResourcesController
5
5
  # Helper methods for controllers which works with STI models.
6
6
  module StiHelpers
7
+ class InvalidType < StandardError; end
8
+
7
9
  extend ActiveSupport::Concern
8
10
 
9
11
  module ClassMethods
@@ -12,15 +14,28 @@ module RailsStuff
12
14
  # By default it uses `.types_list` or `.descendants` to get list of
13
15
  # classes and indexes them by class names.
14
16
  def resource_class_by_type
15
- @resource_class_by_type ||= begin
17
+ @resource_class_by_type ||=
16
18
  if resource_class.respond_to?(:types_list)
17
19
  resource_class.types_list
18
20
  else
19
21
  resource_class.descendants
20
22
  end.index_by(&:name)
21
- end
22
23
  end
23
24
 
25
+ attr_writer :resource_class_by_type
26
+
27
+ def resource_class_for(name)
28
+ return resource_class unless name
29
+ resource_class_by_type[name] ||
30
+ if use_resource_class_for_invalid_type
31
+ resource_class
32
+ else
33
+ raise(InvalidType, "No type mapped for #{name.inspect}")
34
+ end
35
+ end
36
+
37
+ attr_accessor :use_resource_class_for_invalid_type
38
+
24
39
  # Class-level accessor to permitted attributes for specisic class.
25
40
  def permitted_attrs_for
26
41
  @permitted_attrs_for ||= Hash.new { |h, k| h[k] = [] }
@@ -41,15 +56,14 @@ module RailsStuff
41
56
  if params.key?(:id)
42
57
  resource.class
43
58
  else
44
- name = params.require(self.class.resource_param_name).
45
- permit(:type)[:type]
46
- self.class.resource_class_by_type[name] ||
47
- raise(ActiveRecord::RecordNotFound)
59
+ key = self.class.resource_param_name
60
+ name = params.permit(key => [:type])[key].try!(:[], :type)
61
+ self.class.resource_class_for(name)
48
62
  end
49
63
  end
50
64
 
51
65
  # Instantiates object using class_from_request.
52
- def build_resource
66
+ def build_resource(attrs = resource_params)
53
67
  @_resource = super.becomes!(class_from_request)
54
68
  end
55
69
 
@@ -11,7 +11,7 @@ module RailsStuff
11
11
  # Single endpoint for multiple seups. Use `:only` and `:except` options
12
12
  # to filter actions.
13
13
  def setup(only: nil, except: nil)
14
- items = instance_methods.map(&:to_s) - %w(setup)
14
+ items = instance_methods.map(&:to_s) - %w[setup]
15
15
  items -= Array.wrap(except).map(&:to_s) if except
16
16
  if only
17
17
  only = Array.wrap(only).map(&:to_s)
@@ -21,13 +21,13 @@ module RailsStuff
21
21
  items.uniq.each { |item| public_send(item) }
22
22
  end
23
23
 
24
- %w(
24
+ %w[
25
25
  concurrency
26
26
  groups/request
27
27
  groups/feature
28
28
  matchers/be_valid_js
29
29
  matchers/redirect_with_turbolinks
30
- ).each do |file|
30
+ ].each do |file|
31
31
  define_method(file) { require "rails_stuff/rspec_helpers/#{file}" }
32
32
  end
33
33
 
@@ -52,7 +52,7 @@ module RailsStuff
52
52
  config.database_cleaner_strategy = {feature: :truncation}
53
53
  config.database_cleaner_strategy.default = :transaction
54
54
  config.add_setting :database_cleaner_options
55
- config.database_cleaner_options = {truncation: {except: %w(spatial_ref_sys)}}
55
+ config.database_cleaner_options = {truncation: {except: %w[spatial_ref_sys]}}
56
56
  config.add_setting :database_cleaner_args
57
57
  config.database_cleaner_args = ->(ex) do
58
58
  strategy = ex.metadata[:concurrent] && :truncation
@@ -6,7 +6,7 @@ module RailsStuff
6
6
  extend self
7
7
 
8
8
  def setup(only: nil, except: nil)
9
- items = instance_methods.map(&:to_s) - %w(setup)
9
+ items = instance_methods.map(&:to_s) - %w[setup]
10
10
  items -= Array.wrap(except).map(&:to_s) if except
11
11
  if only
12
12
  only = Array.wrap(only).map(&:to_s)
@@ -16,10 +16,10 @@ module RailsStuff
16
16
  items.each { |item| public_send(item) }
17
17
  end
18
18
 
19
- %w(
19
+ %w[
20
20
  integration_session
21
21
  response
22
- ).each do |file|
22
+ ].each do |file|
23
23
  define_method(file.tr('/', '_')) { require "rails_stuff/test_helpers/#{file}" }
24
24
  end
25
25
 
@@ -0,0 +1,66 @@
1
+ module RailsStuff
2
+ # Generates writers which apply given transfromer for values.
3
+ module TransformAttrs
4
+ class << self
5
+ def transformations
6
+ @transformations ||= {}
7
+ end
8
+
9
+ # Register new transformation with given block.
10
+ #
11
+ # number_regexp = /\A\d+\z/
12
+ # RailsStuff::TransformAttrs.register :phone do |val|
13
+ # if val && val.to_s =~ number_regexp
14
+ # ActiveSupport::NumberHelper.number_to_phone(val)
15
+ # else
16
+ # val
17
+ # end
18
+ # end
19
+ def register(name, &block)
20
+ transformations[name] = block
21
+ end
22
+
23
+ def fetch_block(ids)
24
+ if ids.is_a?(Array)
25
+ blocks = ids.map { |x| transformations.fetch(x) }
26
+ ->(val) { blocks.reduce(val) { |x, block| block.call(x) } }
27
+ else
28
+ transformations.fetch(ids)
29
+ end
30
+ end
31
+ end
32
+
33
+ register(:strip) { |val| val && val.to_s.strip }
34
+ register(:nullify, &:presence)
35
+ register(:strip_and_nullify) { |val| val && val.to_s.strip.presence }
36
+
37
+ # Options:
38
+ #
39
+ # - `with` - use built-in transfromers from TransformAttrs.transformations.
40
+ # Add new transformations with TransformAttrs.register.
41
+ # - `new_module` - create new module for generated methods.
42
+ # Accepts `:prepend` or `:include`. By default it uses single module
43
+ # which is prepended.
44
+ #
45
+ # transform_attrs(:attr1, :attr2) { |x| x.to_s.downcase }
46
+ # transform_attrs(:attr3, &:presence) # to nullify blanks
47
+ # transform_attrs(:attr4, with: :strip)
48
+ # transform_attrs(:attr4, with: [:strip, :nullify])
49
+ # transform_attrs(:attr5, new_module: :include)
50
+ def transform_attrs(*attrs, with: nil, new_module: false, &block)
51
+ block ||= TransformAttrs.fetch_block(with)
52
+ mod = Module.new.tap { |x| public_send(new_module, x) } if new_module
53
+ mod ||= transform_attrs_methods
54
+ mod.class_eval do
55
+ attrs.each do |attr|
56
+ define_method("#{attr}=") { |val| super(block[val]) }
57
+ end
58
+ end
59
+ end
60
+
61
+ # Module to store generated methods, so they can be overriden in model.
62
+ def transform_attrs_methods
63
+ @transform_attrs_methods ||= Module.new.tap { |x| prepend x }
64
+ end
65
+ end
66
+ end
@@ -1,5 +1,4 @@
1
1
  require 'active_support/core_ext/class/attribute'
2
- require 'active_support/deprecation'
3
2
 
4
3
  module RailsStuff
5
4
  # Adds `types_list` method which tracks all descendants.
@@ -43,15 +42,6 @@ module RailsStuff
43
42
  types_list.delete self
44
43
  end
45
44
 
46
- # Shortcut to eager load all descendants.
47
- def eager_load_types!(dir = nil)
48
- RequireNested.require_nested(dir || 2) # skip 1 more because of deprecation
49
- end
50
-
51
- ActiveSupport::Deprecation.deprecate_methods self,
52
- deprecator: ActiveSupport::Deprecation.new('0.6', 'RailsStuff'),
53
- eager_load_types!: 'Use RequireNested.require_nested instead'
54
-
55
45
  # Tracks all descendants automatically.
56
46
  def inherited(base)
57
47
  super
@@ -7,7 +7,7 @@ module RailsStuff
7
7
  MAJOR = 0
8
8
  MINOR = 6
9
9
  TINY = 0
10
- PRE = 'rc1'.freeze
10
+ PRE = 'rc2'.freeze
11
11
 
12
12
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
13
13
 
@@ -1,4 +1,3 @@
1
- # coding: utf-8
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'rails_stuff/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_stuff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0.rc1
4
+ version: 0.6.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Melentiev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-04-13 00:00:00.000000000 Z
11
+ date: 2017-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,7 +80,8 @@ files:
80
80
  - bin/install_git_hooks
81
81
  - bin/setup
82
82
  - gemfiles/rails_4.gemfile
83
- - gemfiles/rails_5.gemfile
83
+ - gemfiles/rails_5_0.gemfile
84
+ - gemfiles/rails_5_1.gemfile
84
85
  - lib/assets/javascripts/rails_stuff/plugin_manager.coffee
85
86
  - lib/assets/stylesheets/rails_stuff/_media_queries.scss
86
87
  - lib/net/http/debug.rb
@@ -131,6 +132,7 @@ files:
131
132
  - lib/rails_stuff/test_helpers/concurrency.rb
132
133
  - lib/rails_stuff/test_helpers/integration_session.rb
133
134
  - lib/rails_stuff/test_helpers/response.rb
135
+ - lib/rails_stuff/transform_attrs.rb
134
136
  - lib/rails_stuff/types_tracker.rb
135
137
  - lib/rails_stuff/url_for_keeping_params.rb
136
138
  - lib/rails_stuff/version.rb