trusty 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 396691c71380d978d8119d8bcb3f0d32491f1888
4
- data.tar.gz: 2b29a3e6491960ed1f96630e7ca213305dbda6f4
3
+ metadata.gz: d7f6a8980814e0ac15c4f5cacc0590d44c1f571d
4
+ data.tar.gz: 02c63e4b122e0a2e6593f1310494d37d6eb59185
5
5
  SHA512:
6
- metadata.gz: bb6b586a37a1060600fbeca34fa3fea9826f020cae310be08cda2f77b4e3da74554728cf3c9ade77e2586b24c26e4a934c9124eaf4d6528452f7e545773843ef
7
- data.tar.gz: d39b0d14db882904031780ae22a5e2f02284a620c9003090b8b1dd0d8c7397e895ec469ea28ab655582cf25659a5a8bffa677c32ab1992f4c3f11053b47cc0de
6
+ metadata.gz: 600db5f18e699ece7fe625e77ef13159726ddc13d3276ec126db0acf49e81ab27ec61e2499fbabbacceaf145c0a132119e1ce008374f1790e9291ec04080b2ad
7
+ data.tar.gz: fd053f427ab015f0cc2fc003d3d1bc02ae20aec2256f438d42a1520db5044123758aff6d477ae24a81d1c0f824a152a5f5c1d88747abb4cd974190d4feb7d4b5
data/README.md CHANGED
@@ -18,7 +18,139 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- TODO: Write usage instructions here
21
+ Trusty is a library of a bunch of useful utilities.
22
+
23
+ ### Environment Variables
24
+
25
+ Use `Trusty::Environment` (or the shorthand `Vars`) to access environment variables.
26
+ What's handy is that it will load up environment variables from a `env.yml` file and merge it with `ENV`.
27
+ By default, it loads the section of the YAML file based on the current `ENV['RAILS_ENV']` and `ENV['RACK_ENV']`.
28
+ You can customize the section to load by setting `ENV['ENV_SECTION']` to a custom name.
29
+
30
+ ```Ruby
31
+ # See what the default section name is that will be pulled from env.yml
32
+ section_name = Vars.default_env_section
33
+
34
+ # The following are equivalent
35
+ api_key = Vars['API_KEY']
36
+ api_key = Vars.env['API_KEY']
37
+ api_key = Vars.env.api_key
38
+
39
+ # You can load any YAML file into a Vars property dynamically (should return a Hash).
40
+ # Files will be loaded from Rails' "config" directory by default. These are equivalent:
41
+ custom_config = Vars.custom_config # loads config/custom_config.yml as a Hashie::Mash
42
+ custom_config = Vars.config.custom_config
43
+
44
+ # add paths to find YAML files in other locations (especially if not using Rails)
45
+ paths = [
46
+ Rails.root.join('config'), # added by default
47
+ Rails.root, # search in the root
48
+ Rails.root.join('custom', 'folder') # look in custom/folder/* inside Rails app
49
+ ]
50
+
51
+ Vars.paths += paths
52
+
53
+ # This will find the another_config.yml file under the custom path
54
+ another_config = Vars.another_config # loads custom/folder/another_config.yml as a Hashie::Mash
55
+ another_config = Vars.config.another_config
56
+
57
+ # To access a list of all YAML files that have been loaded
58
+ hash_of_configs = Vars.config
59
+ ```
60
+
61
+ ### Omniauth
62
+
63
+ To easily map Omniauth data to your `User` and/or `Idenity` models with a `User#identities` relationship, use the `Trusty::Omniauth::ProviderMapper` class. Both ActiveRecord and Mongoid are supported.
64
+
65
+ Add this line to your application's Gemfile:
66
+
67
+ gem 'trusty', require: 'trusty/omniauth'
68
+
69
+ Just pass in the Omniauth `Hash` provided in the environment variable to the [`ProviderMapper`](lib/trusty/omniauth/provider_mapper.rb) and you can use the helper methods to populate your models. Check out for more options.
70
+
71
+ ```Ruby
72
+ omniauth = request.env['omniauth.auth']
73
+
74
+ # these are some default options that you can override
75
+ options = {
76
+ user_model: User,
77
+ user_attributes_names: User.column_names,
78
+ identity_model: Identity,
79
+ identity_attribute_names: Identity.column_names
80
+ }
81
+
82
+ # Here is a class that you can use to deal with your model instances,
83
+ # whether finding a user based on their identity or adding a new identity to a user,
84
+ # or even creating a new user with the identity.
85
+ mapper = Trusty::Omniauth::ProviderMapper.new(omniauth, options)
86
+ ```
87
+
88
+ ### YAML
89
+
90
+ Use `Trusty::Utilities::Yaml` to load a file or content.
91
+ An instance of `Trusty::Utilities::YamlContext` is used for rendering YAML and is used as the context.
92
+ If you pass a block to the method where you pass in the file or content, you can include modules and so on in the context if necessary.
93
+
94
+ ```Ruby
95
+ # load a file
96
+ relative_path = "yaml/filename.yml"
97
+
98
+ # optional: pass in an array of paths where to search for the file
99
+ optional_paths = [ Rails.root, Rails.root.join('config') ]
100
+
101
+ # Render YAML and any ERB blocks
102
+ result = Trusty::Utilities::Yaml.load_file(relative_path, optional_paths) do |context|
103
+ # optionally use a block to modify the context (YamlContext instance)
104
+ end
105
+ ```
106
+
107
+ You can use `YamlContext` directly:
108
+
109
+ ```Ruby
110
+ # load the content from the file
111
+ content = File.read Trusty::Utilities::PathFinder.find(relative_path, optional_paths)
112
+
113
+ # render the YAML as a Ruby object
114
+ result = Trusty::Utilities::YamlContext.render content do |context|
115
+ # optionally use a block to modify the context (YamlContext instance)
116
+ end
117
+ ```
118
+
119
+ ### `method_missing` Helpers
120
+
121
+ If you want to dynamically add boolean methods to a class, use `Trusty::Utilities::MethodName`.
122
+ It will allow you to return a boolean for a method that ends with '?'.
123
+ It will also dynamically define the methods for you with a simple module to extend your class called `Trusty::Utilities::MethodNameExtensions`.
124
+
125
+ If you want more control over what happens in your `method_missing` method, you can use [`MethodName`](lib/trusty/utilities/method_name.rb) instances to give you information about the method name you are handling.
126
+
127
+ ```Ruby
128
+ target = MyModel.new
129
+ method_name = "confirmed_at?"
130
+
131
+ # get info about the method name inside method_missing
132
+ method_info = Trusty::Utilities::MethodName.new(method_name)
133
+
134
+ # see if it's a boolean method
135
+ method_info.boolean? # true
136
+
137
+ # if you want to see what the value is for the method name without the '?'
138
+ method_name.base_value_for target # "2013-10-30 19:41:40 UTC"
139
+
140
+ # get the boolean value
141
+ method_name.method_value_for target # true
142
+
143
+ # define the helper method on the target (if it isn't already on there)
144
+ method_name.define_for target # true
145
+ ```
146
+
147
+ Make this functionality automatic by including the `Trusty::Utilities::MethodNameExtensions` module in your class.
148
+
149
+ ```Ruby
150
+ class MyModel
151
+ include Trusty::Utilities::MethodNameExtensions
152
+ end
153
+ ```
22
154
 
