ninetails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|