moon 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/README.rdoc +2 -0
  2. data/Rakefile +10 -3
  3. data/lib/moon.rb +0 -2
  4. data/lib/moon/action.rb +4 -3
  5. data/lib/moon/action/inject_timestamps.rb +44 -0
  6. data/lib/moon/action/model.rb +1 -2
  7. data/lib/moon/action/model/destroy.rb +4 -26
  8. data/lib/moon/action/model/index.rb +10 -17
  9. data/lib/moon/action/model/show.rb +9 -23
  10. data/lib/moon/action/model/store.rb +20 -0
  11. data/lib/moon/action/models/finder.rb +14 -14
  12. data/lib/moon/action/models/initializer.rb +6 -5
  13. data/lib/moon/action/models/updater.rb +1 -4
  14. data/lib/moon/action/rebuild_arrays.rb +1 -4
  15. data/lib/moon/action/{reference_object.rb → reference.rb} +1 -1
  16. data/lib/moon/action/respond_blank.rb +9 -0
  17. data/lib/moon/action/transfer.rb +30 -0
  18. data/lib/moon/action/valid_models_required.rb +13 -6
  19. data/lib/moon/application.rb +12 -7
  20. data/lib/moon/application/configuration.rb +55 -0
  21. data/lib/moon/application/rack.rb +17 -7
  22. data/lib/moon/context.rb +1 -1
  23. data/lib/moon/formatter.rb +4 -13
  24. data/lib/moon/formatter/generic.rb +17 -4
  25. data/lib/moon/response/json.rb +1 -0
  26. data/lib/moon/response/json/blank.rb +9 -0
  27. data/lib/moon/response/json/collection.rb +2 -2
  28. data/lib/moon/response/json/model.rb +3 -3
  29. data/lib/moon/validator.rb +17 -45
  30. data/lib/moon/validator/format.rb +4 -23
  31. data/lib/moon/validator/length.rb +8 -33
  32. data/lib/moon/validator/presence.rb +4 -17
  33. data/spec/lib/moon/action/inject_timestamps_spec.rb +46 -0
  34. data/spec/lib/moon/action/model/destroy_spec.rb +6 -44
  35. data/spec/lib/moon/action/model/index_spec.rb +8 -25
  36. data/spec/lib/moon/action/model/show_spec.rb +33 -25
  37. data/spec/lib/moon/action/model/store_spec.rb +77 -0
  38. data/spec/lib/moon/action/models/finder_spec.rb +25 -11
  39. data/spec/lib/moon/action/models/initializer_spec.rb +7 -5
  40. data/spec/lib/moon/action/models/updater_spec.rb +5 -3
  41. data/spec/lib/moon/action/rebuild_arrays_spec.rb +3 -3
  42. data/spec/lib/moon/action/{reference_object_spec.rb → reference_spec.rb} +1 -1
  43. data/spec/lib/moon/action/respond_blank_spec.rb +24 -0
  44. data/spec/lib/moon/action/transfer_spec.rb +30 -0
  45. data/spec/lib/moon/action/valid_models_required_spec.rb +19 -17
  46. data/spec/lib/moon/application/configuration_spec.rb +75 -0
  47. data/spec/lib/moon/application/rack_spec.rb +6 -5
  48. data/spec/lib/moon/formatter/generic_spec.rb +13 -3
  49. data/spec/lib/moon/formatter_spec.rb +4 -10
  50. data/spec/lib/moon/response/json/blank_spec.rb +19 -0
  51. data/spec/lib/moon/response/json/collection_spec.rb +5 -4
  52. data/spec/lib/moon/response/json/model_spec.rb +5 -4
  53. data/spec/lib/moon/validator/format_spec.rb +8 -25
  54. data/spec/lib/moon/validator/length_spec.rb +10 -36
  55. data/spec/lib/moon/validator/presence_spec.rb +11 -28
  56. data/spec/lib/moon/validator_spec.rb +10 -59
  57. metadata +34 -28
  58. data/lib/moon/action/base.rb +0 -16
  59. data/lib/moon/action/model/create.rb +0 -45
  60. data/lib/moon/action/model/update.rb +0 -42
  61. data/lib/moon/application/routes.rb +0 -16
  62. data/lib/moon/formatter/base.rb +0 -15
  63. data/spec/lib/moon/action/base_spec.rb +0 -29
  64. data/spec/lib/moon/action/model/create_spec.rb +0 -111
  65. data/spec/lib/moon/action/model/update_spec.rb +0 -91
  66. data/spec/lib/moon/application/routes_spec.rb +0 -26
  67. data/spec/lib/moon/formatter/base_spec.rb +0 -30
@@ -3,6 +3,8 @@
3
3
 
4
4
  No fixed API yet. Documentation will follow...