23
155
  ## Contributing
24
156
 
@@ -48,7 +48,7 @@ module Trusty
48
48
  end
49
49
 
50
50
  def default_env_section
51
- @default_env_section ||= ENV['ENV_SECTION'] || Rails.env
51
+ @default_env_section ||= ENV['ENV_SECTION'] || ENV['RAILS_ENV'] || ENV['RACK_ENV']
52
52
  end
53
53
 
54
54
  def config(default_value = nil)
@@ -59,7 +59,7 @@ module Trusty
59
59
  end
60
60
 
61
61
  def paths
62
- @paths ||= [ Rails.root.join("config").to_s ]
62
+ @paths ||= defined?(Rails) ? [ Rails.root.join("config").to_s ] : []
63
63
  end
64
64
 
65
65
  # dynamically add methods that forward to config
@@ -96,4 +96,7 @@ module Trusty
96
96
  # create class methods
97
97
  extend ClassMethods
98
98
  end
99
- end
99
+ end
100
+
101
+ # copy out of namespace
102
+ Vars = Trusty::Environment
@@ -0,0 +1,15 @@
1
+ module Trusty
2
+ module Omniauth
3
+ module MappingHelpers
4
+ def clean(value, *filters, &default_value)
5
+ default_value ||= lambda{ nil }
6
+
7
+ filters.each do |method_name|
8
+ value = value.to_s.send(method_name)
9
+ end
10
+
11
+ value.blank? ? default_value.call : value
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,49 @@
1
+ module Trusty
2
+ module Omniauth
3
+ class ModelImporter
4
+ include MappingHelpers
5
+
6
+ def initialize(provider, options = {})
7
+ @provider = provider
8
+ @options = options
9
+ end
10
+
11
+ def model
12
+ @options[:model]
13
+ end
14
+
15
+ def attribute_names
16
+ @attribute_names ||= @options[:attribute_names] || column_names
17
+ end
18
+
19
+ def attributes(*filter_attribute_names)
20
+ @attributes ||= @provider.attributes(*attribute_names).merge!(@options[:attributes])
21
+
22
+ if filter_attribute_names.any?
23
+ @attributes.slice(*filter_attribute_names)
24
+ else
25
+ @attributes.dup
26
+ end
27
+ end
28
+
29
+ def build_record
30
+ model.new(attributes, :without_protection => true)
31
+ end
32
+
33
+ def update_record!(record)
34
+ record.update_attributes!(attributes, :without_protection => true)
35
+ end
36
+
37
+ def column_names
38
+ @column_names ||= if model.respond_to? :column_names
39
+ model.column_names.map(&:to_sym)
40
+ elsif model.respond_to? :fields
41
+ model.fields.map{|c| c[1].name.to_sym}
42
+ else
43
+ []
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,155 @@
1
+ module Trusty
2
+ module Omniauth
3
+ class ProviderMapper
4
+ include MappingHelpers
5
+
6
+ attr_reader :provider_name, :provider_attributes, :options
7
+ attr_reader :provider_identity, :provider_user
8
+
9
+ # provider_attributes = OmniAuth data
10
+ # options =
11
+ # - :user_model = User model
12
+ # - :user_attributes = Hash of attributes to merge into user_attributes
13
+ # - :user_attributes_names = Array of attribute names to copy from Omniauth data (default: User.column_names)
14
+ # - :identity_model = Identity model
15
+ # - :identity_attributes = Hash of attributes to merge into identity_attributes
16
+ # - :identity_attribute_names = Array of attribute names to copy from Omniauth data (default: Identity.column_names)
17
+ # - :skip_raw_info (default: false) = Boolean whether to exclude OmniAuth "extra" data in identity_attributes[:raw_info]
18
+ # - :skip_nils (default: true) = Boolean whether to remove attributes with nil values
19
+ def initialize(provider_attributes, options = {})
20
+ @provider_attributes = provider_attributes.with_indifferent_access
21
+ @provider_name = provider_attributes['provider']
22
+ @options = {
23
+ :user_attributes => {},
24
+ :identity_attributes => {},
25
+ :skip_raw_info => false,
26
+ :skip_nils => true
27
+ }.merge(options)
28
+
29
+ @provider_identity = ModelMapper.new(self,
30
+ :model => @options[:identity_model] || Identity,
31
+ :attributes => @options[:identity_attributes],
32
+ :attribute_names => @options[:identity_attribute_names]
33
+ )
34
+ @provider_user = ModelMapper.new(self,
35
+ :model => @options[:user_model] || User,
36
+ :attributes => @options[:user_attributes],
37
+ :attribute_names => @options[:user_attribute_names]
38
+ )
39
+ end
40
+
41
+ # Query existing
42
+
43
+ def user
44
+ # first try to find the user based on provider/uid combo
45
+ @user ||= find_user_by_identity
46
+ # find the user by email if not found by identity
47
+ @user ||= find_user_by_email
48
+ end
49
+
50
+ def identity
51
+ @identity ||= find_identity_by_user
52
+ end
53
+
54
+ def user_exists?
55
+ !user.nil?
56
+ end
57
+
58
+ def identity_exists?
59
+ !identity.nil?
60
+ end
61
+
62
+ # USER
63
+
64
+ def build_user
65
+ @provider_user.build_record
66
+ end
67
+
68
+ # IDENTITY
69
+
70
+ def build_identity
71
+ @provider_identity.build_record
72
+ end
73
+
74
+ def build_identity_for_user(user)
75
+ build_identity.tap do |identity|
76
+ # this assumes there is an inverse relationship automatically created
77
+ # such as user.identities would now contain this identity for the user
78
+ identity.user = user
79
+ end
80
+ end
81
+
82
+ def update_existing_identity!
83
+ raise "Identity doesn't exist!" unless identity
84
+
85
+ @provider_identity.update_record!(identity)
86
+ end
87
+
88
+ ###### General ######
89
+
90
+ def attributes(*filter_attribute_names)
91
+ unless @attributes
92
+ info = provider_attributes.fetch('info', {})
93
+ credentials = provider_attributes['credentials']
94
+
95
+ name = clean(info['name']) { [info['first_name'], info['last_name']].join(" ").strip }
96
+ first_name = clean(info['first_name']) { name.split(/\s+/, 2).first }
97
+ last_name = clean(info['last_name']) { name.split(/\s+/, 2).last }
98
+
99
+ @attributes = {
100
+ :provider => provider_name,
101
+ :uid => clean(provider_attributes['uid']),
102
+ :name => name,
103
+ :email => clean(info['email'], :downcase, :strip),
104
+ :verified => provider_attributes['extra']['raw_info']['verified_email'] == true,
105
+ :username => clean(info['nickname']),
106
+ :first_name => first_name,
107
+ :middle_name => clean(info['middle_name']),
108
+ :last_name => last_name,
109
+ :phone => clean(info['phone']),
110
+ :image_url => info['image'],
111
+ :profile_url => info.fetch('urls', {})['public_profile'],
112
+ :token => clean(credentials['token']),
113
+ :secret => clean(credentials['secret']),
114
+ :refresh_token => clean(credentials['refresh_token']),
115
+ :expires => credentials['expires'] == true,
116
+ :expires_at => (Time.at(credentials['expires_at']) rescue nil),
117
+ :raw_info => provider_attributes['extra'].except('access_token').as_json,
118
+ # extra
119
+ :time_zone => Time.zone.name
120
+ }.with_indifferent_access
121
+
122
+ @attributes.reject!{|_,value| value.nil?} if options[:skip_nils]
123
+ @attributes.delete(:raw_info) if options[:skip_raw_info]
124
+ end
125
+
126
+ if filter_attribute_names.any?
127
+ @attributes.slice(*filter_attribute_names)
128
+ else
129
+ @attributes.dup
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ def find_user_by_identity
136
+ if defined?(Mongoid::Document) && @provider_user.model.include?(Mongoid::Document)
137
+ @provider_user.model.elem_match(:identities => @provider_identity.attributes(:provider, :uid)).first
138
+ else
139
+ @provider_user.model.where(
140
+ :id => @provider_identity.model.where( @provider_identity.attributes(:provider, :uid) ).select(:user_id)
141
+ ).first
142
+ end
143
+ end
144
+
145
+ def find_user_by_email
146
+ @provider_user.model.where( @provider_identity.attributes(:email) ).first
147
+ end
148
+
149
+ def find_identity_by_user
150
+ user && user.identities.where( @provider_identity.attributes(:provider, :uid) ).first
151
+ end
152
+
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,3 @@
1
+ require_relative 'omniauth/mapping_helpers'
2
+ require_relative 'omniauth/model_mapper'
3
+ require_relative 'omniauth/provider_mapper'
@@ -2,15 +2,16 @@ module Trusty
2
2
  module Utilities
