ninetails 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +19 -0
- data/app/components/ninetails/element.rb +55 -0
- data/app/components/ninetails/element_definition.rb +67 -0
- data/app/components/ninetails/property.rb +11 -0
- data/app/components/ninetails/property_store.rb +22 -0
- data/app/components/ninetails/property_type.rb +27 -0
- data/app/components/ninetails/section_template.rb +66 -0
- data/app/controllers/ninetails/application_controller.rb +4 -0
- data/app/controllers/ninetails/page_revisions_controller.rb +31 -0
- data/app/controllers/ninetails/pages_controller.rb +14 -0
- data/app/controllers/ninetails/section_templates_controller.rb +17 -0
- data/app/models/ninetails/page.rb +37 -0
- data/app/models/ninetails/page_revision.rb +28 -0
- data/app/models/ninetails/page_revision_section.rb +6 -0
- data/app/models/ninetails/section.rb +30 -0
- data/config/initializers/error_classes.rb +4 -0
- data/config/initializers/json_stuff.rb +9 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20151006093040_create_pages.rb +10 -0
- data/db/migrate/20151006093559_create_page_revisions.rb +8 -0
- data/db/migrate/20151006093754_create_sections.rb +11 -0
- data/db/migrate/20151006094337_create_page_revision_sections.rb +8 -0
- data/db/migrate/20151111085201_add_message_to_page_revisions.rb +5 -0
- data/db/schema.rb +53 -0
- data/lib/ninetails.rb +4 -0
- data/lib/ninetails/engine.rb +37 -0
- data/lib/ninetails/version.rb +3 -0
- data/lib/tasks/ninetails_tasks.rake +8 -0
- data/spec/components/element_definition_spec.rb +104 -0
- data/spec/components/element_spec.rb +92 -0
- data/spec/components/property_spec.rb +34 -0
- data/spec/components/property_store_spec.rb +64 -0
- data/spec/components/property_type_spec.rb +69 -0
- data/spec/components/section_spec.rb +72 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/components/element/button.rb +7 -0
- data/spec/dummy/app/components/element/button_icon.rb +8 -0
- data/spec/dummy/app/components/element/figure.rb +7 -0
- data/spec/dummy/app/components/element/meta.rb +7 -0
- data/spec/dummy/app/components/element/text.rb +7 -0
- data/spec/dummy/app/components/property/icon.rb +8 -0
- data/spec/dummy/app/components/property/image.rb +10 -0
- data/spec/dummy/app/components/property/link.rb +11 -0
- data/spec/dummy/app/components/property/text.rb +8 -0
- data/spec/dummy/app/components/section_template/billboard.rb +14 -0
- data/spec/dummy/app/components/section_template/document_head.rb +10 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +35 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +12 -0
- data/spec/dummy/config/database.yml.travis +4 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/schema.rb +53 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/page_revisions.rb +8 -0
- data/spec/factories/pages.rb +25 -0
- data/spec/factories/sections.rb +15 -0
- data/spec/models/page_revision_spec.rb +5 -0
- data/spec/models/page_spec.rb +26 -0
- data/spec/models/section_spec.rb +113 -0
- data/spec/rails_helper.rb +60 -0
- data/spec/requests/page_revisions_spec.rb +117 -0
- data/spec/requests/pages_spec.rb +68 -0
- data/spec/requests/section_templates_spec.rb +17 -0
- data/spec/spec_helper.rb +98 -0
- data/spec/support/factory_girl.rb +5 -0
- data/spec/support/request_helpers.rb +9 -0
- data/spec/support/shared_examples.rb +34 -0
- metadata +378 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class NoPropertiesDefined
|
|
4
|
+
include Ninetails::PropertyStore
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class SomeProperties
|
|
8
|
+
include Ninetails::PropertyStore
|
|
9
|
+
property :text, Property::Text
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class PropertiesWithValidations
|
|
13
|
+
include Ninetails::PropertyStore
|
|
14
|
+
property :text, String
|
|
15
|
+
validates :text, presence: true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe Ninetails::PropertyStore do
|
|
19
|
+
|
|
20
|
+
it "should expose a list of properties on the class" do
|
|
21
|
+
expect(NoPropertiesDefined).to respond_to :properties
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should have an empty array of properties to begin with" do
|
|
25
|
+
expect(NoPropertiesDefined.properties).to eq []
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should store properties using Ninetails::PropertyType" do
|
|
29
|
+
expect(SomeProperties.properties.first).to be_a Ninetails::PropertyType
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should store the name of a defined property" do
|
|
33
|
+
expect(SomeProperties.properties.first.name).to eq :text
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should store the type of a defined property" do
|
|
37
|
+
expect(SomeProperties.properties.first.type).to eq Property::Text
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should store the property as a virtus attribute" do
|
|
41
|
+
virtus_attr = SomeProperties.attribute_set.first
|
|
42
|
+
expect(virtus_attr.name).to eq :text
|
|
43
|
+
expect(virtus_attr.primitive).to eq Property::Text
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "validations" do
|
|
47
|
+
|
|
48
|
+
let(:prop) { PropertiesWithValidations.new text: nil }
|
|
49
|
+
|
|
50
|
+
before do
|
|
51
|
+
prop.valid? # run validations
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should be possible to validate the propery group" do
|
|
55
|
+
expect(prop.valid?).to be false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should list errors using ActiveModel::Errors" do
|
|
59
|
+
expect(prop.errors.size).to eq 1
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class TextProperty
|
|
4
|
+
include Ninetails::PropertyStore
|
|
5
|
+
property :text, String
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe Ninetails::PropertyType do
|
|
9
|
+
|
|
10
|
+
let(:string_property) { Ninetails::PropertyType.new :foo, String }
|
|
11
|
+
let(:text_property) { Ninetails::PropertyType.new :foo, TextProperty }
|
|
12
|
+
|
|
13
|
+
it "should be initializable with name and type" do
|
|
14
|
+
expect(string_property.name).to eq :foo
|
|
15
|
+
expect(string_property.type).to eq String
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "serializing" do
|
|
19
|
+
it "should be a new instance of the type when the type does not respond to #structure" do
|
|
20
|
+
expect(string_property.serialize).to eq ""
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should use the structure when the type responds to #structure" do
|
|
24
|
+
allow(String).to receive(:respond_to?) { true }
|
|
25
|
+
allow(String).to receive(:serialize) { "HELLO" }
|
|
26
|
+
expect(string_property.serialize).to eq "HELLO"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should initialize a new instance of the type with the serialized_values attribute as an argument" do
|
|
30
|
+
string_property.serialized_values = "123"
|
|
31
|
+
expect(string_property.serialize).to eq "123"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "property" do
|
|
36
|
+
it "should be set to a new instance of the property type" do
|
|
37
|
+
expect(string_property.property).to be_a String
|
|
38
|
+
expect(text_property.property).to be_a TextProperty
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "handling serialized values" do
|
|
43
|
+
it "should be nil when initializing a Ninetails::PropertyType" do
|
|
44
|
+
expect(string_property.serialized_values).to eq nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should be possible to set" do
|
|
48
|
+
string_property.serialized_values = "foobar"
|
|
49
|
+
expect(string_property.serialized_values).to eq "foobar"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should raise a TypeError if you try to set the wrong type" do
|
|
53
|
+
expect {
|
|
54
|
+
string_property.serialized_values = { foo: "bar" }
|
|
55
|
+
}.to raise_error(TypeError)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should be possible to set with a hash if the property conforms to the Ninetails::PropertyStore" do
|
|
59
|
+
text_property.serialized_values = { text: "hello" }
|
|
60
|
+
expect(text_property.serialized_values).to eq({ text: "hello" })
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should use the serialized_values to reinitialize the property" do
|
|
64
|
+
text_property.serialized_values = { text: "hello" }
|
|
65
|
+
expect(text_property.property.text).to eq "hello"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
class ExampleSection < Ninetails::SectionTemplate
|
|
4
|
+
located_in :body
|
|
5
|
+
has_element :foo, Element::Text
|
|
6
|
+
has_element :bar, Element::Button
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
RSpec.describe Ninetails::SectionTemplate do
|
|
10
|
+
|
|
11
|
+
describe "position" do
|
|
12
|
+
it "should be possible to set" do
|
|
13
|
+
expect(ExampleSection.position).to eq :body
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should raise an exception if the position is not one of head or body" do
|
|
17
|
+
expect{ ExampleSection.located_in(:a_cave) }.to raise_error(Ninetails::SectionConfigurationError)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "elements" do
|
|
22
|
+
it "should store elements as a Array" do
|
|
23
|
+
expect(ExampleSection.elements).to be_a Array
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should store the element names" do
|
|
27
|
+
expect(ExampleSection.elements[0].name).to eq :foo
|
|
28
|
+
expect(ExampleSection.elements[1].name).to eq :bar
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should store the element types" do
|
|
32
|
+
expect(ExampleSection.elements[0].type).to eq Element::Text
|
|
33
|
+
expect(ExampleSection.elements[1].type).to eq Element::Button
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "elements structure" do
|
|
38
|
+
before do
|
|
39
|
+
# Mock SecureRandom so we can reliably compare property strucures without worrying about
|
|
40
|
+
# references which don't match
|
|
41
|
+
allow(SecureRandom).to receive(:uuid) { "123" }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
let(:structure) { ExampleSection.new.serialize_elements }
|
|
45
|
+
|
|
46
|
+
it "should be a hash" do
|
|
47
|
+
expect(structure).to be_a(Hash)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should have the property structure for each element" do
|
|
51
|
+
expect(structure[:foo]).to eq Ninetails::ElementDefinition.new(:bogus, Element::Text, :single).properties_structure
|
|
52
|
+
expect(structure[:bar]).to eq Ninetails::ElementDefinition.new(:bogus, Element::Button, :single).properties_structure
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "structure" do
|
|
57
|
+
let(:structure) { ExampleSection.new.serialize }
|
|
58
|
+
|
|
59
|
+
it "should have a type key which is the section class name" do
|
|
60
|
+
expect(structure[:type]).to eq "ExampleSection"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should include the position in tags" do
|
|
64
|
+
expect(structure[:tags][:position]).to eq ExampleSection.position
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should have an elements key which contains the section's elements" do
|
|
68
|
+
expect(structure[:elements]).to eq ExampleSection.new.serialize_elements
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
data/spec/dummy/Rakefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module SectionTemplate
|
|
2
|
+
class Billboard < Ninetails::SectionTemplate
|
|
3
|
+
|
|
4
|
+
located_in :body
|
|
5
|
+
|
|
6
|
+
has_element :title, Element::Text
|
|
7
|
+
has_element :background_image, Element::Figure
|
|
8
|
+
has_element :signup_button, Element::Button
|
|
9
|
+
|
|
10
|
+
has_many_elements :supported_card_icons, Element::Figure
|
|
11
|
+
has_many_elements :supported_device_icons, Element::Figure
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end
|
data/spec/dummy/bin/rake
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'pathname'
|
|
3
|
+
|
|
4
|
+
# path to your application root.
|
|
5
|
+
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
|
|
6
|
+
|
|
7
|
+
Dir.chdir APP_ROOT do
|
|
8
|
+
# This script is a starting point to setup your application.
|
|
9
|
+
# Add necessary setup steps to this file:
|
|
10
|
+
|
|
11
|
+
puts "== Installing dependencies =="
|
|
12
|
+
system "gem install bundler --conservative"
|
|
13
|
+
system "bundle check || bundle install"
|
|
14
|
+
|
|
15
|
+
# puts "\n== Copying sample files =="
|
|
16
|
+
# unless File.exist?("config/database.yml")
|
|
17
|
+
# system "cp config/database.yml.sample config/database.yml"
|
|
18
|
+
# end
|
|
19
|
+
|
|
20
|
+
puts "\n== Preparing database =="
|
|
21
|
+
system "bin/rake db:setup"
|
|
22
|
+
|
|
23
|
+
puts "\n== Removing old logs and tempfiles =="
|
|
24
|
+
system "rm -f log/*"
|
|
25
|
+
system "rm -rf tmp/cache"
|
|
26
|
+
|
|
27
|
+
puts "\n== Restarting application server =="
|
|
28
|
+
system "touch tmp/restart.txt"
|
|
29
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
|
2
|
+
|
|
3
|
+
require 'rails/all'
|
|
4
|
+
|
|
5
|
+
Bundler.require(*Rails.groups)
|
|
6
|
+
require "ninetails"
|
|
7
|
+
|
|
8
|
+
module Dummy
|
|
9
|
+
class Application < Rails::Application
|
|
10
|
+
# Settings in config/environments/* take precedence over those specified here.
|
|
11
|
+
# Application configuration should go into files in config/initializers
|
|
12
|
+
# -- all .rb files in that directory are automatically loaded.
|
|
13
|
+
|
|
14
|
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
|
15
|
+
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
|
16
|
+
# config.time_zone = 'Central Time (US & Canada)'
|
|
17
|
+
|
|
18
|
+
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
|
19
|
+
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
|
20
|
+
# config.i18n.default_locale = :de
|
|
21
|
+
|
|
22
|
+
# Do not swallow errors in after_commit/after_rollback callbacks.
|
|
23
|
+
config.active_record.raise_in_transactional_callbacks = true
|
|
24
|
+
|
|
25
|
+
config.autoload_paths += [
|
|
26
|
+
"#{config.root}/app/components"
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
config.eager_load_paths = [
|
|
30
|
+
Rails.root.join("app/controllers").to_s,
|
|
31
|
+
Rails.root.join("app/components").to_s,
|
|
32
|
+
Rails.root.join("app/models").to_s
|
|
33
|
+
]
|
|
34
|
+
end
|
|
35
|
+
end
|