5
5
 
6
+ http://travis-ci.org/phifty/moon.png
7
+
6
8
  == Development
7
9
 
8
10
  Development has been done test-driven and the code follows at most the Clean Code paradigms. Code smells has been
data/Rakefile CHANGED
@@ -1,4 +1,13 @@
1
- require 'rake/rdoctask'
1
+ require 'rubygems'
2
+ require 'rdoc'
3
+ require 'rdoc/task'
4
+
5
+ # Cucumber
6
+ require 'cucumber/rake/task'
7
+
8
+ Cucumber::Rake::Task.new(:features) do |task|
9
+ task.cucumber_opts = "--format pretty"
10
+ end
2
11
 
3
12
  # RSpec
4
13
  require 'rspec/core/rake_task'
@@ -35,12 +44,10 @@ end
35
44
 
36
45
  namespace :gem do
37
46
 
38
- desc "Builds the gem"
39
47
  task :build do
40
48
  system "gem build *.gemspec && mkdir -p pkg/ && mv *.gem pkg/"
41
49
  end
42
50
 
43
- desc "Builds and installs the gem"
44
51
  task :install => :build do
45
52
  system "gem install pkg/"
46
53
  end
@@ -1,6 +1,4 @@
1
1
  require 'gom'
2
- require 'gom/filesystem-adapter'
3
- require 'gom/couchdb-adapter'
4
2
 
5
3
  module Moon
6
4
 
@@ -1,12 +1,13 @@
1
1
 
2
2
  module Moon::Action
3
3
 
4
- autoload :Base, File.join(File.dirname(__FILE__), "action", "base")
5
- autoload :BuildOptionHashes, File.join(File.dirname(__FILE__), "action", "build_option_hashes")
4
+ autoload :InjectTimestamps, File.join(File.dirname(__FILE__), "action", "inject_timestamps")
6
5
  autoload :Model, File.join(File.dirname(__FILE__), "action", "model")
7
6
  autoload :Models, File.join(File.dirname(__FILE__), "action", "models")
8
7
  autoload :RebuildArrays, File.join(File.dirname(__FILE__), "action", "rebuild_arrays")
9
- autoload :ReferenceObject, File.join(File.dirname(__FILE__), "action", "reference_object")
8
+ autoload :Reference, File.join(File.dirname(__FILE__), "action", "reference")
9
+ autoload :RespondBlank, File.join(File.dirname(__FILE__), "action", "respond_blank")
10
+ autoload :Transfer, File.join(File.dirname(__FILE__), "action", "transfer")
10
11
  autoload :ValidModelsRequired, File.join(File.dirname(__FILE__), "action", "valid_models_required")
11
12
 
12
13
  end
@@ -0,0 +1,44 @@
1
+
2
+ class Moon::Action::InjectTimestamps
3
+
4
+ def initialize(model_key)
5
+ @model_key = model_key
6
+ end
7
+
8
+ def perform(context)
9
+ @context = context
10
+ fetch_model
11
+ fetch_id
12
+ fetch_now
13
+ inject_created_at unless has_id?
14
+ inject_update_at
15
+ nil
16
+ end
17
+
18
+ private
19
+
20
+ def fetch_model
21
+ @model = @context.models[@model_key]
22
+ end
23
+
24
+ def fetch_id
25
+ @id = GOM::Object.id @model
26
+ end
27
+
28
+ def fetch_now
29
+ @now = Time.now
30
+ end
31
+
32
+ def has_id?
33
+ !!@id
34
+ end
35
+
36
+ def inject_created_at
37
+ @model.created_at = @now
38
+ end
39
+
40
+ def inject_update_at
41
+ @model.updated_at = @now
42
+ end
43
+
44
+ end
@@ -1,10 +1,9 @@
1
1
 
2
2
  module Moon::Action::Model
3
3
 
4
- autoload :Create, File.join(File.dirname(__FILE__), "model", "create")
5
4
  autoload :Destroy, File.join(File.dirname(__FILE__), "model", "destroy")
6
5
  autoload :Index, File.join(File.dirname(__FILE__), "model", "index")
7
6
  autoload :Show, File.join(File.dirname(__FILE__), "model", "show")
8
- autoload :Update, File.join(File.dirname(__FILE__), "model", "update")
7
+ autoload :Store, File.join(File.dirname(__FILE__), "model", "store")
9
8
 
10
9
  end
@@ -2,12 +2,12 @@
2
2
  # Generic model destroy action. Removes the specified model from the storage.
3
3
  class Moon::Action::Model::Destroy
4
4
 
5
- def initialize(context)
6
- @context = context
5
+ def initialize(model_symbol)
6
+ @model_symbol = model_symbol
7
7
  end
8
8
 