3
3
  module Yaml
4
4
  module ClassMethods
5
- def load_file(filename, paths = [])
5
+ def load_file(filename, paths = [], &block)
6
6
  # allow multiple filenames and use the first one that exists
7
7
  if path = PathFinder.find(filename, paths)
8
- source = File.read(path)
9
- source = ERB.new(source).result
10
-
11
- YAML.load(source)
8
+ load_content(File.read(path), &block)
12
9
  end
13
10
  end
11
+
12
+ def load_content(content, &block)
13
+ YamlContext.render(content, &block)
14
+ end
14
15
  end
15
16
 
16
17
  extend ClassMethods
@@ -0,0 +1,19 @@
1
+ module Trusty
2
+ module Utilities
3
+ class YamlContext
4
+ def self.render(content, &block)
5
+ new(content, &block).render
6
+ end
7
+
8
+ def initialize(content, &block)
9
+ @content = content
10
+
11
+ yield(self) if block_given?
12
+ end
13
+
14
+ def render
15
+ YAML.load ERB.new(@content).result(binding)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,9 +2,4 @@ require_relative "utilities/method_name"
2
2
  require_relative "utilities/method_name_extensions"
3
3
  require_relative "utilities/path_finder"
4
4
  require_relative "utilities/yaml"
5
-
6
- module Trusty
7
- module Utilities
8
-
9
- end
10
- end
5
+ require_relative "utilities/yaml_context"
@@ -1,3 +1,3 @@
1
1
  module Trusty
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/trusty.rb CHANGED
@@ -1,9 +1,2 @@
1
1
  require "trusty/version"
