rd3 0.0.1

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