cookbook 0.1.5 → 0.1.6
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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/app/assets/javascript/cookbook/addFields.js +41 -0
- data/app/assets/javascript/cookbook/application.js +2 -0
- data/app/assets/javascript/cookbook/removeFields.js +36 -0
- data/app/helpers/cookbook/application_helper.rb +39 -0
- data/app/views/cookbook/_fields.html.haml +3 -3
- data/app/views/cookbook/_use_fields.html.haml +22 -0
- data/cookbook.gemspec +6 -3
- data/lib/cookbook.rb +0 -1
- data/spec/dummy/app/javascript/packs/application.js +1 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +1788 -0
- data/spec/dummy/log/test.log +2447 -0
- data/spec/requests/how_tos_spec.rb +3 -3
- data/spec/requests/recipes_spec.rb +3 -3
- metadata +5 -2
- data/app/views/cookbook/uses/_fields.html.haml +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2959709e5e50fec64984caac992b47de183442c12ce5388b37d476434e1155dc
|
4
|
+
data.tar.gz: 0b8861cf190ec4da06ac43dc6dee23ccc360c2251a427e4a7fcfc9369b32283f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc961bc7d3a9396de7265eeb271b17ff4c500b6c4c40f5187bfa721702017c7fdf0c70ca453951d792cf5fbf1ea1ada3753548bfedce74e517331be5cb8d13be
|
7
|
+
data.tar.gz: 41ceed87fb03aa183e10f4e1ddab2e2de7e147343d7af48a0dc225dcfd38878aca4ecc727e223986ed6aa146a8469c799f61745c2d938c9c1c9c7099bba64a62
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class addFields {
|
2
|
+
// This executes when the function is instantiated.
|
3
|
+
constructor() {
|
4
|
+
this.links = document.querySelectorAll('.add_fields')
|
5
|
+
this.iterateLinks()
|
6
|
+
}
|
7
|
+
|
8
|
+
iterateLinks() {
|
9
|
+
// If there are no links on the page, stop the function from executing.
|
10
|
+
if (this.links.length === 0) return
|
11
|
+
// Loop over each link on the page. A page could have multiple nested forms.
|
12
|
+
this.links.forEach(link => {
|
13
|
+
link.addEventListener('click', e => {
|
14
|
+
this.handleClick(link, e)
|
15
|
+
})
|
16
|
+
})
|
17
|
+
}
|
18
|
+
|
19
|
+
handleClick(link, e) {
|
20
|
+
// Stop the function from executing if a link or event were not passed into the function.
|
21
|
+
if (!link || !e) return
|
22
|
+
// Prevent the browser from following the URL.
|
23
|
+
e.preventDefault()
|
24
|
+
// Save a unique timestamp to ensure the key of the associated array is unique.
|
25
|
+
let time = new Date().getTime()
|
26
|
+
// Save the data id attribute into a variable. This corresponds to `new_object.object_id`.
|
27
|
+
let linkId = link.dataset.id
|
28
|
+
// Create a new regular expression needed to find any instance of the `new_object.object_id` used in the fields data attribute if there's a value in `linkId`.
|
29
|
+
let regexp = linkId ? new RegExp(linkId, 'g') : null
|
30
|
+
// Replace all instances of the `new_object.object_id` with `time`, and save markup into a variable if there's a value in `regexp`.
|
31
|
+
let newFields = regexp ? link.dataset.fields.replace(regexp, time) : null
|
32
|
+
// Add the new markup to the form if there are fields to add.
|
33
|
+
newFields ? link.insertAdjacentHTML('beforebegin', newFields) : null
|
34
|
+
// Tell it new fields are there
|
35
|
+
const event = new Event('cookbook:add_fields')
|
36
|
+
window.dispatchEvent(event);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
// Wait for turbolinks to load, otherwise `document.querySelectorAll()` won't work
|
41
|
+
window.addEventListener('load', () => new addFields())
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class removeFields {
|
2
|
+
// This executes when the function is instantiated.
|
3
|
+
constructor() {
|
4
|
+
this.iterateLinks()
|
5
|
+
}
|
6
|
+
|
7
|
+
iterateLinks() {
|
8
|
+
document.querySelectorAll('.remove_fields').forEach(link => {
|
9
|
+
link.addEventListener('click', e => {
|
10
|
+
this.handleClick(link, e)
|
11
|
+
})
|
12
|
+
})
|
13
|
+
}
|
14
|
+
|
15
|
+
handleClick(link, e) {
|
16
|
+
// Stop the function from executing if a link or event were not passed into the function.
|
17
|
+
if (!link || !e) return
|
18
|
+
// Prevent the browser from following the URL.
|
19
|
+
e.preventDefault()
|
20
|
+
// Find the parent wrapper for the set of nested fields.
|
21
|
+
let fieldParent = link.closest('.nested-fields')
|
22
|
+
// If there is a parent wrapper, find the hidden delete field.
|
23
|
+
let deleteField = fieldParent
|
24
|
+
? fieldParent.querySelector('input[type="hidden"]')
|
25
|
+
: null
|
26
|
+
// If there is a delete field, update the value to `1` and hide the corresponding nested fields.
|
27
|
+
if (deleteField) {
|
28
|
+
deleteField.value = 1
|
29
|
+
fieldParent.style.display = 'none'
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
// Wait for turbolinks to load, otherwise `document.querySelectorAll()` won't work
|
35
|
+
window.addEventListener('load', () => new removeFields())
|
36
|
+
window.addEventListener('cookbook:add_fields', () => new removeFields())
|
@@ -15,6 +15,45 @@ module Cookbook
|
|
15
15
|
render 'cookbook/fields', form: form, usables: build_usables(form.object)
|
16
16
|
end
|
17
17
|
|
18
|
+
# This method creates a link with `data-id` `data-fields` attributes. These attributes are used to create new instances of the nested fields through Javascript.
|
19
|
+
def cookbook_link_to_add_fields(name, f, association, partial = nil)
|
20
|
+
|
21
|
+
# Takes an object (@person) and creates a new instance of its associated model (:addresses)
|
22
|
+
# To better understand, run the following in your terminal:
|
23
|
+
# rails c --sandbox
|
24
|
+
# @person = Person.new
|
25
|
+
# new_object = @person.send(:addresses).klass.new
|
26
|
+
new_object = f.object.send(association).klass.new
|
27
|
+
|
28
|
+
# Saves the unique ID of the object into a variable.
|
29
|
+
# This is needed to ensure the key of the associated array is unique. This is makes parsing the content in the `data-fields` attribute easier through Javascript.
|
30
|
+
# We could use another method to achive this.
|
31
|
+
id = new_object.object_id
|
32
|
+
|
33
|
+
# https://api.rubyonrails.org/ fields_for(record_name, record_object = nil, fields_options = {}, &block)
|
34
|
+
# record_name = :addresses
|
35
|
+
# record_object = new_object
|
36
|
+
# fields_options = { child_index: id }
|
37
|
+
# child_index` is used to ensure the key of the associated array is unique, and that it matched the value in the `data-id` attribute.
|
38
|
+
# `person[addresses_attributes][child_index_value][_destroy]`
|
39
|
+
fields = f.fields_for(association, new_object, child_index: id) do |builder|
|
40
|
+
|
41
|
+
# `association.to_s.singularize + "_fields"` ends up evaluating to `address_fields`
|
42
|
+
# The render function will then look for `views/people/_address_fields.html.erb`
|
43
|
+
# The render function also needs to be passed the value of 'builder', because `views/people/_address_fields.html.erb` needs this to render the form tags.
|
44
|
+
partial.nil? ? render(association.to_s.singularize + "_fields", f: builder) : render(partial, f: builder)
|
45
|
+
end
|
46
|
+
|
47
|
+
# This renders a simple link, but passes information into `data` attributes.
|
48
|
+
# This info can be named anything we want, but in this case we chose `data-id:` and `data-fields:`.
|
49
|
+
# The `id:` is from `new_object.object_id`.
|
50
|
+
# The `fields:` are rendered from the `fields` blocks.
|
51
|
+
# We use `gsub("\n", "")` to remove anywhite space from the rendered partial.
|
52
|
+
# The `id:` value needs to match the value used in `child_index: id`.
|
53
|
+
link_to(name, '#', class: "add_fields button button-action", data: {id: id, fields: fields.gsub("\n", "")})
|
54
|
+
|
55
|
+
end
|
56
|
+
|
18
57
|
private
|
19
58
|
|
20
59
|
def build_usables(object)
|
@@ -1,11 +1,11 @@
|
|
1
|
-
= javascript_include_tag '
|
1
|
+
= javascript_include_tag 'cookbook/application'
|
2
2
|
- if Cookbook.configuration.include_cookbook_css == true
|
3
3
|
= stylesheet_link_tag 'cookbook/application'
|
4
4
|
- usables.each do |usable|
|
5
5
|
%fieldset.used_in{class: usable.plural_class}
|
6
6
|
%legend
|
7
7
|
%h3= usable.title
|
8
|
-
= link_to_add_nested form, usable.uses_sym, "##{usable.plural_class}", partial: 'cookbook/uses/fields', link_text: "Add #{usable.singular_title}", link_classes: 'button button-action'
|
9
8
|
%div{id: usable.plural_class}
|
10
9
|
= form.fields_for usable.uses_sym do |g|
|
11
|
-
= render 'cookbook/
|
10
|
+
= render 'cookbook/use_fields', f: g, usable: usable
|
11
|
+
= cookbook_link_to_add_fields "Add #{usable.singular_title}", form, usable.uses_sym, 'cookbook/use_fields'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
%fieldset.nested-fields
|
2
|
+
:ruby
|
3
|
+
table_sym = f.object_name.gsub(/[^\[]+\[([^\]]+)_uses_attributes\].*/, "\\1").pluralize
|
4
|
+
model = table_sym.to_s.classify.constantize
|
5
|
+
collection = if Cookbook.configuration.authorize_with == :cancancan
|
6
|
+
model.accessible_by(current_ability, :select)
|
7
|
+
else
|
8
|
+
model.all
|
9
|
+
end
|
10
|
+
%legend
|
11
|
+
%h4
|
12
|
+
= model.model_name.human
|
13
|
+
= f.hidden_field :_destroy
|
14
|
+
= f.hidden_field :use_of_type, value: model.model_name.to_s
|
15
|
+
= f.input :use_of_id, collection: collection, as: :select, label_method: model.label_method, value_method: :id, selected: f.object.use_of_id, include_blank: "Select #{model.model_name.human}"
|
16
|
+
= f.input :quantity_minimum
|
17
|
+
= f.input :quantity_maximum
|
18
|
+
= f.input :unit
|
19
|
+
= f.input :sort
|
20
|
+
= f.input :preparation, hint: 'like "crushed" or "greased"'
|
21
|
+
= f.input :note, hint: 'like "to taste"'
|
22
|
+
= link_to "Remove", '#', class: 'remove_fields button button-danger'
|
data/cookbook.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: cookbook 0.1.
|
5
|
+
# stub: cookbook 0.1.6 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "cookbook".freeze
|
9
|
-
s.version = "0.1.
|
9
|
+
s.version = "0.1.6"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.metadata = { "source_code_uri" => "http://github.com/gemvein/cookbook" } if s.respond_to? :metadata=
|
@@ -30,14 +30,17 @@ Gem::Specification.new do |s|
|
|
30
30
|
"README.md",
|
31
31
|
"Rakefile",
|
32
32
|
"VERSION",
|
33
|
+
"app/assets/javascript/cookbook/addFields.js",
|
34
|
+
"app/assets/javascript/cookbook/application.js",
|
35
|
+
"app/assets/javascript/cookbook/removeFields.js",
|
33
36
|
"app/assets/stylesheets/cookbook/application.scss",
|
34
37
|
"app/controllers/concerns/cookbook/params.rb",
|
35
38
|
"app/helpers/cookbook/application_helper.rb",
|
36
39
|
"app/models/cookbook/use.rb",
|
37
40
|
"app/views/cookbook/_fields.html.haml",
|
41
|
+
"app/views/cookbook/_use_fields.html.haml",
|
38
42
|
"app/views/cookbook/_used_in.html.haml",
|
39
43
|
"app/views/cookbook/_uses_of.html.haml",
|
40
|
-
"app/views/cookbook/uses/_fields.html.haml",
|
41
44
|
"bin/rails",
|
42
45
|
"config/initializers/simple_form.rb",
|
43
46
|
"config/locales/simple_form.en.yml",
|
data/lib/cookbook.rb
CHANGED
Binary file
|
data/spec/dummy/db/test.sqlite3
CHANGED
Binary file
|