spontaneous 0.2.0.beta9 → 0.2.0.beta10

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -0
  3. data/LICENSE +18 -17
  4. data/Rakefile +1 -1
  5. data/application/css/core.css.scss +1 -1
  6. data/application/css/dialogue.css.scss +8 -20
  7. data/application/js/preview.js +28 -7
  8. data/application/js/publish.js +15 -4
  9. data/application/js/top_bar.js +0 -16
  10. data/application/js/views/piece_view.js +1 -1
  11. data/lib/spontaneous/asset/environment.rb +16 -1
  12. data/lib/spontaneous/box.rb +68 -0
  13. data/lib/spontaneous/capistrano/deploy.rb +7 -4
  14. data/lib/spontaneous/capistrano/sync.rb +2 -2
  15. data/lib/spontaneous/cli/init.rb +70 -19
  16. data/lib/spontaneous/cli/init/db.rb +34 -55
  17. data/lib/spontaneous/cli/init/mysql.rb +5 -5
  18. data/lib/spontaneous/cli/init/postgresql.rb +8 -9
  19. data/lib/spontaneous/cli/init/sqlite.rb +1 -2
  20. data/lib/spontaneous/cli/migrate.rb +0 -1
  21. data/lib/spontaneous/cli/site.rb +4 -0
  22. data/lib/spontaneous/collections/entry_set.rb +11 -0
  23. data/lib/spontaneous/data_mapper/content_model.rb +2 -0
  24. data/lib/spontaneous/data_mapper/content_model/serialization.rb +2 -2
  25. data/lib/spontaneous/extensions/array.rb +12 -2
  26. data/lib/spontaneous/field/base.rb +10 -0
  27. data/lib/spontaneous/field/file.rb +32 -2
  28. data/lib/spontaneous/field/image.rb +24 -2
  29. data/lib/spontaneous/field/select.rb +8 -0
  30. data/lib/spontaneous/field/webvideo.rb +8 -0
  31. data/lib/spontaneous/generators/site/config/initializers/fields.rb +55 -0
  32. data/lib/spontaneous/json.rb +3 -2
  33. data/lib/spontaneous/logger.rb +2 -2
  34. data/lib/spontaneous/media/file.rb +3 -3
  35. data/lib/spontaneous/media/image/attributes.rb +72 -6
  36. data/lib/spontaneous/media/image/renderable.rb +53 -20
  37. data/lib/spontaneous/media/store.rb +3 -3
  38. data/lib/spontaneous/media/store/backend.rb +16 -0
  39. data/lib/spontaneous/media/store/cloud.rb +52 -12
  40. data/lib/spontaneous/media/store/local.rb +6 -3
  41. data/lib/spontaneous/model.rb +3 -0
  42. data/lib/spontaneous/model/core/entries.rb +34 -13
  43. data/lib/spontaneous/model/core/entry.rb +3 -1
  44. data/lib/spontaneous/model/page/controllers.rb +1 -2
  45. data/lib/spontaneous/model/page/paths.rb +18 -7
  46. data/lib/spontaneous/output/context.rb +0 -8
  47. data/lib/spontaneous/output/template/renderer.rb +2 -0
  48. data/lib/spontaneous/plugins/application/state.rb +0 -4
  49. data/lib/spontaneous/prototypes/field_prototype.rb +4 -0
  50. data/lib/spontaneous/publishing/immediate.rb +0 -5
  51. data/lib/spontaneous/publishing/progress.rb +2 -2
  52. data/lib/spontaneous/publishing/rerender.rb +1 -4
  53. data/lib/spontaneous/publishing/simultaneous.rb +19 -17
  54. data/lib/spontaneous/publishing/steps.rb +12 -3
  55. data/lib/spontaneous/rack.rb +2 -0
  56. data/lib/spontaneous/rack/asset_server.rb +5 -2
  57. data/lib/spontaneous/rack/back.rb +9 -1
  58. data/lib/spontaneous/rack/back/base.rb +1 -0
  59. data/lib/spontaneous/rack/back/changes.rb +5 -0
  60. data/lib/spontaneous/rack/back/preview.rb +4 -4
  61. data/lib/spontaneous/rack/back/private.rb +11 -0
  62. data/lib/spontaneous/rack/middleware/scope.rb +16 -4
  63. data/lib/spontaneous/rack/page_controller.rb +2 -2
  64. data/lib/spontaneous/rack/public.rb +52 -4
  65. data/lib/spontaneous/sequel.rb +10 -13
  66. data/lib/spontaneous/site.rb +28 -8
  67. data/lib/spontaneous/site/publishing.rb +1 -1
  68. data/lib/spontaneous/site/storage.rb +7 -4
  69. data/lib/spontaneous/tasks/environment.rake +3 -0
  70. data/lib/spontaneous/utils/database/postgres_dumper.rb +23 -2
  71. data/lib/spontaneous/version.rb +1 -1
  72. data/spontaneous.gemspec +7 -12
  73. data/test/fixtures/assets/public1/css/data.css.scss +1 -1
  74. data/test/functional/test_application.rb +15 -0
  75. data/test/functional/test_cli.rb +109 -3
  76. data/test/functional/test_front.rb +108 -10
  77. data/test/test_helper.rb +3 -3
  78. data/test/unit/fields/test_boolean_fields.rb +80 -0
  79. data/test/unit/fields/test_date_fields.rb +47 -0
  80. data/test/unit/fields/test_file_field.rb +210 -0
  81. data/test/unit/{test_images.rb → fields/test_image_fields.rb} +133 -15
  82. data/test/unit/fields/test_location_fields.rb +41 -0
  83. data/test/unit/fields/test_option_fields.rb +61 -0
  84. data/test/unit/fields/test_tag_list_fields.rb +45 -0
  85. data/test/unit/fields/test_text_fields.rb +124 -0
  86. data/test/unit/fields/test_web_video_fields.rb +198 -0
  87. data/test/unit/test_assets.rb +22 -22
  88. data/test/unit/test_boxes.rb +34 -13
  89. data/test/unit/test_changesets.rb +1 -0
  90. data/test/unit/test_extensions.rb +17 -0
  91. data/test/unit/test_fields.rb +20 -643
  92. data/test/unit/test_media.rb +9 -9
  93. data/test/unit/test_page.rb +47 -0
  94. data/test/unit/test_publishing_pipeline.rb +2 -2
  95. data/test/unit/test_serialisation.rb +37 -0
  96. data/test/unit/test_storage.rb +42 -3
  97. metadata +37 -17
