rd3 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.
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format documentation
3
+ --backtrace
4
+ --default_path spec
data/.rvmrc ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.9.3@rd3"
8
+
9
+ #
10
+ # Uncomment following line if you want options to be set only for given project.
11
+ #
12
+ # PROJECT_JRUBY_OPTS=( --1.9 )
13
+ #
14
+ # The variable PROJECT_JRUBY_OPTS requires the following to be run in shell:
15
+ #
16
+ # chmod +x ${rvm_path}/hooks/after_use_jruby_opts
17
+ #
18
+
19
+ #
20
+ # First we attempt to load the desired environment directly from the environment
21
+ # file. This is very fast and efficient compared to running through the entire
22
+ # CLI and selector. If you want feedback on which environment was used then
23
+ # insert the word 'use' after --create as this triggers verbose mode.
24
+ #
25
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
26
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
27
+ then
28
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
29
+
30
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
31
+ then
32
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
33
+ fi
34
+ else
35
+ # If the environment file has not yet been created, use the RVM CLI to select.
36
+ if ! rvm --create "$environment_id"
37
+ then
38
+ echo "Failed to create RVM environment '${environment_id}'."
39
+ return 1
40
+ fi
41
+ fi
42
+
43
+ #
44
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
45
+ # it be automatically loaded. Uncomment the following and adjust the filename if
46
+ # necessary.
47
+ #
48
+ # filename=".gems"
49
+ # if [[ -s "$filename" ]]
50
+ # then
51
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
52
+ # fi
53
+
54
+ # If you use bundler, this might be useful to you:
55
+ # if [[ -s Gemfile ]] && ! command -v bundle >/dev/null
56
+ # then
57
+ # printf "The rubygem 'bundler' is not installed. Installing it now.\n"
58
+ # gem install bundler
59
+ # fi
60
+ # if [[ -s Gemfile ]] && command -v bundle
61
+ # then
62
+ # bundle install
63
+ # fi
64
+
65
+ if [[ $- == *i* ]] # check for interactive shells
66
+ then
67
+ echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
68
+ else
69
+ echo "Using: $GEM_HOME" # don't use colors in interactive shells
70
+ fi
71
+
data/.simplecov ADDED
@@ -0,0 +1,5 @@
1
+ # configure code coverage
2
+ SimpleCov.start do
3
+ # exclude directories and files
4
+ add_filter "/spec/"
5
+ end
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem 'activesupport'
6
+ gem 'activemodel'
7
+ gem 'require_all'
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development, :test do
12
+ gem "rdoc", ">= 3.12"
13
+ gem "bundler", ">= 1.0.0"
14
+ gem "jeweler", ">= 1.8.4"
15
+ gem "rspec", ">= 2.12.0"
16
+ gem "simplecov", ">= 0.7.1"
17
+ gem "mysql2", ">= 0.3.11"
18
+ gem "pg", ">= 0.14.1"
19
+ gem "sequel", ">= 3.41.0"
20
+ gem "waz-storage", ">= 1.1.4"
21
+ gem "database_cleaner", ">= 0.9.1"
22
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 obie quelland
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ D3
2
+ =====
3
+
4
+ TODO: update content
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "rd3"
18
+ gem.homepage = "http://github.com/obieq/rd3"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{RD3 is a ruby gem that adheres to and facilitates domain driven design principles}
21
+ gem.description = %Q{ enable domain driven design approach via POROs and Repositories vs Rails' ActiveRecord }
22
+ gem.email = "quelland@gmail.com"
23
+ gem.authors = ["obie quelland"]
24
+ end
25
+ Jeweler::RubygemsDotOrgTasks.new
26
+
27
+ require 'rdoc/task'
28
+ Rake::RDocTask.new do |rdoc|
29
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
30
+
31
+ rdoc.rdoc_dir = 'rdoc'
32
+ rdoc.title = "rd3 #{version}"
33
+ rdoc.rdoc_files.include('README*')
34
+ rdoc.rdoc_files.include('lib/**/*.rb')
35
+ end
36
+
37
+ # Get spec rake tasks working in RSpec 2.0
38
+ require 'rspec/core/rake_task'
39
+
40
+ desc 'Default: run specs.'
41
+ task :default => :spec
42
+
43
+ desc "Run specs"
44
+ RSpec::Core::RakeTask.new do |t|
45
+ end
46
+
47
+ RSpec::Core::RakeTask.new(:fast) do |t|
48
+ t.rspec_opts = '--tag ~speed:slow'
49
+ end
50
+
51
+ RSpec::Core::RakeTask.new(:slow) do |t|
52
+ t.rspec_opts = '--tag speed:slow'
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/lib/rd3.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'active_model'
3
+ require 'require_all'
4
+
5
+ require 'rd3/model'
6
+ require 'rd3/repository'
7
+ require 'rd3/configuration'
8
+ require_rel '../lib/rd3/data_providers'
9
+ require 'rd3/railtie' if defined?(Rails)
10
+ #require 'active_support'
11
+ #require 'active_model'
12
+
13
+ #require 'rd3/railtie' if defined?(Rails)
14
+ #require_rel '../lib' #.reject {|f| railtie.rb}
15
+
16
+ module RD3
17
+ class << self
18
+ attr_reader :config
19
+ end
20
+
21
+ def self.configure(args)
22
+ configuration = nil
23
+ unless args.nil? || args.empty?
24
+ configuration = RD3::Configuration.new
25
+ configuration.environment = args[:environment]
26
+ configuration.config_file_directory = args[:config_file_directory]
27
+ configuration.enable_logical_deletes = args[:enable_logical_deletes]
28
+ end
29
+ @config = configuration
30
+ #@config ||= configuration
31
+ end
32
+ end # module RD3
@@ -0,0 +1,5 @@
1
+ module RD3
2
+ class Configuration
3
+ attr_accessor :environment, :config_file_directory, :enable_logical_deletes
4
+ end
5
+ end
@@ -0,0 +1,67 @@
1
+ require 'yaml'
2
+ require 'waz-storage'
3
+ require 'waz-tables'
4
+
5
+ module RD3
6
+ module DataProviders
7
+ module AzureTableStorage
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ def self.client
12
+ return @client if @client
13
+
14
+ yml_config = YAML.load(File.read("#{RD3.config.config_file_directory}/#{self.config_file_name}.yml"))[RD3.config.environment.to_s]
15
+ yml_config = yml_config.symbolize_keys
16
+
17
+ WAZ::Storage::Base.establish_connection!(:account_name => yml_config[:storage_account_name],
18
+ :access_key => yml_config[:primary_access_key])
19
+ @client = WAZ::Tables::Table.service_instance
20
+ end
21
+
22
+ def self.save(attributes)
23
+ # convert the key attribute to partition key
24
+ # NOTE: don't overwrite the partion key if it has already been set
25
+ attributes[:partition_key] ||= partition_key = attributes.delete(:key)
26
+
27
+ unless attributes[:Timestamp]
28
+ self.client.insert_entity(self.table_name.to_s, attributes)
29
+ else
30
+ self.client.update_entity(self.table_name.to_s, attributes)
31
+ end
32
+
33
+ partition_key
34
+ end
35
+
36
+ def self.find_by_key(key, opts={})
37
+ begin
38
+ if db_instance = @client.get_entity(self.table_name.to_s, key, opts[:row_key])
39
+ db_instance unless self._logical_only(opts) && !db_instance[:active]
40
+ end
41
+ rescue RestClient::ResourceNotFound # returns nil
42
+ end
43
+ end
44
+
45
+ def self.delete(key, opts={})
46
+ if self._logical_only(opts)
47
+ attributes= {:partition_key => key,
48
+ :row_key => opts[:row_key],
49
+ :active => false}
50
+ @client.update_entity(self.table_name.to_s, attributes)
51
+ else
52
+ @client.delete_entity(self.table_name.to_s, key, opts[:row_key])
53
+ end
54
+ end
55
+
56
+ def self._logical_only(opts)
57
+ unless opts[:logical_only].nil?
58
+ opts[:logical_only]
59
+ else
60
+ RD3.config.enable_logical_deletes
61
+ end
62
+ end
63
+ end # included do
64
+
65
+ end # module AzureTableStorage
66
+ end # module DataProviders
67
+ end # module RD3
@@ -0,0 +1,62 @@
1
+ require 'yaml'
2
+ require 'sequel'
3
+
4
+ module RD3
5
+ module DataProviders
6
+ module Rdbms
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ def self.client
11
+ return @client if @client
12
+
13
+ yml_config = YAML.load(File.read("#{RD3.config.config_file_directory}/#{self.config_file_name}.yml"))[RD3.config.environment.to_s]
14
+ yml_config = yml_config.symbolize_keys
15
+
16
+ @client = Sequel.connect(yml_config)
17
+ end
18
+
19
+ def self.save(attributes)
20
+ if id = attributes.delete(:id)
21
+ self._table.where('id = ?', id).update(attributes)
22
+ else
23
+ id = self._table.insert(attributes)
24
+ end
25
+
26
+ id
27
+ end
28
+
29
+ def self.find_by_key(key, opts={})
30
+ # logically deleted instances will return nil
31
+ # if the key exists, but the active flag is false
32
+ filter_logical_deletes = unless opts[:logical_only].nil?
33
+ opts[:logical_only]
34
+ else
35
+ RD3.config.enable_logical_deletes
36
+ end
37
+ filter = {:id => key}
38
+ filter.merge!(:active => filter_logical_deletes) if filter_logical_deletes
39
+ self._table.where(filter).first
40
+ end
41
+
42
+ def self.delete(id, opts)
43
+ logical_delete = unless opts[:logical_only].nil?
44
+ opts[:logical_only]
45
+ else
46
+ RD3.config.enable_logical_deletes
47
+ end
48
+ if logical_delete
49
+ self.save({:id => id, :active => false})
50
+ else
51
+ self._table.where('id = ?', id).delete
52
+ end
53
+ end
54
+
55
+ def self._table
56
+ self.client[self.table_name]
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
data/lib/rd3/model.rb ADDED
@@ -0,0 +1,108 @@
1
+ require 'active_support/core_ext' # necessary for Hash.to_json and Hash.as_json
2
+
3
+ module RD3
4
+ module Model
5
+ extend ActiveSupport::Concern
6
+ include ActiveModel::Validations
7
+
8
+ included do
9
+ def self.class_attributes
10
+ @class_attributes
11
+ end
12
+
13
+ # NOTE: this method must be declared
14
+ # before the attribute declarations
15
+ def self.attribute(*args)
16
+ @class_attributes ||= []
17
+ attributes_with_defaults = args.reduce({}) do |hash, arg|
18
+ arg.instance_of?(Hash) ? hash.merge(arg) : hash.merge(arg => nil)
19
+ end
20
+ @class_attributes.concat(attributes_with_defaults.keys)
21
+
22
+ attributes_with_defaults.each do |attribute, default|
23
+ getter = "@#{attribute}"
24
+ getter.prepend("@#{attribute} = #{default} if @#{attribute}.nil?;") unless default.nil?
25
+
26
+ self.module_eval <<-EVAL
27
+ def #{attribute}=(value)
28
+ # set dirty flag
29
+ @dirty = true unless @dirty || @#{attribute} == value
30
+ @#{attribute} = value
31
+ end
32
+ def #{attribute}
33
+ #{getter}
34
+ end
35
+ EVAL
36
+ end
37
+ end
38
+
39
+ attribute :id, :created_at, :updated_at
40
+ attribute :active=>true
41
+ end
42
+
43
+ # NOTE: 1) we can create a new instance with a hash
44
+ # in such a case, default values will be set
45
+ # 2) we can also create a new instance by COPYING
46
+ # properties from one object to another via
47
+ # its attributes
48
+ # in such a case, default values will NOT be set
49
+ def initialize(*args)
50
+ # default to an empty hash if Class.new is called, i.e., args = nil
51
+ obj = args[0] || {}
52
+
53
+ # an instance SHOULD be marked as dirty if:
54
+ # 1) it's initialized w/ a non-empty hash
55
+ #
56
+ # it SHOULD NOT be marked as dirty if:
57
+ # 1) Class.new is called (empty hash)
58
+ # 2) we're mapping from one object to another
59
+ is_dirty = obj.instance_of?(Hash) && !obj.blank?
60
+
61
+ # grab attributes hash if we're dealing w/ mapping
62
+ # an object instance
63
+ obj = obj.attributes unless obj.instance_of? Hash
64
+
65
+ # map properties
66
+ obj.each do |k,v|
67
+ self.send("#{k}=", v) if self.class_attributes.include? k
68
+ end
69
+
70
+ # reset dirty flag
71
+ @dirty = is_dirty
72
+
73
+ # return self for method chaining
74
+ self
75
+ end
76
+
77
+ # tracks whether or not the instance
78
+ # has been updated/changed post initialization
79
+ def dirty?
80
+ return @dirty ||= false
81
+ end
82
+
83
+ def persisted?
84
+ id.present?
85
+ end
86
+
87
+ def class_attributes
88
+ return self.class.class_attributes
89
+ end
90
+
91
+ def attributes
92
+ self.instance_values.select { |key| class_attributes.include? key.to_sym }.symbolize_keys
93
+ end
94
+
95
+ # add errors to errors collection
96
+ # allows errors to bubble up from a child
97
+ # model to its parent model when working
98
+ # with repositories
99
+ def errors=(value)
100
+ unless value.blank?
101
+ value.each do |k, v|
102
+ self.errors[k] = v
103
+ end
104
+ end
105
+ end
106
+
107
+ end # module Model
108
+ end # module RD3