spontaneous 0.2.0.beta9 → 0.2.0.beta10

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