@@ -12,6 +12,9 @@ Capistrano::Configuration.instance(:must_exist).load do
12
12
  set :revision_dir, lambda { "#{deploy_to}/revisions" }
13
13
  set :upload_dir, lambda { "#{deploy_to}/uploadcache" }
14
14
 
15
+ set :spot, lambda { "./bin/spot" }
16
+ set :rake, lambda { "./bin/rake" }
17
+
15
18
  namespace :spot do
16
19
  task :symlink_cache do
17
20
  cache_dir = File.join(latest_release, 'cache')
@@ -29,24 +32,24 @@ Capistrano::Configuration.instance(:must_exist).load do
29
32
  end
30
33
 
31
34
  task :bundle_assets do
32
- run "cd #{release_path} && ./bin/spot assets compile --destination=#{release_path}"
35
+ run "cd #{release_path} && #{fetch(:spot)} assets compile --destination=#{release_path}"
33
36
  end
34
37
 
35
38
  task :migrate, :roles => :db do
36
39
  spot_env = fetch(:spot_env, "production")
37
- run "cd #{release_path} && SPOT_ENV=#{spot_env} ./bin/spot migrate"
40
+ run "cd #{release_path} && SPOT_ENV=#{spot_env} #{fetch(:spot)} migrate"
38
41
  end
39
42
 
40
43
  task :content_clean, :roles => :db do
41
44
  spot_env = fetch(:spot_env, "production")
42
- run "cd #{release_path} && SPOT_ENV=#{spot_env} ./bin/spot content clean"
45
+ run "cd #{release_path} && SPOT_ENV=#{spot_env} #{fetch(:spot)} content clean"
43
46
  end
44
47
  end
45
48
 
46
49
  namespace :deploy do
47
50
  task :migrate, :roles => :db do
48
51
  spot_env = fetch(:spot_env, "production")