2
2
  require "trusty/environment"
3
-
4
- module Trusty
5
-
6
- end
7
-
8
- # copy out of namespace
9
- Vars = Trusty::Environment
data/trusty.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["joel@joelvanhorn.com"]
11
11
  spec.description = %q{Trusty is a configuration and utilities library.}
12
12
  spec.summary = %q{Trusty allows you to manage environment variables and other common configuration challenges.}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/joelvh/trusty"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -20,6 +20,9 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "omniauth"
24
+ spec.add_development_dependency "rails"
23
25
 
24
26
  spec.add_dependency "dotenv", ">= 0.9.0"
27
+ spec.add_dependency "hashie", ">= 2.0"
25
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trusty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Van Horn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-20 00:00:00.000000000 Z
11
+ date: 2013-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: omniauth
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: dotenv
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +80,20 @@ dependencies:
52
80
  - - '>='
53
81
  - !ruby/object:Gem::Version
54
82
  version: 0.9.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: hashie
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '2.0'
55
97
  description: Trusty is a configuration and utilities library.
56
98
  email:
57
99
  - joel@joelvanhorn.com
@@ -67,14 +109,19 @@ files:
67
109
  - lib/trusty.rb
68
110
  - lib/trusty/environment.rb
69
111
  - lib/trusty/environment/dot_file_parser.rb
112
+ - lib/trusty/omniauth.rb
113
+ - lib/trusty/omniauth/mapping_helpers.rb
114
+ - lib/trusty/omniauth/model_mapper.rb
115
+ - lib/trusty/omniauth/provider_mapper.rb
70
116
  - lib/trusty/utilities.rb
71
117
  - lib/trusty/utilities/method_name.rb
72
118
  - lib/trusty/utilities/method_name_extensions.rb
73
119
  - lib/trusty/utilities/path_finder.rb
74
120
  - lib/trusty/utilities/yaml.rb
121
+ - lib/trusty/utilities/yaml_context.rb
75
122
  - lib/trusty/version.rb
76
123
  - trusty.gemspec
77
- homepage: ''
124
+ homepage: https://github.com/joelvh/trusty
78
125
  licenses:
79
126
  - MIT
80
127
  metadata: {}