page_record 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rubocop.yml +13 -0
- data/CHANGES.md +5 -0
- data/Gemfile.lock +46 -14
- data/Guardfile +24 -0
- data/README.md +27 -1
- data/bin/autospec +16 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/lib/page_record/attribute_accessors.rb +57 -54
- data/lib/page_record/base.rb +27 -22
- data/lib/page_record/class_actions.rb +47 -50
- data/lib/page_record/class_methods.rb +252 -261
- data/lib/page_record/errors.rb +81 -82
- data/lib/page_record/finders.rb +129 -131
- data/lib/page_record/form_builder.rb +4 -4
- data/lib/page_record/formtastic.rb +20 -9
- data/lib/page_record/helpers.rb +192 -131
- data/lib/page_record/inspector.rb +36 -0
- data/lib/page_record/instance_actions.rb +44 -46
- data/lib/page_record/rspec.rb +1 -1
- data/lib/page_record/validation.rb +46 -0
- data/lib/page_record/version.rb +1 -1
- data/lib/page_record.rb +13 -15
- data/page_record.gemspec +4 -1
- data/spec/.rubocop.yml +4 -0
- data/spec/helpers_spec.rb +109 -100
- data/spec/inspector_spec.rb +70 -0
- data/spec/page_record_spec.rb +357 -388
- data/spec/spec_helper.rb +1 -3
- data/spec/support/shared_contexts.rb +24 -2
- data/spec/support/shared_examples.rb +41 -45
- data/spec/support/team.rb +4 -4
- data/spec/support/test_app.rb +10 -13
- data/spec/support/views/page-with-1-error.erb +5 -0
- data/spec/support/views/page-with-2-errors-on-different-attributes.erb +9 -0
- data/spec/support/views/page-with-2-errors-on-same-attribute.erb +6 -0
- data/spec/support/views/page-without-errors.erb +4 -0
- data/spec/validation_spec.rb +142 -0
- data/tmp/rspec_guard_result +1 -0
- metadata +80 -5
data/lib/page_record/helpers.rb
CHANGED
@@ -2,118 +2,177 @@ module PageRecord
|
|
2
2
|
|
3
3
|
module Helpers
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
def form_record_for(type, var=nil)
|
5
|
+
##
|
6
|
+
#
|
7
|
+
# returns a hash containing the record-type and the id. The id is based on the type. For example when
|
8
|
+
# you specify `:team` as the type, it will search for the `@type` instance variable.
|
9
|
+
#
|
10
|
+
# example:
|
11
|
+
#
|
12
|
+
# ```ruby
|
13
|
+
# <%= form_for(@team, html:form_record_for(:team)) do |f| %>
|
14
|
+
# <% end %>
|
15
|
+
# ```
|
16
|
+
# this returns the follwing HTML:
|
17
|
+
#
|
18
|
+
# ```html
|
19
|
+
# <form accept-charset="UTF-8" action="/teams/2" class="edit_team" data-team-id="2" id="edit_team_2" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value=""><input name="_method" type="hidden" value="patch"><input name="authenticity_token" type="hidden" value="QXIbPXH65Ek+8i0j2R8akdHX2WXLo2MuDFuUVL8CQpY="></div>
|
20
|
+
# </form>
|
21
|
+
# ```
|
22
|
+
#
|
23
|
+
# @param type Symbol identifying the type of record and the variable to use
|
24
|
+
# @param var the variable to use. This is optional
|
25
|
+
#
|
26
|
+
# @return Hash
|
27
|
+
#
|
28
|
+
#
|
29
|
+
def form_record_for(type, var = nil)
|
30
30
|
if var
|
31
31
|
id = var.id
|
32
32
|
else
|
33
33
|
id = instance_eval("@#{type}.id")
|
34
34
|
end
|
35
35
|
id ||= 'new'
|
36
|
-
Hash["data-#{type}-id",id]
|
36
|
+
Hash["data-#{type}-id", id]
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
39
|
+
##
|
40
|
+
#
|
41
|
+
# returns a string containing the record-type and the id. The id is based on the type. For example when
|
42
|
+
# you specify `:team` as the type, it will search for the `type` instance variable.
|
43
|
+
#
|
44
|
+
# example:
|
45
|
+
#
|
46
|
+
# ```ruby
|
47
|
+
# <tr <%= record_for(:team)%>>
|
48
|
+
# ```
|
49
|
+
# this returns the follwing HTML:
|
50
|
+
#
|
51
|
+
# ```html
|
52
|
+
# <tr data-team-id="2">
|
53
|
+
# ```
|
54
|
+
#
|
55
|
+
# @param type Symbol identifying the type of record and the variable to use
|
56
|
+
# @param var the variable to use. This is optional
|
57
|
+
#
|
58
|
+
# @return Hash
|
59
|
+
#
|
60
|
+
#
|
61
|
+
def record_for(record, type = nil)
|
62
|
+
unless type
|
63
|
+
type = record.class.to_s.downcase
|
64
|
+
end
|
65
|
+
"data-#{type}-id=#{record.id}"
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
#
|
70
|
+
# Returns a hash containing the attribute name. This can be used as html options in rails helpers
|
71
|
+
#
|
72
|
+
# example in a form builder block:
|
73
|
+
#
|
74
|
+
# ```ruby
|
75
|
+
# <%= f.text_field :name, attribute_for(:name) %>
|
76
|
+
# ```
|
77
|
+
#
|
78
|
+
# this returns the follwing HTML:
|
79
|
+
#
|
80
|
+
# ```html
|
81
|
+
# <input data-attribute-for="name" id="team_name" name="team[name]" type="text">
|
82
|
+
# ```
|
83
|
+
#
|
84
|
+
# @param name Symbol or String identifying the name
|
85
|
+
#
|
86
|
+
# @return Hash
|
87
|
+
#
|
88
|
+
#
|
60
89
|
def attribute_for(name)
|
61
|
-
Hash[
|
90
|
+
Hash['data-attribute-for', name]
|
62
91
|
end
|
63
92
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
93
|
+
##
|
94
|
+
#
|
95
|
+
# Returns a hash containing the action name. This can be used as html options in rails helpers
|
96
|
+
#
|
97
|
+
# example in a form builder block:
|
98
|
+
#
|
99
|
+
# ```ruby
|
100
|
+
# <%= f.submit "Submit", action_for(:save)%>
|
101
|
+
# ```
|
102
|
+
#
|
103
|
+
# this returns the follwing HTML:
|
104
|
+
#
|
105
|
+
# ```html
|
106
|
+
# <input data-action-for="submit" name="commit" type="submit" value="Submit">
|
107
|
+
# ```
|
108
|
+
#
|
109
|
+
# @param name Symbol or String identifying the action name
|
110
|
+
#
|
111
|
+
# @return Hash
|
112
|
+
#
|
113
|
+
#
|
85
114
|
def action_for(name)
|
86
|
-
|
115
|
+
name = name.to_s
|
116
|
+
name = 'save' if name == 'submit'
|
117
|
+
Hash['data-action-for', name]
|
87
118
|
end
|
88
119
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
120
|
+
|
121
|
+
##
|
122
|
+
#
|
123
|
+
# Returns a hash containing the error name. This can be used as html options in rails helpers
|
124
|
+
#
|
125
|
+
# example:
|
126
|
+
#
|
127
|
+
# TODO: Make an example
|
128
|
+
#
|
129
|
+
#
|
130
|
+
# this returns the follwing HTML:
|
131
|
+
#
|
132
|
+
# ```html
|
133
|
+
# <div data-error-for="name">can't be blank</div>
|
134
|
+
# ```
|
135
|
+
#
|
136
|
+
# @param name Symbol or String identifying the name
|
137
|
+
#
|
138
|
+
# @return Hash
|
139
|
+
#
|
140
|
+
#
|
141
|
+
def error_for(name)
|
142
|
+
Hash['data-error-for', name]
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
##
|
148
|
+
#
|
149
|
+
# Writes a tag containing the specified PageRecord attribute
|
150
|
+
#
|
151
|
+
# example:
|
152
|
+
#
|
153
|
+
# ```ruby
|
154
|
+
# <% @teams.each do |team| %>
|
155
|
+
# <tr>
|
156
|
+
# <%= attribute_tag_for(:td, :name) { team.name} %>
|
157
|
+
# <%= attribute_tag_for(:td, :competition) { team.competition} %>
|
158
|
+
# <%= attribute_tag_for(:td, :point) { team.point} %>
|
159
|
+
# <%= attribute_tag_for(:td, :ranking) { team.ranking} %>
|
160
|
+
# <td><%= link_to 'Show', team, action_for(:show) %></td>
|
161
|
+
# <td><%= link_to 'Edit', edit_team_path(team), action_for(:edit) %></td>
|
162
|
+
# <td><%= link_to 'Destroy', team, {method: :delete, data: { confirm: 'Are you sure?' }}.merge(action_for(:destroy)) %></td>
|
163
|
+
# </tr>
|
164
|
+
# ```
|
165
|
+
#
|
166
|
+
# the first `attribute_tag_for` lines returns the follwing HTML:
|
167
|
+
#
|
168
|
+
# ```html
|
169
|
+
# <td data-attribute-for="name">aa</td>
|
170
|
+
# ```
|
171
|
+
#
|
172
|
+
#
|
173
|
+
# rubocop:disable ParameterLists
|
115
174
|
def attribute_tag_for(name, attribute, content_or_options_with_block = nil, options = nil, escape = true, &block)
|
116
|
-
options||= options ? options << {'data-attribute-for' => attribute} :{'data-attribute-for' => attribute}
|
175
|
+
options ||= options ? options << { 'data-attribute-for' => attribute } : { 'data-attribute-for' => attribute }
|
117
176
|
if block_given?
|
118
177
|
options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
|
119
178
|
content_tag_string(name, capture(&block), options, escape)
|
@@ -121,57 +180,59 @@ module PageRecord
|
|
121
180
|
content_tag_string(name, content_or_options_with_block, options, escape)
|
122
181
|
end
|
123
182
|
end
|
183
|
+
# rubocop:enable ParameterLists
|
124
184
|
|
125
185
|
alias_method :atf, :attribute_tag_for
|
126
186
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
#
|
187
|
+
##
|
188
|
+
#
|
189
|
+
# build a form that automagicaly identifies a form as a PageRecord recognisable form
|
190
|
+
# The form is identified by the id of the given record or `new` if the record is new.
|
191
|
+
#
|
192
|
+
# All the elements in the form are labeled according to there field name. And thus easy
|
193
|
+
# recognisable by PageRecord
|
194
|
+
#
|
195
|
+
# example:
|
196
|
+
#
|
197
|
+
# ```ruby
|
198
|
+
# <%= record_form_for(@team) do |f| %>
|
199
|
+
# <div class="field" >
|
200
|
+
# <%= f.label :name %><br>
|
201
|
+
# <%= f.text_field :name %>
|
202
|
+
# </div>
|
203
|
+
# <div class="field"%>
|
204
|
+
# <%= f.label :competition %><br>
|
205
|
+
# <%= f.text_field :competition%>
|
206
|
+
# </div>
|
207
|
+
# <div class="actions">
|
208
|
+
# <%= f.submit "Submit"%>
|
209
|
+
# </div>
|
210
|
+
# <% end %>
|
211
|
+
# ```
|
212
|
+
# @see
|
213
|
+
#
|
214
|
+
# @return formBuilder object
|
215
|
+
#
|
216
|
+
#
|
158
217
|
def record_form_for(record, options = {}, &block)
|
159
218
|
case record
|
160
219
|
when String, Symbol
|
161
220
|
object_name = record
|
162
221
|
else
|
163
222
|
object = record.is_a?(Array) ? record.last : record
|
164
|
-
raise ArgumentError,
|
223
|
+
raise ArgumentError, 'First argument in form cannot contain nil or be empty' unless object
|
165
224
|
object_name = options[:as] || model_name_from_record_or_class(object).param_key
|
166
225
|
end
|
167
|
-
options = options.merge(html:form_record_for(object_name), builder:PageRecord::FormBuilder)
|
226
|
+
options = options.merge(html: form_record_for(object_name), builder: PageRecord::FormBuilder)
|
168
227
|
form_for(record, options, &block)
|
169
228
|
end
|
170
229
|
end
|
171
230
|
|
172
231
|
end
|
173
232
|
|
233
|
+
# rubocop:disable HandleExceptions
|
174
234
|
begin
|
175
|
-
|
235
|
+
ActionView::Base.send :include, PageRecord::Helpers
|
176
236
|
rescue NameError
|
177
237
|
end
|
238
|
+
# rubocop:enable HandleExceptions
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PageRecord
|
2
|
+
|
3
|
+
module Inspector
|
4
|
+
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
def inspect
|
11
|
+
attributes = Hash.new
|
12
|
+
self.class.attributes.each do | attribute|
|
13
|
+
begin
|
14
|
+
attributes[attribute] = self.send(attribute)
|
15
|
+
rescue AttributeNotFound
|
16
|
+
attributes[attribute] = '--not found on page--'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
def inspect
|
25
|
+
{
|
26
|
+
type: self.type,
|
27
|
+
host_class: self.host_class,
|
28
|
+
selector: self.selector,
|
29
|
+
filter: self.filter,
|
30
|
+
attributes: self.attributes,
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -1,52 +1,50 @@
|
|
1
1
|
module PageRecord
|
2
|
-
|
2
|
+
class Base
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
4
|
+
##
|
5
|
+
# This is the implementation of the record action routine. It has two variants.
|
6
|
+
# it has a `?` variant and a `normal` variant.
|
7
|
+
#
|
8
|
+
# normal variant:
|
9
|
+
# It checks the page for a data-action-for='action' tag somewhere on the page.
|
10
|
+
# If it finds it, it clicks it.
|
11
|
+
#
|
12
|
+
# `?` variant:
|
13
|
+
# It checks the page for a data-action-for='action' tag somewhere on the page.
|
14
|
+
# If it finds it, returns the Capybara element.
|
15
|
+
#
|
16
|
+
# @param action [Symbol] this is the name of the action
|
17
|
+
#
|
18
|
+
# @return [Capybara::Result]
|
19
|
+
#
|
20
|
+
# @raise [PageRecord::MultipleRecords] when there are more actions with
|
21
|
+
# this name on the page
|
22
|
+
#
|
23
|
+
def method_missing(action)
|
24
|
+
raw_action = /(.*)\?/.match(action)
|
25
|
+
begin
|
26
|
+
if raw_action
|
27
|
+
action_for?(raw_action[1])
|
28
|
+
else
|
29
|
+
action_for(action)
|
30
|
+
end
|
31
|
+
rescue Capybara::ElementNotFound
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
35
|
|
36
|
+
private
|
36
37
|
|
37
|
-
|
38
|
+
# @private
|
39
|
+
def action_for(action)
|
40
|
+
element = action_for?(action)
|
41
|
+
element.click
|
42
|
+
element
|
43
|
+
end
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
# @private
|
47
|
-
def action_for?(action)
|
48
|
-
@record.find("[data-action-for='#{action}']")
|
49
|
-
end
|
50
|
-
end
|
45
|
+
# @private
|
46
|
+
def action_for?(action)
|
47
|
+
@record.find("[data-action-for='#{action}']")
|
48
|
+
end
|
49
|
+
end
|
51
50
|
end
|
52
|
-
|
data/lib/page_record/rspec.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module PageRecord
|
4
|
+
class Base
|
5
|
+
##
|
6
|
+
# Searches the record for any errors and returns them
|
7
|
+
#
|
8
|
+
# @return [ActiveModel::Errors] the error object for the current record
|
9
|
+
#
|
10
|
+
# @raise [AttributeNotFound] when the attribute is not found in the record
|
11
|
+
#
|
12
|
+
def errors
|
13
|
+
found_errors = @record.all("[data-error-for]")
|
14
|
+
error_list = ActiveModel::Errors.new(self)
|
15
|
+
found_errors.each do | error |
|
16
|
+
attribute = error['data-error-for']
|
17
|
+
message = error.text
|
18
|
+
error_list.add(attribute, message)
|
19
|
+
end
|
20
|
+
error_list
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Returns true of there are no errors on the current record
|
25
|
+
#
|
26
|
+
# @return bool
|
27
|
+
#
|
28
|
+
# @raise [AttributeNotFound] when the attribute is not found in the record
|
29
|
+
#
|
30
|
+
def valid?
|
31
|
+
errors.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Returns true of there are errors on the current record
|
36
|
+
#
|
37
|
+
# @return bool
|
38
|
+
#
|
39
|
+
# @raise [AttributeNotFound] when the attribute is not found in the record
|
40
|
+
#
|
41
|
+
def invalid?
|
42
|
+
!valid?
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/page_record/version.rb
CHANGED
data/lib/page_record.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
require 'active_support/core_ext'
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
2
|
+
require 'page_record/version'
|
3
|
+
require 'page_record/inspector'
|
4
|
+
require 'page_record/base'
|
5
|
+
require 'page_record/finders'
|
6
|
+
require 'page_record/instance_actions'
|
7
|
+
require 'page_record/attribute_accessors'
|
8
|
+
require 'page_record/class_actions'
|
9
|
+
require 'page_record/class_methods'
|
10
|
+
require 'page_record/errors'
|
11
|
+
require 'page_record/validation'
|
10
12
|
if defined?(ActionView::Base)
|
11
|
-
|
12
|
-
|
13
|
+
require 'page_record/helpers'
|
14
|
+
require 'page_record/form_builder'
|
13
15
|
end
|
14
|
-
if defined?(Formtastic::Helpers::FormHelper)
|
15
|
-
require "page_record/formtastic"
|
16
|
-
end
|
17
|
-
|
18
|
-
|
16
|
+
require 'page_record/formtastic' if defined?(Formtastic::Helpers::FormHelper)
|
19
17
|
|
data/page_record.gemspec
CHANGED
@@ -25,8 +25,11 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "sinatra"
|
26
26
|
spec.add_development_dependency "actionpack"
|
27
27
|
spec.add_development_dependency "activerecord"
|
28
|
+
spec.add_development_dependency "guard-rspec"
|
29
|
+
spec.add_development_dependency "ruby_gntp"
|
28
30
|
# spec.add_development_dependency "debugger"
|
29
31
|
|
30
32
|
spec.add_dependency "capybara" , '~>2.1.0'
|
31
33
|
spec.add_dependency "activesupport"
|
32
|
-
|
34
|
+
spec.add_dependency "activemodel"
|
35
|
+
end
|
data/spec/.rubocop.yml
ADDED