page_record 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.rubocop.yml +13 -0
  2. data/CHANGES.md +5 -0
  3. data/Gemfile.lock +46 -14
  4. data/Guardfile +24 -0
  5. data/README.md +27 -1
  6. data/bin/autospec +16 -0
  7. data/bin/guard +16 -0
  8. data/bin/rake +16 -0
  9. data/bin/rspec +16 -0
  10. data/lib/page_record/attribute_accessors.rb +57 -54
  11. data/lib/page_record/base.rb +27 -22
  12. data/lib/page_record/class_actions.rb +47 -50
  13. data/lib/page_record/class_methods.rb +252 -261
  14. data/lib/page_record/errors.rb +81 -82
  15. data/lib/page_record/finders.rb +129 -131
  16. data/lib/page_record/form_builder.rb +4 -4
  17. data/lib/page_record/formtastic.rb +20 -9
  18. data/lib/page_record/helpers.rb +192 -131
  19. data/lib/page_record/inspector.rb +36 -0
  20. data/lib/page_record/instance_actions.rb +44 -46
  21. data/lib/page_record/rspec.rb +1 -1
  22. data/lib/page_record/validation.rb +46 -0
  23. data/lib/page_record/version.rb +1 -1
  24. data/lib/page_record.rb +13 -15
  25. data/page_record.gemspec +4 -1
  26. data/spec/.rubocop.yml +4 -0
  27. data/spec/helpers_spec.rb +109 -100
  28. data/spec/inspector_spec.rb +70 -0
  29. data/spec/page_record_spec.rb +357 -388
  30. data/spec/spec_helper.rb +1 -3
  31. data/spec/support/shared_contexts.rb +24 -2
  32. data/spec/support/shared_examples.rb +41 -45
  33. data/spec/support/team.rb +4 -4
  34. data/spec/support/test_app.rb +10 -13
  35. data/spec/support/views/page-with-1-error.erb +5 -0
  36. data/spec/support/views/page-with-2-errors-on-different-attributes.erb +9 -0
  37. data/spec/support/views/page-with-2-errors-on-same-attribute.erb +6 -0
  38. data/spec/support/views/page-without-errors.erb +4 -0
  39. data/spec/validation_spec.rb +142 -0
  40. data/tmp/rspec_guard_result +1 -0
  41. metadata +80 -5
@@ -2,118 +2,177 @@ module PageRecord
2
2
 
3
3
  module Helpers
4
4
 
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)
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
- # Returns a hash containing the attribute name. This can be used as html options in rails helpers
42
- #
43
- # example in a form builder block:
44
- #
45
- # ```ruby
46
- #<%= f.text_field :name, attribute_for(:name) %>
47
- # ```
48
- #
49
- # this returns the follwing HTML:
50
- #
51
- # ```html
52
- # <input data-attribute-for="name" id="team_name" name="team[name]" type="text">
53
- # ```
54
- #
55
- # @param name Symbol or String identifying the name
56
- #
57
- # @return Hash
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["data-attribute-for",name]
90
+ Hash['data-attribute-for', name]
62
91
  end
63
92
 
64
- ##
65
- #
66
- # Returns a hash containing the action name. This can be used as html options in rails helpers
67
- #
68
- # example in a form builder block:
69
- #
70
- # ```ruby
71
- # <%= f.submit "Submit", action_for(:save)%>
72
- # ```
73
- #
74
- # this returns the follwing HTML:
75
- #
76
- # ```html
77
- # <input data-action-for="submit" name="commit" type="submit" value="Submit">
78
- # ```
79
- #
80
- # @param name Symbol or String identifying the action name
81
- #
82
- # @return Hash
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
- Hash["data-action-for",name]
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
- # Writes a tag containing the specified PageRecord attribute
92
- #
93
- # example:
94
- #
95
- # ```ruby
96
- # <% @teams.each do |team| %>
97
- # <tr>
98
- # <%= attribute_tag_for(:td, :name) { team.name} %>
99
- # <%= attribute_tag_for(:td, :competition) { team.competition} %>
100
- # <%= attribute_tag_for(:td, :point) { team.point} %>
101
- # <%= attribute_tag_for(:td, :ranking) { team.ranking} %>
102
- # <td><%= link_to 'Show', team, action_for(:show) %></td>
103
- # <td><%= link_to 'Edit', edit_team_path(team), action_for(:edit) %></td>
104
- # <td><%= link_to 'Destroy', team, {method: :delete, data: { confirm: 'Are you sure?' }}.merge(action_for(:destroy)) %></td>
105
- # </tr>
106
- # ```
107
- #
108
- # the first `attribute_tag_for` lines returns the follwing HTML:
109
- #
110
- # ```html
111
- #<td data-attribute-for="name">aa</td>
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
- # build a form that automagicaly identifies a form as a PageRecord recognisable form
131
- # The form is identified by the id of the given record or `new` if the record is new.
132
- #
133
- # All the elements in the form are labeled according to there field name. And thus easy
134
- # recognisable by PageRecord
135
- #
136
- # example:
137
- #
138
- # ```ruby
139
- # <%= record_form_for(@team) do |f| %>
140
- # <div class="field" >
141
- # <%= f.label :name %><br>
142
- # <%= f.text_field :name %>
143
- # </div>
144
- # <div class="field"%>
145
- # <%= f.label :competition %><br>
146
- # <%= f.text_field :competition%>
147
- # </div>
148
- # <div class="actions">
149
- # <%= f.submit "Submit"%>
150
- # </div>
151
- # <% end %>
152
- # ```
153
- # @see
154
- #
155
- # @return formBuilder object
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, "First argument in form cannot contain nil or be empty" unless object
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
- ActionView::Base.send :include, PageRecord::Helpers
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
- class Base
2
+ class Base
3
3
 
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
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
- private
38
+ # @private
39
+ def action_for(action)
40
+ element = action_for?(action)
41
+ element.click
42
+ element
43
+ end
38
44
 
39
- # @private
40
- def action_for(action)
41
- element = action_for?(action)
42
- element.click
43
- element
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
-
@@ -1,7 +1,7 @@
1
1
  require 'page_record'
2
2
 
3
3
  RSpec.configure do |config|
4
- config.before(:each) do
4
+ config.before(:each) do
5
5
  PageRecord::Base.page session
6
6
  end
7
7
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module PageRecord
2
- VERSION = "0.4.0"
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/page_record.rb CHANGED
@@ -1,19 +1,17 @@
1
1
  require 'active_support/core_ext'
2
- require "page_record/version"
3
- require "page_record/base"
4
- require "page_record/finders"
5
- require "page_record/instance_actions"
6
- require "page_record/attribute_accessors"
7
- require "page_record/class_actions"
8
- require "page_record/class_methods"
9
- require "page_record/errors"
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
- require "page_record/helpers"
12
- require "page_record/form_builder"
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
- end
34
+ spec.add_dependency "activemodel"
35
+ end
data/spec/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ inherit_from: ../.rubocop.yml
2
+
3
+ StringLiterals:
4
+ Enabled: false