9
- def perform
10
- model = self.model
9
+ def perform(context)
10
+ model = context.models[@model_symbol]
11
11
  model_class = model.class
12
12
  if model
13
13
  GOM::Storage.remove model
@@ -17,26 +17,4 @@ class Moon::Action::Model::Destroy
17
17
  end
18
18
  end
19
19
 
20
- def model
21
- @context.models[self.class.model_symbol]
22
- end
23
-
24
- def self.model_symbol=(value)
25
- @model_symbol = value
26
- end
27
-
28
- def self.model_symbol
29
- @model_symbol
30
- end
31
-
32
- def self.perform(context)
33
- new(context).perform
34
- end
35
-
36
- def self.[](model_symbol)
37
- klass = self.dup
38
- klass.model_symbol = model_symbol
39
- klass
40
- end
41
-
42
20
  end
@@ -2,30 +2,23 @@
2
2
  # Common model index action
3
3
  class Moon::Action::Model::Index
4
4
 
5
- def initialize(context)
6
- @context = context
7
- end
8
-
9
- def perform
10
- Moon::Response::JSON::Collection.new @context.collections[self.class.collection_key]
5
+ def initialize(collection_key)
6
+ @collection_key = collection_key
11
7
  end
12
8
 
13
- def self.collection_key=(value)
14
- @collection_key = value
9
+ def perform(context)
10
+ @context = context
11
+ Moon::Response::JSON::Collection.new collection, formatters
15
12
  end
16
13
 
17
- def self.collection_key
18
- @collection_key
19
- end
14
+ private
20
15
 
21
- def self.perform(context)
22
- new(context).perform
16
+ def collection
17
+ @context.collections[@collection_key]
23
18
  end
24
19
 
25
- def self.[](collection_key)
26
- klass = self.dup
27
- klass.collection_key = collection_key
28
- klass
20
+ def formatters
21
+ @context.application.configuration.formatters
29
22
  end
30
23
 
31
24
  end
@@ -2,31 +2,17 @@
2
2
  # Common model show action
3
3
  class Moon::Action::Model::Show
4
4
 
5
- def initialize(context)
6
- @context = context
5
+ def initialize(model_key)
6
+ @model_key = model_key
7
7
  end
8
8
 
9
- def perform
10
- model_key = self.class.model_key
11
- Moon::Response::JSON::Model.new model_key, @context.models[model_key]
12
- end
13
-
14
- def self.model_key=(value)
15
- @model_key = value
16
- end
17
-
18
- def self.model_key
19
- @model_key
20
- end
21
-
22
- def self.perform(context)
23
- new(context).perform
24
- end
25
-
26
- def self.[](model_key)
27
- klass = self.dup
28
- klass.model_key = model_key
29
- klass
9
+ def perform(context)
10
+ model = context.models[@model_key]
11
+ if model
12
+ Moon::Response::JSON::Model.new @model_key, context.models[@model_key], context.application.configuration.formatters
13
+ else
14
+ Moon::Response::JSON::Message.new 404, "Model not found."
15
+ end
30
16
  end
31
17
 
32
18
  end
@@ -0,0 +1,20 @@
1
+
2
+ # Generic model update action. Stores the specified model to the storage.
3
+ class Moon::Action::Model::Store
4
+
5
+ def initialize(model_symbol)
6
+ @model_symbol = model_symbol
7
+ end
8
+
9
+ def perform(context)
10
+ model = context.models[@model_symbol]
11
+ if model
12
+ storage_name = GOM::Object.storage_name(model) || context.application.storage_name
13
+ GOM::Storage.store model, storage_name
14
+ nil
15
+ else
16
+ Moon::Response::JSON::Message.new 200, "No model initialized."
17
+ end
18
+ end
19
+
20
+ end
@@ -1,33 +1,33 @@
1
1
 
2
- # This action takes parameters that ends with '_id' out of the context and searches the fitting model
3
- # for it. The result is assign to the context.
2
+ # This action takes parameter and session keys that ends with '_id' out of the context and searches the fitting model
3
+ # for it. The result is assign to the context models.
4
4
  class Moon::Action::Models::Finder
5
5
 
6
- def initialize(context)
6
+ def perform(context)
7
7
  @context = context
8
- end
9
-
10
- def perform
11
- find_models
8
+ find_session_models
9
+ find_parameter_models
12
10
  nil
13
11
  end
14
12
 
15
13
  private
16
14
 
17
- def find_models
15
+ def find_session_models
16
+ @context.session.each do |key, value|
17
+ find_model key, value, "current_" if self.class.point_to_model?(key)
18
+ end
19
+ end
20
+
21
+ def find_parameter_models
18
22
  @context.parameters.each do |key, value|
19
23
  find_model key, value if self.class.point_to_model?(key)
