advanced 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +180 -7
- data/lib/advanced/search_form.rb +2 -4
- data/lib/advanced/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53d443c5de56e2d0a6ea9cca3c9fc004b7abb5bd
|
4
|
+
data.tar.gz: 19f45cb819603d9aae9481310ff15d8738cfca50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b2ef8b08fa42d2b7e3349003fef96f764f2ef28a194bb66b7d161b3721a09dceabbf658ce5f3c35ab681738443983074fb85a92f2e2e9bbb493e0749d8e279d
|
7
|
+
data.tar.gz: 50923019d6fa927fcfa10eeba8837f09a5b7968db7228ce7ee0bf8251a515059a292d75409cc8a8d19301bb9d0e8b70bf2ed0b203d55cfe9424815c2e695963b
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Advanced
|
2
2
|
|
3
|
-
|
3
|
+
Advanced is a library for building complex searches with Active Record.
|
4
4
|
|
5
|
-
|
5
|
+
[Click here to see the source for the demo application.](https://github.com/rzane/advanced_demo)
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -22,19 +22,192 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
### Advanced::Search
|
26
26
|
|
27
|
-
|
27
|
+
Start by inheriting Advanced::Search.
|
28
28
|
|
29
|
-
|
29
|
+
```ruby
|
30
|
+
class StateSearch < Advanced::Search
|
31
|
+
def search_name(name:, **)
|
32
|
+
where('states.name like ?', "%#{name}%")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
`Advanced::Search` will look at the methods you've defined that start with `search_`. Above, we've declared the `search_name` method and listed the `name` parameter as a required key.
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
StateSearch.call(State.all, name: 'New')
|
41
|
+
#=> SELECT * FROM states WHERE states.name like '%New%'
|
42
|
+
|
43
|
+
StateSearch.call(State.all, foo: 'bar')
|
44
|
+
#=> SELECT * FROM states
|
45
|
+
|
46
|
+
StateSearch.call(State.all, name: '')
|
47
|
+
#=> SELECT * FROM states
|
48
|
+
```
|
49
|
+
|
50
|
+
### Search composition
|
51
|
+
|
52
|
+
We can compose multiple search objects.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class CitySearch < Advanced::Search
|
56
|
+
def search_name(name:, **)
|
57
|
+
where('cities.name like ?', "%#{name}%")
|
58
|
+
end
|
59
|
+
|
60
|
+
def search_state(state:, **)
|
61
|
+
joins(:state).merge StateSearch.call(State.all, state)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
CitySearch.call(City.all, name: 'New York')
|
68
|
+
#=> SELECT "cities".* FROM "cities" WHERE (cities.name like '%New York%')
|
69
|
+
|
70
|
+
CitySearch.call(City.all, state: { name: 'New York' })
|
71
|
+
#=> SELECT "cities".* FROM "cities"
|
72
|
+
#=> INNER JOIN "states" ON "states"."id" = "cities"."state_id"
|
73
|
+
#=> WHERE (states.name like '%New York%')
|
74
|
+
```
|
75
|
+
|
76
|
+
### Advanced::SearchForm
|
77
|
+
|
78
|
+
A common feature in Rails applications is building filters. `Advanced::SearchForm` can help you do that. It's basically just a hash that is compatible with Rails form builders.
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class StateSearch < Advanced::Search
|
82
|
+
# ...
|
83
|
+
|
84
|
+
class Form < Advanced::SearchForm
|
85
|
+
search StateSearch
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
It scans the keyword arguments in your search methods and defines accessors automatically:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
form = StateSearch::Form.new(name: 'Foo')
|
94
|
+
form.name #=> 'Foo'
|
95
|
+
form.name = 'Bar'
|
96
|
+
form.name #=> 'Bar'
|
97
|
+
form.to_h #=> { name: 'Foo' }
|
98
|
+
```
|
99
|
+
|
100
|
+
`Advanced::Search` treats this object like a hash, so you can just pass it along:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
StateSearch.call(State.all, form)
|
104
|
+
```
|
30
105
|
|
31
|
-
|
106
|
+
So, a controller action might look like this:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
def index
|
110
|
+
@form = StateSearch::Form.new(params[:q])
|
111
|
+
@states = StateSearch.call(State.all, @form)
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
Your view might look something like this:
|
116
|
+
|
117
|
+
```erb
|
118
|
+
<%= form_for @form, method: :get, url: states_path, as: :q do |f| %>
|
119
|
+
<p>
|
120
|
+
<%= f.label :name %>
|
121
|
+
<%= f.text_field :name %>
|
122
|
+
</p>
|
123
|
+
|
124
|
+
<%= f.submit 'Search' %>
|
125
|
+
<% end %>
|
126
|
+
|
127
|
+
<table>
|
128
|
+
<thead>
|
129
|
+
<tr>
|
130
|
+
<th>Name</th>
|
131
|
+
</tr>
|
132
|
+
</thead>
|
133
|
+
|
134
|
+
<tbody>
|
135
|
+
<% @states.each do |state| %>
|
136
|
+
<tr>
|
137
|
+
<td><%= state.name %></td>
|
138
|
+
</tr>
|
139
|
+
<% end %>
|
140
|
+
</tbody>
|
141
|
+
</table>
|
142
|
+
```
|
143
|
+
|
144
|
+
### Composing forms
|
145
|
+
|
146
|
+
You can compose forms just like your compose your searches.
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
class CitySearch < Advanced::Search
|
150
|
+
# ...
|
151
|
+
class Form < Advanced::SearchForm
|
152
|
+
search CitySearch
|
153
|
+
nested :state, StateSearch::Form
|
154
|
+
end
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
form = CitySearch::Form.new(name: 'New York', state: { name: 'New York' })
|
160
|
+
form.name #=> 'New York'
|
161
|
+
form.state.name #=> 'New York'
|
162
|
+
form.to_h #=> { name: 'New York', state: { name: 'New York' }}
|
163
|
+
```
|
164
|
+
|
165
|
+
Then, in your view, you can use `fields_for` to generate your form fields:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
<%= form_for @form, method: :get, url: cities_path, as: :q do |f| %>
|
169
|
+
<p>
|
170
|
+
<%= f.label :name %>
|
171
|
+
<%= f.text_field :name %>
|
172
|
+
</p>
|
173
|
+
|
174
|
+
<%= f.fields_for :state do |state| %>
|
175
|
+
<p>
|
176
|
+
<%= state.label :name, 'State' %>
|
177
|
+
<%= state.text_field :name %>
|
178
|
+
</p>
|
179
|
+
<% end %>
|
180
|
+
|
181
|
+
<%= f.submit 'Search' %>
|
182
|
+
<% end %>
|
183
|
+
```
|
184
|
+
|
185
|
+
# Other goodies
|
186
|
+
|
187
|
+
You can extend your models with a search method to keep it brief.
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
class State < ApplicationRecord
|
191
|
+
extend StateSearch.scope
|
192
|
+
end
|
193
|
+
```
|
194
|
+
|
195
|
+
Now, you have a shorthand:
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
State.search(name: 'New York')
|
199
|
+
```
|
200
|
+
|
201
|
+
If you'd prefer to call your search method something other than `search`, that's cool too:
|
202
|
+
|
203
|
+
```ruby
|
204
|
+
extend StateSearch.scope(:custom_search)
|
205
|
+
```
|
32
206
|
|
33
207
|
## Contributing
|
34
208
|
|
35
209
|
Bug reports and pull requests are welcome on GitHub at https://github.com/Ray Zane/advanced.
|
36
210
|
|
37
|
-
|
38
211
|
## License
|
39
212
|
|
40
213
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/advanced/search_form.rb
CHANGED
@@ -34,10 +34,8 @@ module Advanced
|
|
34
34
|
instance_variable_set(ivar, form.new)
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
instance_variable_set(ivar, form.new(values))
|
40
|
-
end
|
37
|
+
define_method("#{key}=") do |values|
|
38
|
+
instance_variable_set(ivar, form.new(values))
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
data/lib/advanced/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: advanced
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ray Zane
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-08-
|
11
|
+
date: 2017-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|