trusty 0.0.1 → 0.0.2

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