20
24
  end
21
25
  end
22
26
 
23
- def find_model(key, id)
27
+ def find_model(key, id, prefix = "")
24
28
  model_name = self.class.model_name key
25
29
  model = GOM::Storage.fetch id
26
- @context.models[model_name.downcase.to_sym] = model
27
- end
28
-
29
- def self.perform(context)
30
- new(context).perform
30
+ @context.models[:"#{prefix}#{model_name.downcase}"] = model
31
31
  end
32
32
 
33
33
  private
@@ -3,16 +3,17 @@
3
3
  # a model from it.
4
4
  class Moon::Action::Models::Initializer
5
5
 
6
- def self.perform(context)
7
- initialize_models context
6
+ def perform(context)
7
+ @context = context
8
+ initialize_models
8
9
  nil
9
10
  end
10
11
 
11
12
  private
12
13
 
13
- def self.initialize_models(context)
14
- context.parameters.each do |key, value|
15
- context.models[key.to_sym] = Builder.new(key, value).model
14
+ def initialize_models
15
+ @context.parameters.each do |key, value|
16
+ @context.models[key.to_sym] = Builder.new(key, value).model
16
17
  end
17
18
  end
18
19
 
@@ -2,11 +2,8 @@
2
2
  # Uses the parameters in the context and tries to update the models.
3
3
  class Moon::Action::Models::Updater
4
4
 
5
- def initialize(context)
5
+ def perform(context)
6
6
  @context = context
7
- end
8
-
9
- def perform
10
7
  @context.models.each do |model_key, model|
11
8
  Model.new(model, @context.parameters[model_key]).update
12
9
  end
@@ -2,11 +2,8 @@
2
2
  # Converts each hash with numeric keys { "0" => "one", "1" => "two" } into arrays [ "one", "two" ].
3
3
  class Moon::Action::RebuildArrays
4
4
 
5
- def initialize(context)
5
+ def perform(context)
6
6
  @context = context
7
- end
8
-
9
- def perform
10
7
  @context.parameters = self.class.rebuild_arrays @context.parameters
11
8
  nil
12
9
  end
@@ -1,6 +1,6 @@
1
1
 
2
2
  # The action creates a reference to the given store object and stores it in the given model attribute.
3
- class Moon::Action::ReferenceObject
3
+ class Moon::Action::Reference
4
4
 
5
5
  def initialize(options)
6
6
  from, to = options.values_at :from, :to
@@ -0,0 +1,9 @@
1
+
2
+ # The action responses a blank json response without any conditions.
3
+ class Moon::Action::RespondBlank
4
+
5
+ def perform(context)
6
+ Moon::Response::JSON::Blank.new
7
+ end
8
+
9
+ end
@@ -0,0 +1,30 @@
1
+
2
+ # The action transfers a value from the given store object and stores it in the given model attribute.
3
+ class Moon::Action::Transfer
4
+
5
+ def initialize(options)
6
+ from, to = options.values_at :from, :to
7
+ @store_method, @store_key = from
8
+ @model_key, @model_attribute = to
9
+ end
10
+
11
+ def perform(context)
12
+ @context = context
13
+ fetch_value
14
+ store_value
15
+ nil
16
+ end
17
+
18
+ private
19
+
20
+ def fetch_value
21
+ store = @context.send @store_method.to_sym
22
+ @value = store[@store_key.to_sym]
23
+ end
24
+
25
+ def store_value
26
+ model = @context.models[@model_key.to_sym]
27
+ model.send :"#{@model_attribute}=", @value
28
+ end
29
+
30
+ end
@@ -2,20 +2,27 @@
2
2
  # The action checks if every model in the context is valid.
3
3
  class Moon::Action::ValidModelsRequired
4
4
 
5
- def self.perform(context)
6
- validation_errors = validate_models context
5
+ def perform(context)
6
+ @context = context
7
+ validation_errors = validate_models
7
8
  validation_errors.empty? ? nil : Moon::Response::JSON::ValidationErrors.new(validation_errors)
8
9
  end
9
10
 
10
11
  private
11
12
 
12
- def self.validate_models(context)
13
+ def validate_models
13
14
  validation_errors = { }
14
- context.models.each do |key, model|
15
- validator = Moon::Validator[model.class].new model
16
- validation_errors[key] = validator.messages unless validator.ok?
15
+ @context.models.each do |key, model|
16
+ messages = validate_model key, model
17
+ validation_errors[key] = messages unless messages.empty?
17
18
  end
18
19
  validation_errors
19
20
  end
20
21
 
22
+ def validate_model(key, model)
23
+ checks = @context.application.configuration.validators[model.class]
24
+ validator = Moon::Validator.new @context, checks
25
+ validator.messages model
26
+ end
27
+
21
28
  end