49
- run "cd #{latest_release} && SPOT_ENV=#{spot_env} ./bin/spot migrate"
52
+ run "cd #{latest_release} && SPOT_ENV=#{spot_env} #{fetch(:spot)} migrate"
50
53
  end
51
54
  end
52
55
 
@@ -39,7 +39,7 @@ Capistrano::Configuration.instance(:must_exist).load do
39
39
  puts " * Syncing database DOWN"
40
40
  dumper = Spontaneous::Utils::Database.dumper_for_database
41
41
  dumpfilename = ENV['dumpfile'] || dumper.dumpfilename
42
- run %(cd #{current_path} && ./bin/rake db:dump dumpfile=#{dumpfilename} )
42
+ run %(cd #{current_path} && #{fetch(:rake)} db:dump dumpfile=#{dumpfilename} )
43
43
  dump_file = File.join("tmp", dumpfilename)
44
44
  top.download(File.join(current_path, dump_file), dump_file)
45
45
  system "bundle exec rake db:load dumpfile=#{dump_file}"
@@ -54,7 +54,7 @@ Capistrano::Configuration.instance(:must_exist).load do
54
54
  dumper.dump(dump_file)
55
55
  remote_dump_file = File.join(deploy_to, dumpfilename)
56
56
  top.upload(dump_file, remote_dump_file)
57
- run %(cd #{current_path} && #{fetch(:bundle_cmd, 'bundle')} exec rake db:load dumpfile=#{remote_dump_file} )
57
+ run %(cd #{current_path} && #{fetch(:bundle_cmd, 'bundle')} exec #{fetch(:rake)} db:load dumpfile=#{remote_dump_file} )
58
58
  end
59
59
  end
60
60
 
@@ -19,18 +19,21 @@ module Spontaneous::Cli
19
19
  method_option :create_user, :type => :boolean, :default => true, :desc => "Enable creation of a root user"
20
20
 
21
21
  def init
22
- initialize_size
22
+ initialize_site
23
23
  end
24
24
 
25
25
  protected
26
26
 
27
- def initialize_size
27
+ def initialize_site
28
28
  prepare :init
29
29
 
30
30
  @site = ::Spontaneous::Site.instantiate(Dir.pwd, options.environment, :console)
31
31
  Sequel.extension :migration
32
32
 
33
- database_initializer.run
33
+ site_initializer.run(@site.environment)
34
+
35
+ empty_directory "tmp" unless ::File.directory?("tmp")
36
+ empty_directory "log" unless ::File.directory?("log")
34
37
 
35
38
  boot!
36
39
 
@@ -38,6 +41,68 @@ module Spontaneous::Cli
38
41
  insert_root_user if (options.create_user && ::Spontaneous::Permissions::User.count == 0)
39
42
  end
40
43
 
44
+ class DatabaseInitializer
45
+ def initialize(cli, site)
46
+ @cli, @site = cli, site
47
+ end
48
+
49
+ def run(environment)
50
+ initialize_databases(environment)
51
+ end
52
+
53
+ def initialize_databases(environment)
54
+ database_initializers(environment).each do |initializer|
55
+ initializer.run
56
+ end
57
+ end
58
+
59
+ # Returns a list of initializers for the given env.
60
+ #
61
+ # This de-dupes the initializers according to the config so that only
62
+ # one call is made in the case where different envs return the same db
63
+ # config.
64
+ def database_initializers(environment)
65
+ dbs = database_environments(environment).map { |env|
66
+ database_instance(env)
67
+ }.uniq { |db| db.opts }
68
+ dbs.map { |db| initializer_for_db(db) }
69
+ end
70
+
71
+ def database_initializer(env)
72
+ initializer_for_db(database_instance(env))
73
+ end
74
+
75
+ def initializer_for_db(db)
76
+ initializer_class = case db.opts[:adapter]
77
+ when /mysql/
78
+ 'MySQL'
79
+ when /postgres/
80
+ 'Postgresql'
81
+ when /sqlite/
82
+ 'Sqlite'
83
+ end
84
+ klass = Spontaneous::Cli::Init.const_get(initializer_class)
85
+ klass.new(@cli, db)
86
+ end
87
+
88
+ def database_instance(env)
89
+ @site.database_instance(database_config(env))
90
+ end
91
+
92
+ def database_config(env)
93
+ @site.db_connection_options(env)
94
+ end
95
+
96
+ def database_environments(environment)
97
+ case environment
98
+ when :development
99
+ [:development, :test]
100
+ else
101
+ [environment]
102
+ end
103
+ end
104
+ end
105
+
41
106
  def insert_root_user
42
107
  invoke "user:add", [], options.account
43
108
  # Set up auto_login configuration with the name of the root user
@@ -51,22 +116,8 @@ module Spontaneous::Cli
51
116
  end
52
117
  end
53
118
 
54
- def database_initializer
55
- @database_initializer ||= get_database_initializer
56
- end
57
-
58
- def get_database_initializer
59
- connection_params = @site.db_config
60
- classname = case connection_params[:development][:adapter]
61
- when /mysql/
62
- 'MySQL'
63
- when /postgres/
64
- 'Postgresql'
65
- when /sqlite/
66
- 'Sqlite'
67
- end
68
- klass = Spontaneous::Cli::Init.const_get(classname)
69
- klass.new(connection_params, self)
119
+ def site_initializer
120
+ @site_initializer ||= DatabaseInitializer.new(self, @site)
70
121
  end
71
122
  end # Init
72
123
  end # Spontaneous::Cli
@@ -4,50 +4,43 @@ module Spontaneous::Cli
4
4
  class Init
5
5
  class Db
6
6
 
7
- attr_reader :site_connection_params, :admin_connection_params, :database, :config
7
+ attr_reader :database, :config
8
8
 
9
- def initialize(connection, cli)
9
+ def initialize(cli, database)
10
10
  @cli = cli
11
- @connection = connection
12
- # setup_connection_params(connection_settings, @cli.options)
13
- # @admin_connection_params[:database] = "postgres"
11
+ @database = database
14
12
  end
15
13
 
16
14
  def run
17
- databases.each do |site_connection_params, admin_connection_params|
18
- # config = site_connection_params.merge(:database => db)
19
- create(admin_connection_params, site_connection_params)
20
- migrate(site_connection_params)
21
- end
15
+ create
16
+ migrate
22
17
  end
23
18
 
24
- def create(admin_config, site_config)
25
- Sequel.connect(admin_config) do |connection|
19
+ def create
20
+ Sequel.connect(admin_connection_params) do |connection|
26
21
  begin
27
- @cli.say " >> Creating database `#{site_config[:database]}`", :green
28
- create_database(connection, site_config)
22
+ @cli.say " >> Creating database `#{database.opts[:database]}`", :green
23
+ create_database(connection)
29
24
  rescue => e
30
- @cli.say " >>> Unable to create #{admin_config[:adapter]} database `#{site_config[:database]}`:\n > #{e}", :red
25
+ @cli.say " >>> Unable to create #{connection.opts[:adapter]} database `#{database.opts[:database]}`:\n > #{e}", :red
31
26
  end
32
27
  end
33
28
  end
34
29
 
35
- def migrate(site_config)
36
- Sequel.connect(site_config) do |connection|
37
- begin
38
- connection.logger = nil
39
- @cli.say " >> Running migrations..."
40
- Sequel::Migrator.apply(connection, ::Spontaneous.gem_dir('db/migrations'))
41
- @cli.say " >> Done"
42
- rescue => e
43
- @cli.say " >>> Error running migrations on database `#{site_config[:database]}`:\n > #{e}", :red
44
- raise e
45
- end
30
+ def migrate
31
+ begin
32
+ database.logger = nil
33
+ @cli.say " >> Running migrations..."
34
+ Sequel::Migrator.apply(database, ::Spontaneous.gem_dir('db/migrations'))
35
+ @cli.say " >> Done"
36
+ rescue => e
37
+ @cli.say " >>> Error running migrations on database `#{site_config[:database]}`:\n > #{e}", :red
38
+ raise e
46
39
  end
47
40
  end
48
41
 
49
- def create_database(connection, config)
50
- commands = create_database_commands(config)
42
+ def create_database(connection)
43
+ commands = create_database_commands(database.opts)
51
44
  commands.each do |command, raise_error|
52
45
  begin
53
46
  connection.run(command)
@@ -57,37 +50,23 @@ module Spontaneous::Cli
57
50
  end
58
51
  end
59
52
 
60
- def create_database_commands(config)
61
- [["", false]]
53
+ # connect to the database as a super/root user in order to create
54
+ # the database
55
+ def admin_connection_params
56
+ config = @database.opts.dup
57
+ config.delete(:database)
58
+ config[:user] = options.user unless options.user.blank?
59
+ config[:password] = options.password unless options.password.blank?
60
+ config
62
61
  end
63
62
 
64
- def setup_connection_params(connection_settings, options)
65
- @options = options
66
- @site_connection_params = connection_settings
67
- @admin_connection_params = @site_connection_params.dup
68
- @admin_connection_params[:user] = @options.user unless @options.user.blank?
69
- @admin_connection_params[:password] = @options.password unless @options.password.blank?
70
-
71
- # @database = @admin_connection_params.delete(:database)
72
- end
73
-
74
- def databases
75
- environments.map { |env|
76
- config_for_environment(env)
77
- }
78
- end
79
-
80
- def config_for_environment(env)
81
- site_config = @connection[env].dup
82
- admin_config = site_config.dup
83
- admin_config.delete(:database)
84
- admin_config[:user] = @cli.options.user unless @cli.options.user.blank?
85
- admin_config[:password] = @cli.options.password unless @cli.options.password.blank?
86
- [site_config, admin_config]
63
+ # Override in db specific sub-classes
64
+ def create_database_commands(opts)
65
+ [["", false]]
87
66
  end
88
67
 
89
- def environments
90
- [:development, :test]
68
+ def options
69
+ @cli.options
91
70
  end
92
71
  end
93
72
  end
@@ -4,11 +4,11 @@ module Spontaneous::Cli
4
4
  class Init
5
5
  class MySQL < Db
6
6
 
7
- def create_database_commands(config)
8
- host = config[:host].blank? ? "" : "@#{config[:host]}"
9
- cmds = [ ["CREATE DATABASE `#{config[:database]}` CHARACTER SET UTF8", true] ]
10
- unless config[:user] == "root"
11
- cmds << ["GRANT ALL ON `#{config[:database]}`.* TO `#{config[:user]}`#{host} IDENTIFIED BY '#{config[:password]}'", false]
7
+ def create_database_commands(opts)
8
+ host = opts[:host].blank? ? "" : "@#{opts[:host]}"
9
+ cmds = [ ["CREATE DATABASE `#{opts[:database]}` CHARACTER SET UTF8", true] ]
10
+ unless opts[:user] == "root"
11
+ cmds << ["GRANT ALL ON `#{opts[:database]}`.* TO `#{opts[:user]}`#{host} IDENTIFIED BY '#{opts[:password]}'", false]
12
12
  end
13
13
  cmds
14
14
  end
@@ -4,10 +4,9 @@ module Spontaneous::Cli
4
4
  class Init
5
5
  class Postgresql < Db
6
6
 
7
- def config_for_environment(env)
8
- site_config, admin_config = super
9
- admin_config[:database] = "postgres"
10
- [site_config, admin_config]
7
+ def admin_connection_params
8
+ config = super
9
+ config.merge(database: 'postgres')
11
10
  end
12
11
 
13
12
  # On some machines the db creation fails due to incompabilities between the UTF8 encoding
@@ -19,12 +18,12 @@ module Spontaneous::Cli
19
18
  #
20
19
  # but I don't know a good/the best way to determine the most appropriate UTF-8 locale
21
20
  # C.UTF-8 doesn't exist on OS X.
22
- def create_database_commands(config)
23
- create_cmd = %(CREATE DATABASE "#{config[:database]}" WITH TEMPLATE=template0 ENCODING='UTF8')
21
+ def create_database_commands(opts)
22
+ create_cmd = %(CREATE DATABASE "#{opts[:database]}" WITH TEMPLATE=template0 ENCODING='UTF8')
24
23
  cmds = []
25
- unless config[:user].blank?
26
- create_cmd << %( OWNER="#{config[:user]}")
27
- cmds << [%(CREATE ROLE "#{config[:user]}" LOGIN PASSWORD '#{config[:password]}'), false]
24
+ unless opts[:user].blank?
25
+ create_cmd << %( OWNER="#{opts[:user]}")
26
+ cmds << [%(CREATE ROLE "#{opts[:user]}" LOGIN PASSWORD '#{opts[:password]}'), false]
28
27
  end
29
28
  cmds << [create_cmd, true]
30
29
  end
@@ -5,8 +5,7 @@ require 'fileutils'
5
5
  module Spontaneous::Cli
6
6
  class Init
7
7
  class Sqlite < Db
8
-
9
- def create_database(connection, config)
8
+ def create_database(connection)
10
9
  FileUtils.mkdir_p(File.join(@cli.options.site, 'db'))
11
10
  end
12
11
  end
@@ -12,7 +12,6 @@ module Spontaneous::Cli
12
12
  def apply
13
13
  prepare! :migrate
14
14
  Sequel.extension :migration
15
- connection_params = ::Spontaneous.db_settings
16
15
  say " >> Running migrations..."
17
16
  Sequel::Migrator.apply(Spontaneous.database, ::Spontaneous.gem_dir('db/migrations'))
18
17
  say " >> Done"
@@ -126,6 +126,10 @@ module Spontaneous
126
126
  render_site
127
127
  end
128
128
 
129
+ no_commands do
130
+ alias_method :rerender, :render
131
+ end
132
+
129
133
  desc "revision", "Shows the site status"
130
134
  def revision(*args)
131
135
  show_site_revision
@@ -82,12 +82,23 @@ module Spontaneous::Collections
82
82
  store[sid]
83
83
  end
84
84
 
85
+ # TODO: replace this with optimized version that can return a list of
86
+ # ids for a particular box without loading the box's content
87
+ def ids(box)
88
+ for_box(box).map(&:id)
89
+ end
90
+
85
91
  def insert(index, box, entry)
86
92
  box_id = box.schema_id.to_s
87
93
  store[box_id].insert(index, entry)
88
94
  owner.entry_modified!(entry)
89
95
  end
90
96
 
97
+ # Called after the modification of box contents to keep the
98
+ # raw data in-sync with the owner's structure
99
+ def update(piece_store)
100
+ @piece_store = piece_store
101
+ end
91
102
 
92
103
  def destroy!
93
104
  self.destroy
@@ -85,6 +85,8 @@ module Spontaneous
85
85
  mapper.get(id)
86
86
  end
87
87
 
88
+ # Allows for Page/123 => #<Page id=123...>
89
+ alias_method :/, :get
88
90
  alias_method :[], :get
89
91
 
90
92
  def primary_key_lookup(id)
@@ -38,7 +38,7 @@ module Spontaneous::DataMapper
38
38
  end
39
39
 
40
40
  def _deserialize_value(value)
41
- Yajl::Parser.new(:symbolize_keys => true).parse(value || "null")
41
+ Spontaneous::parse_json(value || "null")
42
42
  end
43
43
 
44
44
  def _serialize_column(column, value)
@@ -47,7 +47,7 @@ module Spontaneous::DataMapper
47
47
  end
48
48
 
49
49
  def _serialize_value(value)
50
- Yajl::Encoder.new.encode(value)
50
+ Spontaneous::encode_json(value)
51
51
  end
52
52
  end
53
53
  end
@@ -5,7 +5,9 @@ module Spontaneous
5
5
  module Array
6
6
  def render_using(renderer, *args)
7
7
  self.map { |e|
8
- if e.respond_to?(:render_using)
8
+ if e.respond_to?(:render_inline_using)
9
+ e.render_inline_using(renderer, *args)
10
+ elsif e.respond_to?(:render_using)
9
11
  e.render_using(renderer, *args)
10
12
  elsif e.respond_to?(:render)
11
13
  e.render(*args)
@@ -16,7 +18,15 @@ module Spontaneous
16
18
  end
17
19
 
18
20
  def render(*args)
19
- self.map { |e| e.respond_to?(:render) ? e.render(*args) : e }.join
21
+ self.map { |e|
22
+ if e.respond_to?(:render_inline)
23
+ e.render_inline(*args)
24
+ elsif e.respond_to?(:render)
25
+ e.render(*args)
26
+ else
27
+ e
28
+ end
29
+ }.join
20
30
  end
21
31
  end
22
32
  end