rearmed_rails 1.0.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +9 -0
- data/README.md +53 -78
- data/Rakefile +6 -7
- data/lib/generators/rearmed_rails/setup_generator.rb +1 -1
- data/lib/rearmed_rails.rb +42 -3
- data/lib/rearmed_rails/default_enabled_patches.hash +14 -28
- data/lib/rearmed_rails/exceptions.rb +11 -0
- data/lib/rearmed_rails/monkey_patches/{rails/active_record/base.rb → active_record.rb} +9 -10
- data/lib/rearmed_rails/monkey_patches/{rails/helpers.rb → helpers.rb} +5 -6
- data/lib/rearmed_rails/version.rb +1 -1
- data/test/{tc_rearmed.rb → rearmed_rails_test.rb} +31 -50
- metadata +9 -13
- data/lib/rearmed_rails/apply_patches.rb +0 -6
- data/lib/rearmed_rails/monkey_patches/minitest.rb +0 -35
- data/lib/rearmed_rails/monkey_patches/rails/active_record/batches.rb +0 -60
- data/lib/rearmed_rails/monkey_patches/rails/active_record/query_methods.rb +0 -110
- data/lib/rearmed_rails/monkey_patches/rails/v3.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 66bf5b7b6b2a6f6cfb1697c7a05edfc21dbb27d3f3bf38ffce810fc5f2ea2b21
|
4
|
+
data.tar.gz: 5f96d7b7582e51ec05b74da7f85bc18f1eebb5f07a73a09e2375dc4fec928570
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5153c73e99edd5ee9f010babbd24eed05640a6ba538fb3991083ec9130c6979c447763fd39cf289e9bdefedb1ae6a908aaada86f0beedecb15dc108d57fb513f
|
7
|
+
data.tar.gz: deca81c0c5c8f2c5226ab2f9d2d82abaebd8eea3d3cfac87fd8c85c54e6dee572db8f5b89073bb0e7e7877d805dea890cedb2e799b758647ba760778f6a28215
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
---------
|
3
3
|
|
4
|
+
- **2.0.0 - July 11, 2018**
|
5
|
+
- Change method of applying patches from `require 'rearmed_rails/apply_patches'` to `RearmedRails#apply_patches!`
|
6
|
+
- Once `apply_patches!` has been called, then `enabled_patches` cannot be changed. If it is, it will raise a `PatchesAlreadyAppliedError`
|
7
|
+
- Allow setting `:all` for `Rearmed#enabled_patches=`
|
8
|
+
- Add type checking to `Rearmed#enabled_patches=`
|
9
|
+
- Remove support for Rails 3
|
10
|
+
- Remove and Extract minitest methods to new gem `minitest-changed-assertions`
|
11
|
+
- Remove `ActiveRecord#or` method as it does not always return correct results. Instead use this gem https://github.com/khiav223577/rails_or
|
12
|
+
- Remove `ActiveRecord#find_in_relation_batches` and `ActiveRecord#find_relation_each` methods. The reason I implemented these methods was to improve some performance issues I was having. After used this and then later trying some other techniques I can confirm this is a poor technique to improve performance. Therefore I am removing these methods.
|
4
13
|
- **1.0.5 - August 3, 2017**
|
5
14
|
- Fix `options_for_select_include_blank` & `options_for_select_include_blank` for Rails 5.1+ and improved them to patch in safer way
|
6
15
|
- **1.0.4 - July 19, 2017**
|
data/README.md
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
# Rearmed Rails
|
2
|
-
|
2
|
+
|
3
|
+
<a href="https://badge.fury.io/rb/rearmed_rails" target="_blank"><img height="21" style='border:0px;height:21px;' border='0' src="https://badge.fury.io/rb/rearmed_rails.svg" alt="Gem Version"></a>
|
4
|
+
<a href='https://travis-ci.org/westonganger/rearmed_rails' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://api.travis-ci.org/westonganger/rearmed_rails.svg?branch=master' border='0' alt='Build Status' /></a>
|
5
|
+
<a href='https://rubygems.org/gems/rearmed_rails' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://ruby-gem-downloads-badge.herokuapp.com/rearmed?label=rubygems&type=total&total_label=downloads&color=brightgreen' border='0' alt='RubyGems Downloads' /></a>
|
6
|
+
<a href='https://ko-fi.com/A5071NK' target='_blank'><img height='22' style='border:0px;height:22px;' src='https://az743702.vo.msecnd.net/cdn/kofi1.png?v=a' border='0' alt='Buy Me a Coffee' /></a>
|
7
|
+
|
3
8
|
|
4
9
|
A collection of helpful methods and monkey patches for Rails
|
5
10
|
|
6
|
-
The difference between this library and others is that all monkey patching is performed in an opt-in way because you shouldnt be using methods you dont know about
|
11
|
+
The difference between this library and others is that all monkey patching is performed in an opt-in way because you shouldnt be using methods that you dont know about.
|
7
12
|
|
8
13
|
```ruby
|
9
14
|
# Gemfile
|
@@ -17,73 +22,59 @@ Run `rails g rearmed_rails:setup` to create a settings files in `config/initiali
|
|
17
22
|
# config/initializers/rearmed.rb
|
18
23
|
|
19
24
|
RearmedRails.enabled_patches = {
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
or: false,
|
28
|
-
pluck_to_hash: false,
|
29
|
-
pluck_to_struct: false,
|
30
|
-
reset_auto_increment: false,
|
31
|
-
reset_table: false
|
32
|
-
},
|
33
|
-
helpers: {
|
34
|
-
field_is_array: false,
|
35
|
-
link_to_confirm: false,
|
36
|
-
options_for_select_include_blank: false,
|
37
|
-
options_from_collection_for_select_include_blank: false
|
38
|
-
},
|
39
|
-
v3: {
|
40
|
-
all: false,
|
41
|
-
pluck: false,
|
42
|
-
update_columns: false
|
43
|
-
}
|
25
|
+
find_duplicates: false,
|
26
|
+
find_or_create: false,
|
27
|
+
newest: false,
|
28
|
+
pluck_to_hash: false,
|
29
|
+
pluck_to_struct: false,
|
30
|
+
reset_auto_increment: false,
|
31
|
+
reset_table: false
|
44
32
|
},
|
45
|
-
|
46
|
-
|
47
|
-
|
33
|
+
helpers: {
|
34
|
+
field_is_array: false,
|
35
|
+
link_to_confirm: false,
|
36
|
+
options_for_select_include_blank: false,
|
37
|
+
options_from_collection_for_select_include_blank: false
|
48
38
|
}
|
49
39
|
}
|
50
40
|
|
41
|
+
RearmedRails.apply_patches!
|
42
|
+
```
|
43
|
+
|
44
|
+
Some other argument formats the `enabled_patches` option accepts are:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
### Enable everything
|
48
|
+
Rearmed.enabled_patches = :all
|
49
|
+
|
50
|
+
### Disable everything
|
51
|
+
Rearmed.enabled_patches = nil
|
51
52
|
|
52
|
-
|
53
|
+
### Hash values can be boolean/nil values also
|
54
|
+
Rearmed.enabled_patches = {
|
55
|
+
active_record: true,
|
56
|
+
helpers: false,
|
57
|
+
}
|
53
58
|
```
|
54
59
|
|
60
|
+
By design, once `apply_patches!` is called then `RearmedRails.enabled_patches` is no longer editable and `apply_patches!` cannot be called again. If you try to do so, it will raise a `PatchesAlreadyAppliedError`. There is no-built in way of changing the patches, if you need to do so (which you shouldn't) that is up to you to figure out.
|
61
|
+
|
55
62
|
|
56
63
|
## Rails
|
57
64
|
|
58
65
|
### ActiveRecord
|
59
66
|
|
60
67
|
```ruby
|
61
|
-
# This version of `or` behaves way nicer than the stupid one that was implemented in Rails 5
|
62
|
-
# it allows you to do what you need when you want to. This patch is for Rails 4, 5+
|
63
|
-
Post.where(name: 'foo').or.where(content: 'bar')
|
64
|
-
Post.where(name: 'foo').or.my_custom_scope
|
65
|
-
Post.where(name: 'foo').or(Post.where(content: 'bar'))
|
66
|
-
Post.where(name: 'foo').or(content: 'bar')
|
67
|
-
|
68
|
-
Post.pluck_to_hash(:name, :category, :id)
|
69
|
-
Post.pluck_to_struct(:name, :category, :id)
|
70
|
-
|
71
68
|
Post.find_or_create(name: 'foo', content: 'bar') # use this instead of the super confusing first_or_create method
|
72
69
|
Post.find_or_create!(name: 'foo', content: 'bar')
|
73
70
|
|
74
|
-
Post.find_duplicates # return active record relation of all records that have duplicates. By default it skips the primary_key, created_at, updated_at, & deleted_at columns
|
75
|
-
Post.find_duplicates(:name) # find duplicates based on the name attribute
|
76
|
-
Post.find_duplicates(:name, :category) # find duplicates based on the name & category attribute
|
77
|
-
Post.find_duplicates(self.column_names.reject{|x| ['id','created_at','updated_at','deleted_at'].include?(x)})
|
78
|
-
|
79
|
-
# It also can delete duplicates. Valid values for keep are :first & :last. Valid values for delete_method are :destroy & :delete. soft_delete is only used if you are using acts_as_paranoid on your model.
|
80
|
-
Post.find_duplicates(:name, :category, delete: true)
|
81
|
-
Post.find_duplicates(:name, :category, delete: {keep: :first, delete_method: :destroy, soft_delete: true}) # these are the default settings for delete: true
|
82
|
-
|
83
71
|
Post.newest # get the newest post, by default ordered by :created_at
|
84
72
|
Post.newest(:updated_at) # different sort order
|
85
73
|
Post.newest(:published_at, :created_at) # multiple columns to sort on
|
86
74
|
|
75
|
+
Post.pluck_to_hash(:name, :category, :id)
|
76
|
+
Post.pluck_to_struct(:name, :category, :id)
|
77
|
+
|
87
78
|
Post.reset_table # delete all records from table and reset autoincrement column (id), works with mysql/mariadb/postgresql/sqlite
|
88
79
|
# or with options
|
89
80
|
Post.reset_table(delete_method: :destroy) # to ensure all callbacks are fired
|
@@ -92,11 +83,17 @@ Post.reset_auto_increment # reset mysql/mariadb/postgresql/sqlite auto-increment
|
|
92
83
|
# or with options
|
93
84
|
Post.reset_auto_increment(value: 1, column: :id) # column option is only relevant for postgresql
|
94
85
|
|
95
|
-
Post.
|
96
|
-
Post.
|
97
|
-
|
86
|
+
Post.find_duplicates # return active record relation of all records that have duplicates. By default it skips the primary_key, created_at, updated_at, & deleted_at columns
|
87
|
+
Post.find_duplicates(:name) # find duplicates based on the name attribute
|
88
|
+
Post.find_duplicates(:name, :category) # find duplicates based on the name & category attribute
|
89
|
+
Post.find_duplicates(self.column_names.reject{|x| ['id','created_at','updated_at','deleted_at'].include?(x)})
|
98
90
|
|
99
|
-
|
91
|
+
# It also can delete duplicates.
|
92
|
+
# Valid values for keep are :first & :last.
|
93
|
+
# Valid values for delete_method are :destroy & :delete. The soft-delete option is only used if you are using acts_as_paranoid on your model.
|
94
|
+
Post.find_duplicates(:name, :category, delete: true)
|
95
|
+
Post.find_duplicates(:name, :category, delete: {keep: :first, delete_method: :destroy, soft_delete: true}) # these are the default settings for delete: true
|
96
|
+
```
|
100
97
|
|
101
98
|
### Helpers
|
102
99
|
|
@@ -110,42 +107,20 @@ options_for_select(@users.map{|x| [x.name, x.id]}, include_blank: true, selected
|
|
110
107
|
# options_from_collection_for_select_include_blank
|
111
108
|
options_from_collection_for_select(@users, 'id', 'name', include_blank: true, selected: params[:user_id])
|
112
109
|
|
113
|
-
# returns
|
110
|
+
# returns Rails v3 behaviour of allowing confirm attribute as well as data-confirm
|
114
111
|
= link_to 'Delete', post_path(post), method: :delete, confirm: "Are you sure you want to delete this post?"
|
115
112
|
```
|
116
113
|
|
117
|
-
### Rails 3.x Backports
|
118
|
-
```ruby
|
119
|
-
Post.all # Now returns AR relation
|
120
|
-
Post.first.update_columns(a: 'foo', b: 'bar')
|
121
|
-
Post.pluck(:name, :id) # adds multi column pluck support ex. => [['first', 1], ['second', 2], ['third', 3]]
|
122
|
-
```
|
123
|
-
|
124
|
-
### Minitest Methods
|
125
|
-
```ruby
|
126
|
-
assert_changed 'user.name' do
|
127
|
-
user.name = "Bob"
|
128
|
-
end
|
129
|
-
|
130
|
-
assert_not_changed -> { user.name } do
|
131
|
-
user.update(user_params)
|
132
|
-
end
|
133
|
-
|
134
|
-
assert_not_changed lambda{ user.name } do
|
135
|
-
user.update(user_params)
|
136
|
-
end
|
137
|
-
```
|
138
|
-
|
139
114
|
# Contributing
|
140
115
|
If you want to request a new method please raise an issue and we will discuss the idea.
|
141
116
|
|
142
117
|
|
143
118
|
# Credits
|
144
|
-
Created by Weston Ganger - [@westonganger](https://github.com/westonganger)
|
119
|
+
Created by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
|
145
120
|
|
146
121
|
For any consulting or contract work please contact me via my company website: [Solid Foundation Web Development](https://solidfoundationwebdev.com)
|
147
122
|
|
148
|
-
##
|
123
|
+
## Other Libraries in the Rearmed family of Plugins
|
149
124
|
- [Rearmed Ruby](https://github.com/westonganger/rearmed-rb)
|
150
125
|
- [Rearmed JS](https://github.com/westonganger/rearmed_rails)
|
151
126
|
- [Rearmed CSS](https://github.com/westonganger/rearmed_css)
|
data/Rakefile
CHANGED
@@ -5,20 +5,19 @@ task :test do
|
|
5
5
|
require 'rake/testtask'
|
6
6
|
Rake::TestTask.new do |t|
|
7
7
|
t.libs << 'test'
|
8
|
-
t.test_files = FileList['test
|
8
|
+
t.test_files = FileList['test/**/*_test.rb']
|
9
9
|
t.verbose = true
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
task :console do
|
14
|
-
require '
|
14
|
+
require 'active_record'
|
15
|
+
require 'action_view'
|
15
16
|
|
16
|
-
|
17
|
-
rails: true,
|
18
|
-
minitest: true
|
19
|
-
}
|
17
|
+
require 'rearmed_rails'
|
20
18
|
|
21
|
-
|
19
|
+
RearmedRails.enabled_patches = :all
|
20
|
+
RearmedRails.apply_patches!
|
22
21
|
|
23
22
|
require 'irb'
|
24
23
|
binding.irb
|
@@ -7,7 +7,7 @@ module RearmedRails
|
|
7
7
|
create_file "config/initializers/rearmed_rails.rb", <<eos
|
8
8
|
RearmedRails.enabled_patches = #{File.read(File.join(File.dirname(__FILE__), '../../rearmed_rails/default_enabled_patches.hash'))}
|
9
9
|
|
10
|
-
|
10
|
+
RearmedRails.apply_patches!'
|
11
11
|
eos
|
12
12
|
end
|
13
13
|
|
data/lib/rearmed_rails.rb
CHANGED
@@ -2,19 +2,58 @@ require 'rearmed_rails/version'
|
|
2
2
|
|
3
3
|
module RearmedRails
|
4
4
|
|
5
|
-
|
5
|
+
DEFAULT_PATCHES = eval(File.read(File.join(File.dirname(__FILE__), 'rearmed_rails/default_enabled_patches.hash'))).freeze
|
6
|
+
private_constant :DEFAULT_PATCHES
|
7
|
+
|
8
|
+
@enabled_patches = Marshal.load(Marshal.dump(DEFAULT_PATCHES))
|
9
|
+
@applied = false
|
6
10
|
|
7
11
|
def self.enabled_patches=(val)
|
8
|
-
@
|
12
|
+
if @applied
|
13
|
+
raise ::RearmedRails::Exceptions::PatchesAlreadyAppliedError.new
|
14
|
+
else
|
15
|
+
if val.nil?
|
16
|
+
@enabled_patches = Marshal.load(Marshal.dump(DEFAULT_PATCHES))
|
17
|
+
elsif val == :all
|
18
|
+
@enabled_patches = val
|
19
|
+
elsif val.is_a?(Hash)
|
20
|
+
@enabled_patches = Marshal.load(Marshal.dump(DEFAULT_PATCHES))
|
21
|
+
|
22
|
+
DEFAULT_PATCHES.keys.each do |k|
|
23
|
+
methods = val[k] || val[k.to_sym]
|
24
|
+
if methods
|
25
|
+
if methods.is_a?(Hash) || methods == true
|
26
|
+
@enabled_patches[k] = methods
|
27
|
+
else
|
28
|
+
raise TypeError.new('Invalid value within the hash passed to Rearmed.enabled_patches=')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
else
|
33
|
+
raise TypeError.new('Invalid value passed to Rearmed.enabled_patches=')
|
34
|
+
end
|
35
|
+
end
|
9
36
|
end
|
10
37
|
|
11
38
|
def self.enabled_patches
|
12
39
|
@enabled_patches
|
13
40
|
end
|
14
41
|
|
42
|
+
def self.apply_patches!
|
43
|
+
if @applied
|
44
|
+
raise ::RearmedRails::Exceptions::PatchesAlreadyAppliedError.new
|
45
|
+
else
|
46
|
+
Dir[File.join(__dir__, 'rearmed_rails/monkey_patches/**/*.rb')].each do |filename|
|
47
|
+
require filename
|
48
|
+
end
|
49
|
+
|
50
|
+
@applied = true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
15
54
|
private
|
16
55
|
|
17
|
-
def self.
|
56
|
+
def self._dig(collection, *values)
|
18
57
|
current_val = nil
|
19
58
|
current_collection = collection
|
20
59
|
values.each_with_index do |val,i|
|
@@ -1,31 +1,17 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
field_is_array: false,
|
17
|
-
link_to_confirm: false,
|
18
|
-
options_for_select_include_blank: false,
|
19
|
-
options_from_collection_for_select_include_blank: false
|
20
|
-
},
|
21
|
-
v3: {
|
22
|
-
all: false,
|
23
|
-
pluck: false,
|
24
|
-
update_columns: false
|
25
|
-
},
|
26
|
-
minitest: {
|
27
|
-
assert_changed: false,
|
28
|
-
assert_not_changed: false
|
29
|
-
}
|
2
|
+
active_record: {
|
3
|
+
find_duplicates: false,
|
4
|
+
find_or_create: false,
|
5
|
+
newest: false,
|
6
|
+
pluck_to_hash: false,
|
7
|
+
pluck_to_struct: false,
|
8
|
+
reset_auto_increment: false,
|
9
|
+
reset_table: false
|
10
|
+
},
|
11
|
+
helpers: {
|
12
|
+
field_is_array: false,
|
13
|
+
link_to_confirm: false,
|
14
|
+
options_for_select_include_blank: false,
|
15
|
+
options_from_collection_for_select_include_blank: false
|
30
16
|
}
|
31
17
|
}
|
@@ -1,10 +1,9 @@
|
|
1
|
-
enabled = RearmedRails.enabled_patches
|
2
|
-
enabled ||= RearmedRails.dig(RearmedRails.enabled_patches, :rails, :active_record) == true
|
1
|
+
enabled = RearmedRails.enabled_patches == :all || RearmedRails._dig(RearmedRails.enabled_patches, :active_record) == true
|
3
2
|
|
4
3
|
if defined?(ActiveRecord)
|
5
4
|
|
6
5
|
ActiveRecord::Base.class_eval do
|
7
|
-
if enabled || RearmedRails.
|
6
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :newest)
|
8
7
|
def self.newest(*columns)
|
9
8
|
if columns.empty? || !columns.to_s.include?('created_at')
|
10
9
|
columns << 'created_at'
|
@@ -18,7 +17,7 @@ if defined?(ActiveRecord)
|
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
if enabled || RearmedRails.
|
20
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :reset_table)
|
22
21
|
def self.reset_table(opts={})
|
23
22
|
if opts[:delete_method] && opts[:delete_method].to_sym == :destroy
|
24
23
|
if self.try(:paranoid?)
|
@@ -53,7 +52,7 @@ if defined?(ActiveRecord)
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
if enabled || RearmedRails.
|
55
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :reset_auto_increment)
|
57
56
|
def self.reset_auto_increment(opts={})
|
58
57
|
case self.connection.adapter_name.downcase.to_sym
|
59
58
|
when :mysql2
|
@@ -69,7 +68,7 @@ if defined?(ActiveRecord)
|
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
72
|
-
if enabled || RearmedRails.
|
71
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :find_duplicates)
|
73
72
|
def self.find_duplicates(*args)
|
74
73
|
options = {}
|
75
74
|
|
@@ -143,7 +142,7 @@ if defined?(ActiveRecord)
|
|
143
142
|
end
|
144
143
|
end
|
145
144
|
|
146
|
-
if enabled || RearmedRails.
|
145
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :find_or_create)
|
147
146
|
def self.find_or_create(attrs={}, save_opts={})
|
148
147
|
unless self.where(attrs).limit(1).first
|
149
148
|
x = self.class.new(attrs)
|
@@ -161,7 +160,7 @@ if defined?(ActiveRecord)
|
|
161
160
|
end
|
162
161
|
end
|
163
162
|
|
164
|
-
if enabled || RearmedRails.
|
163
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :pluck_to_hash)
|
165
164
|
def self.pluck_to_hash(*keys)
|
166
165
|
hash_type = keys[-1].is_a?(Hash) ? keys.pop.fetch(:hash_type, HashWithIndifferentAccess) : HashWithIndifferentAccess
|
167
166
|
block_given = block_given?
|
@@ -175,7 +174,7 @@ if defined?(ActiveRecord)
|
|
175
174
|
end
|
176
175
|
end
|
177
176
|
|
178
|
-
if enabled || enabled || RearmedRails.
|
177
|
+
if enabled || enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :pluck_to_struct)
|
179
178
|
def self.pluck_to_struct(*keys)
|
180
179
|
struct_type = keys[-1].is_a?(Hash) ? keys.pop.fetch(:struct_type, Struct) : Struct
|
181
180
|
block_given = block_given?
|
@@ -192,7 +191,7 @@ if defined?(ActiveRecord)
|
|
192
191
|
|
193
192
|
private
|
194
193
|
|
195
|
-
if enabled || RearmedRails.
|
194
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :active_record, :pluck_to_hash) || RearmedRails._dig(RearmedRails.enabled_patches, :pluck_to_struct)
|
196
195
|
def self.format_keys(keys)
|
197
196
|
if keys.blank?
|
198
197
|
[column_names, column_names]
|
@@ -1,9 +1,8 @@
|
|
1
|
-
enabled = RearmedRails.enabled_patches
|
2
|
-
enabled ||= RearmedRails.dig(RearmedRails.enabled_patches, :rails, :helpers) == true
|
1
|
+
enabled = RearmedRails.enabled_patches == :all || RearmedRails._dig(RearmedRails.enabled_patches, :helpers) == true
|
3
2
|
|
4
3
|
if defined?(ActionView::Helpers)
|
5
4
|
|
6
|
-
if enabled || RearmedRails.
|
5
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :helpers, :link_to_confirm)
|
7
6
|
ActionView::Helpers::UrlHelper.module_eval do
|
8
7
|
def convert_options_to_data_attributes(options, html_options)
|
9
8
|
if html_options
|
@@ -25,7 +24,7 @@ if defined?(ActionView::Helpers)
|
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
28
|
-
if enabled || RearmedRails.
|
27
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :helpers, :field_is_array)
|
29
28
|
module ActionView
|
30
29
|
module Helpers
|
31
30
|
module Tags
|
@@ -53,7 +52,7 @@ if defined?(ActionView::Helpers)
|
|
53
52
|
|
54
53
|
RearmedRails::RailsHelpers.module_eval do
|
55
54
|
|
56
|
-
if enabled || RearmedRails.
|
55
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :helpers, :options_for_select_include_blank)
|
57
56
|
def options_for_select(container, selected = nil)
|
58
57
|
if selected.is_a?(Hash)
|
59
58
|
include_blank = selected[:include_blank] || selected['include_blank']
|
@@ -77,7 +76,7 @@ if defined?(ActionView::Helpers)
|
|
77
76
|
end
|
78
77
|
end
|
79
78
|
|
80
|
-
if enabled || RearmedRails.
|
79
|
+
if enabled || RearmedRails._dig(RearmedRails.enabled_patches, :helpers, :options_for_select_include_blank)
|
81
80
|
def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
|
82
81
|
options = collection.map do |element|
|
83
82
|
[value_for_collection(element, text_method), value_for_collection(element, value_method), option_html_attributes(element)]
|
@@ -5,53 +5,49 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
require 'yaml'
|
7
7
|
require 'minitest'
|
8
|
+
require 'minitest/autorun'
|
8
9
|
|
10
|
+
require 'active_record'
|
11
|
+
require 'action_view'
|
9
12
|
require 'rearmed_rails'
|
10
13
|
|
11
|
-
|
14
|
+
RearmedRails.enabled_patches = :all
|
15
|
+
RearmedRails.apply_patches!
|
12
16
|
|
13
|
-
class
|
17
|
+
class RearmedRailsTest < MiniTest::Test
|
14
18
|
def setup
|
15
|
-
|
16
|
-
alias_method :eql, :assert_equal
|
17
|
-
end
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
rails: true,
|
21
|
-
minitest: true
|
22
|
-
}
|
23
|
-
require 'rearmed_rails/apply_patches'
|
21
|
+
def teardown
|
24
22
|
end
|
25
23
|
|
26
|
-
def
|
27
|
-
|
28
|
-
assert_changed "str" do
|
29
|
-
str = 'second'
|
30
|
-
end
|
24
|
+
def test_enabled_patches
|
25
|
+
RearmedRails.instance_variable_set(:@applied, false)
|
31
26
|
|
32
|
-
|
33
|
-
assert_changed ->{ str } do
|
34
|
-
str = 'second'
|
35
|
-
end
|
27
|
+
default = RearmedRails.const_get(:DEFAULT_PATCHES)
|
36
28
|
|
37
|
-
|
38
|
-
|
39
|
-
name = 'second'
|
40
|
-
end
|
29
|
+
RearmedRails.enabled_patches = nil
|
30
|
+
assert_equal RearmedRails.enabled_patches, default
|
41
31
|
|
42
|
-
|
43
|
-
|
44
|
-
name = 'first'
|
45
|
-
end
|
32
|
+
RearmedRails.enabled_patches = {}
|
33
|
+
assert_equal RearmedRails.enabled_patches, default
|
46
34
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
35
|
+
RearmedRails.enabled_patches = :all
|
36
|
+
assert_equal RearmedRails.enabled_patches, :all
|
37
|
+
|
38
|
+
RearmedRails.enabled_patches = {active_record: true, helpers: false, foo: :bar}
|
39
|
+
assert_equal RearmedRails.enabled_patches, default.merge({active_record: true})
|
51
40
|
|
52
|
-
|
53
|
-
|
54
|
-
|
41
|
+
[true, false, [], '', 1, :foo, RearmedRails].each do |x|
|
42
|
+
assert_raises TypeError do
|
43
|
+
RearmedRails.enabled_patches = x
|
44
|
+
end
|
45
|
+
|
46
|
+
if x != true && x != false
|
47
|
+
assert_raises TypeError do
|
48
|
+
RearmedRails.enabled_patches = {active_record: x}
|
49
|
+
end
|
50
|
+
end
|
55
51
|
end
|
56
52
|
end
|
57
53
|
|
@@ -74,26 +70,11 @@ class TestRearmedRails < MiniTest::Test
|
|
74
70
|
#Post.reset_auto_increment # reset mysql/mariadb/postgresql/sqlite auto-increment column, if contains records then defaults to starting from next available number
|
75
71
|
## or with options
|
76
72
|
#Post.reset_auto_increment(value: 1, column: :id) # column option is only relevant for postgresql
|
77
|
-
|
78
|
-
#Post.find_in_relation_batches # this returns a relation instead of an array
|
79
|
-
#Post.find_relation_each # this returns a relation instead of an array
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_rails_3
|
83
|
-
#my_hash.compact
|
84
|
-
#my_hash.compact!
|
85
|
-
#Post.all # Now returns AR relation
|
86
|
-
#Post.first.update_columns(a: 'foo', b: 'bar')
|
87
|
-
#Post.pluck(:name, :id) # adds multi column pluck support ex. => [['first', 1], ['second', 2], ['third', 3]]
|
88
73
|
end
|
89
74
|
|
90
75
|
def test_rails_4
|
91
|
-
#Post.where(name: 'foo').or.where(content: 'bar')
|
92
|
-
#Post.where(name: 'foo').or.my_custom_scope
|
93
|
-
#Post.where(name: 'foo').or(Post.where(content: 'bar'))
|
94
|
-
#Post.where(name: 'foo).or(content: 'bar')
|
95
|
-
|
96
76
|
#= link_to 'Delete', post_path(post), method: :delete, confirm: "Are you sure you want to delete this post?"
|
97
77
|
# returns to rails 3 behaviour of allowing confirm attribute as well as data-confirm
|
98
78
|
end
|
79
|
+
|
99
80
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rearmed_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Weston Ganger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
description: A collection of helpful methods and monkey patches for Rails
|
56
|
-
email: westonganger
|
56
|
+
email: weston@westonganger.com
|
57
57
|
executables: []
|
58
58
|
extensions: []
|
59
59
|
extra_rdoc_files: []
|
@@ -64,16 +64,12 @@ files:
|
|
64
64
|
- Rakefile
|
65
65
|
- lib/generators/rearmed_rails/setup_generator.rb
|
66
66
|
- lib/rearmed_rails.rb
|
67
|
-
- lib/rearmed_rails/apply_patches.rb
|
68
67
|
- lib/rearmed_rails/default_enabled_patches.hash
|
69
|
-
- lib/rearmed_rails/
|
70
|
-
- lib/rearmed_rails/monkey_patches/
|
71
|
-
- lib/rearmed_rails/monkey_patches/
|
72
|
-
- lib/rearmed_rails/monkey_patches/rails/active_record/query_methods.rb
|
73
|
-
- lib/rearmed_rails/monkey_patches/rails/helpers.rb
|
74
|
-
- lib/rearmed_rails/monkey_patches/rails/v3.rb
|
68
|
+
- lib/rearmed_rails/exceptions.rb
|
69
|
+
- lib/rearmed_rails/monkey_patches/active_record.rb
|
70
|
+
- lib/rearmed_rails/monkey_patches/helpers.rb
|
75
71
|
- lib/rearmed_rails/version.rb
|
76
|
-
- test/
|
72
|
+
- test/rearmed_rails_test.rb
|
77
73
|
homepage: https://github.com/westonganger/rearmed_rails
|
78
74
|
licenses: []
|
79
75
|
metadata: {}
|
@@ -93,9 +89,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
89
|
version: '0'
|
94
90
|
requirements: []
|
95
91
|
rubyforge_project:
|
96
|
-
rubygems_version: 2.6
|
92
|
+
rubygems_version: 2.7.6
|
97
93
|
signing_key:
|
98
94
|
specification_version: 4
|
99
95
|
summary: A collection of helpful methods and monkey patches for Rails
|
100
96
|
test_files:
|
101
|
-
- test/
|
97
|
+
- test/rearmed_rails_test.rb
|
@@ -1,6 +0,0 @@
|
|
1
|
-
require 'rearmed_rails/monkey_patches/rails/active_record/base'
|
2
|
-
require 'rearmed_rails/monkey_patches/rails/active_record/batches'
|
3
|
-
require 'rearmed_rails/monkey_patches/rails/active_record/query_methods'
|
4
|
-
require 'rearmed_rails/monkey_patches/rails/helpers'
|
5
|
-
require 'rearmed_rails/monkey_patches/rails/v3'
|
6
|
-
require 'rearmed_rails/monkey_patches/minitest'
|
@@ -1,35 +0,0 @@
|
|
1
|
-
if defined?(Minitest::Assertions)
|
2
|
-
|
3
|
-
enabled = RearmedRails.enabled_patches[:minitest] == true
|
4
|
-
|
5
|
-
Minitest::Assertions.module_eval do
|
6
|
-
|
7
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :minitest, :assert_changed)
|
8
|
-
def assert_changed(expression, &block)
|
9
|
-
if expression.respond_to?(:call)
|
10
|
-
e = expression
|
11
|
-
else
|
12
|
-
e = lambda{ block.binding.eval(expression) }
|
13
|
-
end
|
14
|
-
old = e.call
|
15
|
-
block.call
|
16
|
-
refute_equal old, e.call
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :minitest, :assert_not_changed)
|
21
|
-
def assert_not_changed(expression, &block)
|
22
|
-
if expression.respond_to?(:call)
|
23
|
-
e = expression
|
24
|
-
else
|
25
|
-
e = lambda{ block.binding.eval(expression) }
|
26
|
-
end
|
27
|
-
old = e.call
|
28
|
-
block.call
|
29
|
-
assert_equal old, e.call
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
enabled = RearmedRails.enabled_patches[:rails] == true
|
2
|
-
enabled ||= RearmedRails.dig(RearmedRails.enabled_patches, :rails, :active_record) == true
|
3
|
-
|
4
|
-
if defined?(ActiveRecord::Batches)
|
5
|
-
|
6
|
-
ActiveRecord::Batches.module_eval do
|
7
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :rails, :active_record, :find_in_relation_batches)
|
8
|
-
def find_in_relation_batches(options = {})
|
9
|
-
options.assert_valid_keys(:start, :batch_size)
|
10
|
-
|
11
|
-
relation = self
|
12
|
-
start = options[:start]
|
13
|
-
batch_size = options[:batch_size] || 1000
|
14
|
-
|
15
|
-
unless block_given?
|
16
|
-
return to_enum(:find_in_relation_batches, options) do
|
17
|
-
total = start ? where(table[primary_key].gteq(start)).size : size
|
18
|
-
(total - 1).div(batch_size) + 1
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
if logger && (arel.orders.present? || arel.taken.present?)
|
23
|
-
logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size")
|
24
|
-
end
|
25
|
-
|
26
|
-
relation = relation.reorder(batch_order).limit(batch_size)
|
27
|
-
#records = start ? relation.where(table[primary_key].gteq(start)).to_a : relation.to_a
|
28
|
-
records = start ? relation.where(table[primary_key].gteq(start)) : relation
|
29
|
-
|
30
|
-
while records.any?
|
31
|
-
records_size = records.size
|
32
|
-
primary_key_offset = records.last.id
|
33
|
-
raise ActiveRecordError, "Primary key not included in the custom select clause" unless primary_key_offset
|
34
|
-
|
35
|
-
yield records
|
36
|
-
|
37
|
-
break if records_size < batch_size
|
38
|
-
|
39
|
-
records = relation.where(table[primary_key].gt(primary_key_offset))#.to_a
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :rails, :active_record, :find_relation_each)
|
45
|
-
def find_relation_each(options = {})
|
46
|
-
if block_given?
|
47
|
-
find_in_relation_batches(options) do |records|
|
48
|
-
records.each { |record| yield record }
|
49
|
-
end
|
50
|
-
else
|
51
|
-
enum_for :find_relation_each, options do
|
52
|
-
options[:start] ? where(table[primary_key].gteq(options[:start])).size : size
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
enabled = RearmedRails.enabled_patches[:rails] == true
|
2
|
-
enabled ||= RearmedRails.dig(RearmedRails.enabled_patches, :rails, :active_record) == true
|
3
|
-
|
4
|
-
if defined?(ActiveRecord)
|
5
|
-
|
6
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :rails, :active_record, :or)
|
7
|
-
|
8
|
-
if Rails::VERSION::MAJOR > 4
|
9
|
-
|
10
|
-
unless defined?(ActiveRecord::Relation::QueryMethods)
|
11
|
-
module ActiveRecord
|
12
|
-
class Relation
|
13
|
-
module QueryMethods
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
module RearmedRails
|
20
|
-
class OrChain
|
21
|
-
def initialize(scope)
|
22
|
-
@scope = scope
|
23
|
-
end
|
24
|
-
|
25
|
-
def method_missing(method, *args, &block)
|
26
|
-
other = @scope.klass.unscoped do
|
27
|
-
@scope.klass.send(method, *args, &block)
|
28
|
-
end
|
29
|
-
return @scope.or(other)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
ActiveRecord::QueryMethods.module_eval do
|
35
|
-
def or(opts=nil, *rest)
|
36
|
-
if opts.nil?
|
37
|
-
return RearmedRails::OrChain.new(self)
|
38
|
-
else
|
39
|
-
other = opts.is_a?(ActiveRecord::Relation) ? opts : klass.unscoped.where(opts, rest)
|
40
|
-
|
41
|
-
self.where_clause = self.where_clause.or(other.where_clause)
|
42
|
-
self.having_clause = self.having_clause.or(other.having_clause)
|
43
|
-
|
44
|
-
return self
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
else # end of Rails 5+ section, Rails 4 below
|
50
|
-
|
51
|
-
module ActiveRecord
|
52
|
-
module Querying
|
53
|
-
delegate :or, to: :all
|
54
|
-
end
|
55
|
-
|
56
|
-
module QueryMethods
|
57
|
-
class OrChain
|
58
|
-
def initialize(scope)
|
59
|
-
@scope = scope
|
60
|
-
end
|
61
|
-
|
62
|
-
def method_missing(method, *args, &block)
|
63
|
-
right_relation = @scope.klass.unscoped do
|
64
|
-
@scope.klass.send(method, *args, &block)
|
65
|
-
end
|
66
|
-
@scope.or(right_relation)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def or(opts = :chain, *rest)
|
71
|
-
if opts == :chain
|
72
|
-
OrChain.new(self)
|
73
|
-
else
|
74
|
-
left = self
|
75
|
-
right = (ActiveRecord::Relation === opts) ? opts : klass.unscoped.where(opts, rest)
|
76
|
-
|
77
|
-
unless left.where_values.empty? || right.where_values.empty?
|
78
|
-
left.where_values = [left.where_ast.or(right.where_ast)]
|
79
|
-
right.where_values = []
|
80
|
-
end
|
81
|
-
|
82
|
-
left = left.merge(right)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
private # Returns an Arel AST containing only where_values
|
87
|
-
|
88
|
-
def where_ast
|
89
|
-
arel_wheres = []
|
90
|
-
|
91
|
-
where_values.each do |where|
|
92
|
-
arel_wheres << (String === where ? Arel.sql(where) : where)
|
93
|
-
end
|
94
|
-
|
95
|
-
return Arel::Nodes::Grouping.new(Arel::Nodes::And.new(arel_wheres)) if arel_wheres.length >= 2
|
96
|
-
|
97
|
-
if Arel::Nodes::SqlLiteral === arel_wheres.first
|
98
|
-
Arel::Nodes::Grouping.new(arel_wheres.first)
|
99
|
-
else
|
100
|
-
arel_wheres.first
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
end # end of Rails 4 section
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
enabled = RearmedRails.enabled_patches[:rails] == true
|
2
|
-
enabled ||= RearmedRails.dig(RearmedRails.enabled_patches, :rails, :v3) == true
|
3
|
-
|
4
|
-
if defined?(ActiveRecord) && ActiveRecord::VERSION::MAJOR < 4
|
5
|
-
|
6
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :rails, :v3, :all)
|
7
|
-
ActiveRecord::FinderMethods.module_eval do
|
8
|
-
def all(*args)
|
9
|
-
args.any? ? apply_finder_options(args.first) : self
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :rails, :v3, :pluck)
|
15
|
-
ActiveRecord::Relation.class_eval do
|
16
|
-
def pluck(*args)
|
17
|
-
args.map! do |column_name|
|
18
|
-
if column_name.is_a?(Symbol) && column_names.include?(column_name.to_s)
|
19
|
-
"#{connection.quote_table_name(table_name)}.#{connection.quote_column_name(column_name)}"
|
20
|
-
else
|
21
|
-
column_name.to_s
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
relation = clone
|
26
|
-
relation.select_values = args
|
27
|
-
klass.connection.select_all(relation.arel).map! do |attributes|
|
28
|
-
initialized_attributes = klass.initialize_attributes(attributes)
|
29
|
-
attributes.map do |key, attr|
|
30
|
-
klass.type_cast_attribute(key, initialized_attributes)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
if enabled || RearmedRails.dig(RearmedRails.enabled_patches, :rails, :v3, :update_columns)
|
38
|
-
ActiveRecord::Persistence::ClassMethods.module_eval do
|
39
|
-
def update_columns(attributes)
|
40
|
-
raise ActiveRecordError, "cannot update a new record" if new_record?
|
41
|
-
raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
|
42
|
-
|
43
|
-
attributes.each_key do |key|
|
44
|
-
raise ActiveRecordError, "#{key.to_s} is marked as readonly" if self.class.readonly_attributes.include?(key.to_s)
|
45
|
-
end
|
46
|
-
|
47
|
-
updated_count = self.class.unscoped.where(self.class.primary_key => id).update_all(attributes)
|
48
|
-
|
49
|
-
attributes.each do |k, v|
|
50
|
-
raw_write_attribute(k, v)
|
51
|
-
end
|
52
|
-
|
53
|
-
updated_count == 1
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|