friendly-attributes 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +12 -7
- data/LICENSE.txt +1 -1
- data/README.md +109 -0
- data/lib/friendly_attributes.rb +2 -1
- data/lib/friendly_attributes/base.rb +49 -0
- data/lib/friendly_attributes/class_methods.rb +13 -12
- data/lib/friendly_attributes/configuration.rb +35 -0
- data/lib/friendly_attributes/details_delegator.rb +98 -28
- data/lib/friendly_attributes/instance_methods.rb +120 -18
- data/lib/friendly_attributes/test/matchers.rb +11 -1
- metadata +144 -75
- data/README.rdoc +0 -21
- data/lib/friendly_attributes/details.rb +0 -17
data/CHANGELOG.md
CHANGED
@@ -1,28 +1,33 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
### 0.7.0
|
5
|
+
* (ihoka,cristi) Support for associating multiple FriendlyAttributes models with a single ActiveRecord model
|
6
|
+
* (ihoka,cristi) FriendlyAttributes::Details renamed to FriendlyAttributes::Base
|
7
|
+
* (ihoka,cristi) Documentation
|
8
|
+
|
4
9
|
### 0.6.1
|
5
|
-
* (ihoka) Extended #changed? on the ActiveRecord model to indicate the record has been changed if the associated Friendly has changed.
|
10
|
+
* (ihoka,cristi) Extended #changed? on the ActiveRecord model to indicate the record has been changed if the associated Friendly has changed.
|
6
11
|
|
7
12
|
### 0.6.0
|
8
|
-
* (ihoka) Added #friendly_details_build_options method to the ActiveRecord model, allowing to specify default attributes when initially building the Friendly model.
|
13
|
+
* (ihoka,cristi) Added #friendly_details_build_options method to the ActiveRecord model, allowing to specify default attributes when initially building the Friendly model.
|
9
14
|
|
10
15
|
### 0.5.0
|
11
16
|
|
12
|
-
* (ihoka) Added configurable active_record_key to the FriendlyDetails model. active_record_key affects the name of the generated Friendly index table and the attribute in which the ActiveRecord model ID is stored. It defaults to :active_record_id.
|
17
|
+
* (ihoka,cristi) Added configurable active_record_key to the FriendlyDetails model. active_record_key affects the name of the generated Friendly index table and the attribute in which the ActiveRecord model ID is stored. It defaults to :active_record_id.
|
13
18
|
|
14
19
|
### 0.4.0
|
15
20
|
|
16
|
-
* (ihoka) Added #attributes method to FriendlyAttributes::Details base class.
|
21
|
+
* (ihoka,cristi) Added #attributes method to FriendlyAttributes::Details base class.
|
17
22
|
|
18
23
|
### 0.3.2
|
19
24
|
|
20
|
-
* (ihoka) Added description to spec matcher.
|
25
|
+
* (ihoka,cristi) Added description to spec matcher.
|
21
26
|
|
22
27
|
### 0.3.1
|
23
28
|
|
24
|
-
* (ihoka) added spec matchers
|
29
|
+
* (ihoka,cristi) added spec matchers
|
25
30
|
|
26
31
|
### 0.3.0
|
27
32
|
|
28
|
-
* (ihoka) Extended the DSL to allow passing a hash of options when defining friendly_attributes.
|
33
|
+
* (ihoka,cristi) Extended the DSL to allow passing a hash of options when defining friendly_attributes.
|
data/LICENSE.txt
CHANGED
data/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# Friendly Attributes
|
2
|
+
|
3
|
+
Extend your ActiveRecord models with attributes dynamically, without any schema migrations.
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
[FriendlyORM][friendly] is an implementation of a document based storage on top of MySQL.
|
8
|
+
|
9
|
+
FriendlyAttributes associates FriendlyORM documents with your ActiveRecord models, handles delegation of attribute accessors and automatically saves and destroys the associated document.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Currently, only ActiveRecord 2.3.x is supported. ActiveRecord 3 is not supported yet.
|
14
|
+
|
15
|
+
Add it to your Gemfile:
|
16
|
+
|
17
|
+
gem 'friendly-attributes'
|
18
|
+
|
19
|
+
or, to your `config/environment.rb` in Rails:
|
20
|
+
|
21
|
+
config.gem 'friendly-attributes'
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
To use Friendly Attributes, you must have an existing ActiveRecord model:
|
26
|
+
|
27
|
+
# app/models/user.rb
|
28
|
+
class User < ActiveRecord::Base
|
29
|
+
# ...
|
30
|
+
end
|
31
|
+
|
32
|
+
Create a class for storing your Friendly document, extending `FriendlyAttributes::Base`:
|
33
|
+
|
34
|
+
# app/models/user_details.rb
|
35
|
+
class UserDetails < FriendlyAttributes::Base
|
36
|
+
end
|
37
|
+
|
38
|
+
`FriendlyAttributes::Base` mixes in `Friendly::Document`, so check out the [Friendly ORM documentation][friendly] for what options you can use here, like defining indexes and scopes.
|
39
|
+
|
40
|
+
Configure the attributes you need to extend your ActiveRecord model:
|
41
|
+
|
42
|
+
# app/models/account.rb
|
43
|
+
class User < ActiveRecord::Base
|
44
|
+
include FriendlyAttributes
|
45
|
+
|
46
|
+
friendly_details UserDetails, {
|
47
|
+
String => :github_username,
|
48
|
+
Integer => [:shoe_size, :birth_year]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
If using Rails, configure the database to be used by Friendly, by creating `config/friendly.yml` and specifying the configuration. If you don't mind mixing tables, the database can be the same as the one configured for Rails, but it does not have to be. Note that Friendly automatically creates a table for each index you define in your Friendly document.
|
53
|
+
|
54
|
+
# config/friendly.yml
|
55
|
+
development:
|
56
|
+
adapter: mysql
|
57
|
+
socket: /tmp/mysql.sock
|
58
|
+
database: friendly_database_development
|
59
|
+
username: root
|
60
|
+
password:
|
61
|
+
|
62
|
+
Use the Rails console or a rake task to create the Friendly document tables:
|
63
|
+
|
64
|
+
Friendly.create_tables!
|
65
|
+
|
66
|
+
Once complete, you can use your Friendly Attributes just like you would regular ActiveRecord attributes:
|
67
|
+
|
68
|
+
user = User.first
|
69
|
+
user.shoe_size = 42
|
70
|
+
user.save!
|
71
|
+
|
72
|
+
## Documentation
|
73
|
+
|
74
|
+
Check out the source documentation for more information about usage.
|
75
|
+
|
76
|
+
## Development
|
77
|
+
|
78
|
+
In order to setup a development environment and run the specs, you need Bundler:
|
79
|
+
|
80
|
+
gem install bundler
|
81
|
+
|
82
|
+
Then, install the dependencies:
|
83
|
+
|
84
|
+
bundle install
|
85
|
+
|
86
|
+
Create a database to use for runnning specs:
|
87
|
+
|
88
|
+
mysqladmin create friendly_attributes_test
|
89
|
+
|
90
|
+
Copy spec/config.yml.example and customize it with the database you have created:
|
91
|
+
|
92
|
+
cp spec/config.yml.sample spec/config.yml
|
93
|
+
|
94
|
+
Run the specs:
|
95
|
+
|
96
|
+
rake spec
|
97
|
+
|
98
|
+
## Credits
|
99
|
+
|
100
|
+
Friendly Attributes was developed by [Istvan Hoka][ihoka] and [Cristi Duma][cduma].
|
101
|
+
|
102
|
+
Copyright (c) 2011 Aissac Labs. See [LICENSE.txt][license] for further details.
|
103
|
+
|
104
|
+
[github]: http://github.com/ihoka/friendly-attributes
|
105
|
+
[friendly]: http://github.com/jamesgolick/friendly
|
106
|
+
[ihoka]: http://istvanhoka.com
|
107
|
+
[cduma]: http://twitter.com/cristiduma
|
108
|
+
[blinksale]: http://www.blinksale.com
|
109
|
+
[license]: LICENSE.txt
|
data/lib/friendly_attributes.rb
CHANGED
@@ -4,8 +4,9 @@ require 'active_record'
|
|
4
4
|
module FriendlyAttributes
|
5
5
|
autoload :ClassMethods, 'friendly_attributes/class_methods'
|
6
6
|
autoload :InstanceMethods, 'friendly_attributes/instance_methods'
|
7
|
-
autoload :
|
7
|
+
autoload :Base, 'friendly_attributes/base'
|
8
8
|
autoload :DetailsDelegator, 'friendly_attributes/details_delegator'
|
9
|
+
autoload :Configuration, 'friendly_attributes/configuration'
|
9
10
|
|
10
11
|
module Test
|
11
12
|
autoload :Matchers, 'friendly_attributes/test/matchers'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module FriendlyAttributes
|
2
|
+
class Base
|
3
|
+
class << self
|
4
|
+
# Finds an existing Friendly model, associated with an ActiveRecord model,
|
5
|
+
# or builds a new Friendly model, using the specified options.
|
6
|
+
#
|
7
|
+
# @param [Integer] ActiveRecord model ID for which to find the associated Friendly model
|
8
|
+
# @param [Hash] options
|
9
|
+
# @return [FriendlyAttributes::Base] found or new record
|
10
|
+
def find_or_build_by_active_record_id(active_record_id, options={})
|
11
|
+
active_record_id && first(active_record_key => active_record_id) || new(options.merge(active_record_key => active_record_id))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Set the ID of the associated ActiveRecord model.
|
16
|
+
#
|
17
|
+
# Uses the :active_record_key property of the model.
|
18
|
+
#
|
19
|
+
# @param [String, Integer] active_record_id value to set the attribute
|
20
|
+
# @return [String, Integer] value
|
21
|
+
def write_active_record_id(active_record_id)
|
22
|
+
send(:"#{active_record_key}=", active_record_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get the ID of the associated ActiveRecord model.
|
26
|
+
#
|
27
|
+
# Uses the :active_record_key property of the model.
|
28
|
+
#
|
29
|
+
# @return [Integer] ActiveRecord ID
|
30
|
+
def read_active_record_id
|
31
|
+
send(active_record_key)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Save the FriendlyAttribute model if it has been changed.
|
35
|
+
# Before saving, it sets the specified active_record_id, to handle the case when it is a new record or has been reassigned.
|
36
|
+
#
|
37
|
+
# @param [Integer] active_record_id ID of the associated ActiveRecord model
|
38
|
+
# @return [true, false] result of saving the record
|
39
|
+
def update_if_changed_with_model(active_record_id)
|
40
|
+
write_active_record_id(active_record_id) unless read_active_record_id == active_record_id
|
41
|
+
save if changed?
|
42
|
+
end
|
43
|
+
|
44
|
+
# Alias for Friendly::Document#to_hash
|
45
|
+
def attributes
|
46
|
+
to_hash
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,5 +1,15 @@
|
|
1
1
|
module FriendlyAttributes
|
2
2
|
module ClassMethods
|
3
|
+
# Configure a Friendly Base model associated with an ActiveRecord model.
|
4
|
+
#
|
5
|
+
# @overload friendly_details(klass, attributes)
|
6
|
+
# @param [Class] klass FriendlyAttributes::Base instance used to extend the ActiveRecord model
|
7
|
+
# @param [Hash] attributes hash of types and attributes names with which to extend the ActiveRecord, through FriendlyAttributes::Base
|
8
|
+
#
|
9
|
+
# @overload friendly_details(klass, attributes, options)
|
10
|
+
# @param [Hash] options configuration options for extending the FriendlyAttributes extension (see {DetailsDelegator#initialize})
|
11
|
+
#
|
12
|
+
# @return [DetailsDelegator]
|
3
13
|
def friendly_details(*args, &block)
|
4
14
|
klass = args.shift
|
5
15
|
options = args.extract_options!
|
@@ -9,18 +19,9 @@ module FriendlyAttributes
|
|
9
19
|
options = {}
|
10
20
|
end
|
11
21
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
value.each { |v| delegated_attribute v, key }
|
16
|
-
else
|
17
|
-
delegated_attribute value, key
|
18
|
-
end
|
19
|
-
end
|
20
|
-
}
|
21
|
-
|
22
|
-
DetailsDelegator.new(klass, self, options, &block).tap do |dd|
|
23
|
-
dd.instance_eval(&delegate_options)
|
22
|
+
DetailsDelegator.new(klass, self, attributes, options, &block).tap do |dd|
|
23
|
+
dd.setup_delegated_attributes
|
24
|
+
dd.instance_eval(&block) if block_given?
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module FriendlyAttributes
|
2
|
+
class Configuration
|
3
|
+
attr_reader :details_delegators, :model, :attributes
|
4
|
+
|
5
|
+
def initialize(active_record_model)
|
6
|
+
@model = active_record_model
|
7
|
+
@details_delegators = []
|
8
|
+
@attributes = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(delegator)
|
12
|
+
details_delegators << delegator
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_attribute(name, friendly_model)
|
16
|
+
attributes[name] = friendly_model
|
17
|
+
end
|
18
|
+
|
19
|
+
def model_for_attribute(attr)
|
20
|
+
attributes[attr]
|
21
|
+
end
|
22
|
+
|
23
|
+
def friendly_models
|
24
|
+
details_delegators.map { |dd| dd.friendly_model }
|
25
|
+
end
|
26
|
+
|
27
|
+
def map_models(&block)
|
28
|
+
friendly_models.map(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def each_model(&block)
|
32
|
+
friendly_models.each(&block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,51 +1,121 @@
|
|
1
1
|
module FriendlyAttributes
|
2
2
|
class DetailsDelegator
|
3
|
-
attr_reader
|
3
|
+
# @attr_reader [Class] friendly_model FriendlyAttributes::Base class towa which the attributes are delegated
|
4
|
+
# @attr_reader [Class] active_record_model The ActiveRecord::Base class from which the attributes are delegated
|
5
|
+
# @attr_reader [Hash<Symbol, Class>] delegated_attributes Attributes delegated by this DetailsDelegator
|
6
|
+
attr_reader :friendly_model, :active_record_model, :delegated_attributes, :attributes
|
4
7
|
|
5
8
|
delegate :attribute, :indexes, :to => :friendly_model
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
include Friendly::Document
|
15
|
-
|
16
|
-
attribute _active_record_key, Integer
|
17
|
-
indexes _active_record_key
|
18
|
-
|
19
|
-
cattr_accessor :active_record_key
|
10
|
+
class << self
|
11
|
+
# Method name for the FriendlyAttributes::Base class passed to it.
|
12
|
+
#
|
13
|
+
# @param [Class] klass class we want to get the name for
|
14
|
+
# @return [Symbol] underscored name of the class.
|
15
|
+
def friendly_model_name(klass)
|
16
|
+
klass.name.underscore.to_sym
|
20
17
|
end
|
21
|
-
friendly_model.active_record_key = _active_record_key
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
@details ||= friendly_model.find_or_build_by_active_record_id(id, friendly_details_build_options)
|
31
|
-
end
|
19
|
+
# Instance variable name for the FriendlyAttributes::Base or `friendly_model_name` passed to it.
|
20
|
+
#
|
21
|
+
# @param [Symbol, String, Class] name_or_klass Class or name for which to generate the ivar name
|
22
|
+
# @return [Symbol] ivar name
|
23
|
+
def friendly_model_ivar(name_or_klass)
|
24
|
+
name_or_klass = friendly_model_name(name_or_klass) if name_or_klass.is_a?(Class)
|
25
|
+
:"@#{name_or_klass}_ivar"
|
32
26
|
end
|
33
27
|
|
34
|
-
|
28
|
+
# Reader method name for a certain FriendlyAttributes::Base instance associated with the model.
|
29
|
+
#
|
30
|
+
# @param [Symbol, String, Class] name_or_klass Class or name for which to generate the reader method name
|
31
|
+
# @return [Symbol] reader method name
|
32
|
+
def friendly_model_reader(name_or_klass)
|
33
|
+
name_or_klass = friendly_model_name(name_or_klass) if name_or_klass.is_a?(Class)
|
34
|
+
:"load_#{name_or_klass}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Initialize new DetailsDelegator instance.
|
39
|
+
#
|
40
|
+
# @param [Class] friendly_model FriendlyAttributes model, that inherits from FriendlyModel::Base
|
41
|
+
# @param [Class] ar_model ActiveRecord model, host for the FriendlyAttributes model
|
42
|
+
# @param [Hash] attributes
|
43
|
+
# @param [Hash] options
|
44
|
+
# @option options [Symbol] :active_record_key (:active_record_id) name of the 'foreign key' in which the FriendlyModel::Base instance keeps a reference to the ActiveRecord model
|
45
|
+
def initialize(friendly_model, ar_model, attributes, options={})
|
46
|
+
@active_record_model = ar_model
|
47
|
+
@friendly_model = friendly_model
|
48
|
+
@attributes = attributes
|
49
|
+
@delegated_attributes = {}
|
35
50
|
|
36
|
-
|
51
|
+
setup_friendly_model(options.delete(:active_record_key) || :active_record_id)
|
52
|
+
setup_active_record_model
|
37
53
|
end
|
38
54
|
|
39
55
|
def delegated_attribute(name, klass)
|
56
|
+
delegated_attributes[name] = klass
|
57
|
+
|
40
58
|
attribute name, klass
|
41
59
|
delegated_method(:"#{name}")
|
42
60
|
delegated_method(:"#{name}=")
|
61
|
+
|
62
|
+
active_record_model.friendly_attributes_configuration.add_attribute(name, friendly_model)
|
43
63
|
end
|
44
64
|
|
45
65
|
def delegated_method(name)
|
46
|
-
|
47
|
-
|
66
|
+
friendly_model = self.friendly_model
|
67
|
+
|
68
|
+
active_record_model.class_eval do
|
69
|
+
delegate :"#{name}", :to => FriendlyAttributes::DetailsDelegator.friendly_model_reader(friendly_model)
|
48
70
|
end
|
49
71
|
end
|
72
|
+
|
73
|
+
def setup_delegated_attributes
|
74
|
+
attributes.each do |key, value|
|
75
|
+
if Array === value
|
76
|
+
value.each { |v| delegated_attribute v, key }
|
77
|
+
else
|
78
|
+
delegated_attribute value, key
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def setup_friendly_model(_active_record_key)
|
86
|
+
friendly_model.instance_eval do
|
87
|
+
include Friendly::Document
|
88
|
+
|
89
|
+
attribute _active_record_key, Integer
|
90
|
+
indexes _active_record_key
|
91
|
+
|
92
|
+
cattr_accessor :active_record_key
|
93
|
+
end
|
94
|
+
friendly_model.active_record_key = _active_record_key
|
95
|
+
end
|
96
|
+
|
97
|
+
def setup_active_record_model
|
98
|
+
friendly_model = self.friendly_model
|
99
|
+
|
100
|
+
active_record_model.class_eval do
|
101
|
+
# Stores the FriendlyAttributes configuration for the ActiveRecord model.
|
102
|
+
cattr_accessor :friendly_attributes_configuration
|
103
|
+
|
104
|
+
define_method(FriendlyAttributes::DetailsDelegator.friendly_model_reader(friendly_model)) do
|
105
|
+
find_or_build_and_memoize_details(friendly_model)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
unless active_record_model.friendly_attributes_configuration
|
110
|
+
active_record_model.friendly_attributes_configuration = Configuration.new(active_record_model)
|
111
|
+
|
112
|
+
active_record_model.class_eval do
|
113
|
+
after_save :update_friendly_models
|
114
|
+
after_destroy :destroy_friendly_models
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
active_record_model.friendly_attributes_configuration.add(self)
|
119
|
+
end
|
50
120
|
end
|
51
121
|
end
|
@@ -1,33 +1,135 @@
|
|
1
1
|
module FriendlyAttributes
|
2
2
|
module InstanceMethods
|
3
|
-
|
4
|
-
|
3
|
+
# Read the value of a Friendly attribute
|
4
|
+
#
|
5
|
+
# @param [Symbol, String] attr name of the attribute to read
|
6
|
+
# @return [Object] value of the read attribute
|
7
|
+
def read_friendly_attribute(attr)
|
8
|
+
friendly_instance_for_attribute(attr).send(attr)
|
5
9
|
end
|
6
|
-
|
7
|
-
|
8
|
-
|
10
|
+
|
11
|
+
# Write the value of a Friendly attribute
|
12
|
+
#
|
13
|
+
# @param [Symbol, String] attr name of the attribute to set
|
14
|
+
# @param [Object] value value to set the attribute to
|
15
|
+
def write_friendly_attribute(attr, value)
|
16
|
+
friendly_instance_for_attribute(attr).send(:"#{attr}=", value)
|
9
17
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
18
|
+
|
19
|
+
# Returns the Friendly instance corresponding to the specified attribute
|
20
|
+
#
|
21
|
+
# @param [Symbol, String] attr name of the attribute
|
22
|
+
# @return [Class] FriendyAttributes::Base instance
|
23
|
+
def friendly_instance_for_attribute(attr)
|
24
|
+
klass = friendly_attributes_configuration.model_for_attribute(attr)
|
25
|
+
send DetailsDelegator.friendly_model_reader(klass)
|
13
26
|
end
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
27
|
+
|
28
|
+
# Update all associated Friendly instances, if they have been changed.
|
29
|
+
# If assigning attributes resulted in new instances being built, they will be created.
|
30
|
+
def update_friendly_models
|
31
|
+
present_friendly_instances.each do |details|
|
32
|
+
details.update_if_changed_with_model(id)
|
33
|
+
end
|
19
34
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
35
|
+
|
36
|
+
# Destroys all FriendlyAttributes associated with the model. Forces loading and sends :destroy to all associated Friendly models.
|
37
|
+
#
|
38
|
+
# @return [true, false] result of attempting to destroy the associated FriendlyAttributes
|
39
|
+
def destroy_friendly_models
|
40
|
+
all_friendly_instances.map(&:destroy).all?
|
23
41
|
end
|
24
42
|
|
25
|
-
|
43
|
+
# Hook provided in order to customize the defaults for building Friendly model instances associated with a certain model.
|
44
|
+
# Redefine the method on the FriendlyAttributes::Base subclass to customize.
|
45
|
+
#
|
46
|
+
# Defaults to an empty Hash.
|
47
|
+
#
|
48
|
+
# @example We want to specify build options for the UserDetails instances, but not for UserSecondDetails
|
49
|
+
# class User < ActiveRecord::Base
|
50
|
+
# include FriendlyAttributes
|
51
|
+
#
|
52
|
+
# friendly_details(UserDetails, Integer => :shoe_size)
|
53
|
+
# friendly_details(UserSecondDetails, Integer => :second_int)
|
54
|
+
#
|
55
|
+
# def friendly_details_build_options(friendly_model)
|
56
|
+
# if UserDetails == friendly_model
|
57
|
+
# { :shoe_size => 42 }
|
58
|
+
# else
|
59
|
+
# {}
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# @param [Class] friendly_model FriendlyAttributes::Base subclass for which the build options should be returned
|
65
|
+
# @return [Hash] default attributes to be used when building the associated friendly_model
|
66
|
+
def friendly_details_build_options(friendly_model = nil)
|
26
67
|
{}
|
27
68
|
end
|
28
69
|
|
70
|
+
# Finds or builds the Friendly instance associated through friendly_model. Result is memoized in an instance variable.
|
71
|
+
# @see FriendlyAttributes::Base.find_or_build_by_active_record_id
|
72
|
+
# @see FriendlyAttributes::DetailsDelegator.friendly_model_ivar
|
73
|
+
#
|
74
|
+
# @param [Class] friendly_model FriendlyAttributes::Base subclass
|
75
|
+
def find_or_build_and_memoize_details(friendly_model)
|
76
|
+
friendly_model_ivar = DetailsDelegator.friendly_model_ivar(friendly_model)
|
77
|
+
|
78
|
+
val = instance_variable_get(friendly_model_ivar)
|
79
|
+
return val if val.present?
|
80
|
+
|
81
|
+
instance_variable_set(friendly_model_ivar,
|
82
|
+
friendly_model.
|
83
|
+
find_or_build_by_active_record_id(id, friendly_details_build_options(friendly_model)))
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns true if the FriendlyAttributes specified instance is loaded.
|
87
|
+
#
|
88
|
+
# @param [Class, Symbol, String] friendly_model Class or name of the FriendlyAttributes model
|
89
|
+
# @return [true, false] is the FriendlyAttributes instance loaded
|
90
|
+
def friendly_instance_present?(friendly_model)
|
91
|
+
friendly_model_ivar = DetailsDelegator.friendly_model_ivar(friendly_model)
|
92
|
+
val = instance_variable_get(friendly_model_ivar)
|
93
|
+
val.present?
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns the associated FriendlyAttributes instance, if it has been loaded. If not loaded, returns nil.
|
97
|
+
#
|
98
|
+
# @param [Class, Symbol, String] friendly_model Class or name of the FriendlyAttributes model
|
99
|
+
# @return [FriendlyAttributes::Base, nil] instance of the FriendlyAttributes or nil
|
100
|
+
def friendly_instance_presence(friendly_model)
|
101
|
+
friendly_instance_present?(friendly_model) ?
|
102
|
+
send(DetailsDelegator.friendly_model_reader(friendly_model)) :
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
# List of all the FriendlyAttributes::Base instances associated with the model.
|
107
|
+
# Forces loading if the details have not been loaded yet.
|
108
|
+
#
|
109
|
+
# @return [Array<FriendlyAttributes::Base>] FriendlyAttributes instances
|
110
|
+
def all_friendly_instances
|
111
|
+
friendly_attributes_configuration.friendly_models.map do |friendly_model|
|
112
|
+
send(DetailsDelegator.friendly_model_reader(friendly_model))
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# List of FriendlyAttributes::Base instances that have been loaded.
|
117
|
+
# Does not force loading of details not loaded yet.
|
118
|
+
#
|
119
|
+
# @return [Array<FriendlyAttributes::Base>] FriendlyAttributes instances
|
120
|
+
def present_friendly_instances
|
121
|
+
friendly_attributes_configuration.friendly_models.map do |friendly_model|
|
122
|
+
friendly_instance_presence(friendly_model)
|
123
|
+
end.compact
|
124
|
+
end
|
125
|
+
|
126
|
+
# Returns if the record has been changed and should be saved, taking into account any FriendlyAttributes.
|
127
|
+
#
|
128
|
+
# Overloads ActiveRecord::Base#changed?
|
129
|
+
#
|
130
|
+
# @return [true, false]
|
29
131
|
def changed?
|
30
|
-
super || (
|
132
|
+
super || present_friendly_instances.any?(&:changed?)
|
31
133
|
end
|
32
134
|
end
|
33
135
|
end
|
@@ -5,6 +5,8 @@ module FriendlyAttributes
|
|
5
5
|
def initialize(example, type, *attributes)
|
6
6
|
@example = example
|
7
7
|
@type = type
|
8
|
+
@options = attributes.extract_options!
|
9
|
+
@through = @options[:through]
|
8
10
|
@attributes = attributes
|
9
11
|
end
|
10
12
|
|
@@ -12,7 +14,7 @@ module FriendlyAttributes
|
|
12
14
|
@actual = Class === actual ? actual : actual.class
|
13
15
|
|
14
16
|
result = @actual.ancestors.include?(FriendlyAttributes) && @attributes.all? { |attr|
|
15
|
-
@
|
17
|
+
@through.attributes.include?(attr) && @through.attributes[attr].type == @type
|
16
18
|
}
|
17
19
|
end
|
18
20
|
|
@@ -29,6 +31,14 @@ module FriendlyAttributes
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
34
|
+
# RSpec matcher for checking Friendly attributes.
|
35
|
+
# Passes if the model has the specified FriendlyAttributes associated with it.
|
36
|
+
#
|
37
|
+
# @example Using the matcher
|
38
|
+
# it { should have_friendly_attributes(String, :ssn, :work_email, :through => UserDetails) }
|
39
|
+
# it { should have_friendly_attributes(Friendly::Boolean, :is_active, :through => CompanyDetails) }
|
40
|
+
#
|
41
|
+
# @return [HaveFriendlyAttribute] matcher
|
32
42
|
def have_friendly_attributes(*args)
|
33
43
|
HaveFriendlyAttribute.new(self, *args)
|
34
44
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: friendly-attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 3
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 7
|
9
|
+
- 0
|
10
|
+
version: 0.7.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Istvan Hoka
|
@@ -15,12 +15,10 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-02-20 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
prerelease: false
|
23
|
-
type: :runtime
|
24
22
|
name: activerecord
|
25
23
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
24
|
none: false
|
@@ -33,26 +31,24 @@ dependencies:
|
|
33
31
|
- 3
|
34
32
|
- 5
|
35
33
|
version: 2.3.5
|
36
|
-
requirement: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
34
|
prerelease: false
|
39
35
|
type: :runtime
|
36
|
+
requirement: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
40
38
|
name: friendly
|
41
39
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
42
40
|
none: false
|
43
41
|
requirements:
|
44
|
-
- -
|
42
|
+
- - ">="
|
45
43
|
- !ruby/object:Gem::Version
|
46
|
-
hash:
|
44
|
+
hash: 3
|
47
45
|
segments:
|
48
46
|
- 0
|
49
|
-
|
50
|
-
- 0
|
51
|
-
version: 0.6.0
|
52
|
-
requirement: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
47
|
+
version: "0"
|
54
48
|
prerelease: false
|
55
49
|
type: :runtime
|
50
|
+
requirement: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
56
52
|
name: yajl-ruby
|
57
53
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
58
54
|
none: false
|
@@ -65,10 +61,10 @@ dependencies:
|
|
65
61
|
- 7
|
66
62
|
- 7
|
67
63
|
version: 0.7.7
|
68
|
-
requirement: *id003
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
64
|
prerelease: false
|
71
65
|
type: :runtime
|
66
|
+
requirement: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
72
68
|
name: memcached
|
73
69
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
74
70
|
none: false
|
@@ -81,12 +77,26 @@ dependencies:
|
|
81
77
|
- 20
|
82
78
|
- 1
|
83
79
|
version: 0.20.1
|
80
|
+
prerelease: false
|
81
|
+
type: :runtime
|
84
82
|
requirement: *id004
|
85
83
|
- !ruby/object:Gem::Dependency
|
84
|
+
name: ruby-debug
|
85
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
version: "0"
|
86
94
|
prerelease: false
|
87
|
-
type: :
|
95
|
+
type: :runtime
|
96
|
+
requirement: *id005
|
97
|
+
- !ruby/object:Gem::Dependency
|
88
98
|
name: mysql
|
89
|
-
version_requirements: &
|
99
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
90
100
|
none: false
|
91
101
|
requirements:
|
92
102
|
- - ~>
|
@@ -97,28 +107,28 @@ dependencies:
|
|
97
107
|
- 8
|
98
108
|
- 1
|
99
109
|
version: 2.8.1
|
100
|
-
requirement: *id005
|
101
|
-
- !ruby/object:Gem::Dependency
|
102
110
|
prerelease: false
|
103
111
|
type: :development
|
112
|
+
requirement: *id006
|
113
|
+
- !ruby/object:Gem::Dependency
|
104
114
|
name: rspec
|
105
|
-
version_requirements: &
|
115
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
106
116
|
none: false
|
107
117
|
requirements:
|
108
118
|
- - ~>
|
109
119
|
- !ruby/object:Gem::Version
|
110
|
-
hash:
|
120
|
+
hash: 27
|
111
121
|
segments:
|
112
122
|
- 2
|
113
|
-
-
|
123
|
+
- 5
|
114
124
|
- 0
|
115
|
-
version: 2.
|
116
|
-
requirement: *id006
|
117
|
-
- !ruby/object:Gem::Dependency
|
125
|
+
version: 2.5.0
|
118
126
|
prerelease: false
|
119
127
|
type: :development
|
128
|
+
requirement: *id007
|
129
|
+
- !ruby/object:Gem::Dependency
|
120
130
|
name: bundler
|
121
|
-
version_requirements: &
|
131
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
122
132
|
none: false
|
123
133
|
requirements:
|
124
134
|
- - ~>
|
@@ -129,12 +139,12 @@ dependencies:
|
|
129
139
|
- 0
|
130
140
|
- 0
|
131
141
|
version: 1.0.0
|
132
|
-
requirement: *id007
|
133
|
-
- !ruby/object:Gem::Dependency
|
134
142
|
prerelease: false
|
135
143
|
type: :development
|
144
|
+
requirement: *id008
|
145
|
+
- !ruby/object:Gem::Dependency
|
136
146
|
name: jeweler
|
137
|
-
version_requirements: &
|
147
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
138
148
|
none: false
|
139
149
|
requirements:
|
140
150
|
- - ~>
|
@@ -145,12 +155,12 @@ dependencies:
|
|
145
155
|
- 5
|
146
156
|
- 1
|
147
157
|
version: 1.5.1
|
148
|
-
requirement: *id008
|
149
|
-
- !ruby/object:Gem::Dependency
|
150
158
|
prerelease: false
|
151
159
|
type: :development
|
160
|
+
requirement: *id009
|
161
|
+
- !ruby/object:Gem::Dependency
|
152
162
|
name: rcov
|
153
|
-
version_requirements: &
|
163
|
+
version_requirements: &id010 !ruby/object:Gem::Requirement
|
154
164
|
none: false
|
155
165
|
requirements:
|
156
166
|
- - ">="
|
@@ -159,12 +169,12 @@ dependencies:
|
|
159
169
|
segments:
|
160
170
|
- 0
|
161
171
|
version: "0"
|
162
|
-
requirement: *id009
|
163
|
-
- !ruby/object:Gem::Dependency
|
164
172
|
prerelease: false
|
165
173
|
type: :development
|
174
|
+
requirement: *id010
|
175
|
+
- !ruby/object:Gem::Dependency
|
166
176
|
name: database_cleaner
|
167
|
-
version_requirements: &
|
177
|
+
version_requirements: &id011 !ruby/object:Gem::Requirement
|
168
178
|
none: false
|
169
179
|
requirements:
|
170
180
|
- - ~>
|
@@ -175,12 +185,68 @@ dependencies:
|
|
175
185
|
- 5
|
176
186
|
- 0
|
177
187
|
version: 0.5.0
|
178
|
-
|
188
|
+
prerelease: false
|
189
|
+
type: :development
|
190
|
+
requirement: *id011
|
179
191
|
- !ruby/object:Gem::Dependency
|
192
|
+
name: autotest
|
193
|
+
version_requirements: &id012 !ruby/object:Gem::Requirement
|
194
|
+
none: false
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
hash: 3
|
199
|
+
segments:
|
200
|
+
- 0
|
201
|
+
version: "0"
|
180
202
|
prerelease: false
|
181
|
-
type: :
|
203
|
+
type: :development
|
204
|
+
requirement: *id012
|
205
|
+
- !ruby/object:Gem::Dependency
|
206
|
+
name: autotest-fsevent
|
207
|
+
version_requirements: &id013 !ruby/object:Gem::Requirement
|
208
|
+
none: false
|
209
|
+
requirements:
|
210
|
+
- - ">="
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
hash: 3
|
213
|
+
segments:
|
214
|
+
- 0
|
215
|
+
version: "0"
|
216
|
+
prerelease: false
|
217
|
+
type: :development
|
218
|
+
requirement: *id013
|
219
|
+
- !ruby/object:Gem::Dependency
|
220
|
+
name: autotest-growl
|
221
|
+
version_requirements: &id014 !ruby/object:Gem::Requirement
|
222
|
+
none: false
|
223
|
+
requirements:
|
224
|
+
- - ">="
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
hash: 3
|
227
|
+
segments:
|
228
|
+
- 0
|
229
|
+
version: "0"
|
230
|
+
prerelease: false
|
231
|
+
type: :development
|
232
|
+
requirement: *id014
|
233
|
+
- !ruby/object:Gem::Dependency
|
234
|
+
name: syntax
|
235
|
+
version_requirements: &id015 !ruby/object:Gem::Requirement
|
236
|
+
none: false
|
237
|
+
requirements:
|
238
|
+
- - ">="
|
239
|
+
- !ruby/object:Gem::Version
|
240
|
+
hash: 3
|
241
|
+
segments:
|
242
|
+
- 0
|
243
|
+
version: "0"
|
244
|
+
prerelease: false
|
245
|
+
type: :development
|
246
|
+
requirement: *id015
|
247
|
+
- !ruby/object:Gem::Dependency
|
182
248
|
name: activerecord
|
183
|
-
version_requirements: &
|
249
|
+
version_requirements: &id016 !ruby/object:Gem::Requirement
|
184
250
|
none: false
|
185
251
|
requirements:
|
186
252
|
- - ~>
|
@@ -191,12 +257,12 @@ dependencies:
|
|
191
257
|
- 3
|
192
258
|
- 5
|
193
259
|
version: 2.3.5
|
194
|
-
requirement: *id011
|
195
|
-
- !ruby/object:Gem::Dependency
|
196
260
|
prerelease: false
|
197
261
|
type: :runtime
|
262
|
+
requirement: *id016
|
263
|
+
- !ruby/object:Gem::Dependency
|
198
264
|
name: friendly
|
199
|
-
version_requirements: &
|
265
|
+
version_requirements: &id017 !ruby/object:Gem::Requirement
|
200
266
|
none: false
|
201
267
|
requirements:
|
202
268
|
- - ~>
|
@@ -207,12 +273,12 @@ dependencies:
|
|
207
273
|
- 6
|
208
274
|
- 0
|
209
275
|
version: 0.6.0
|
210
|
-
requirement: *id012
|
211
|
-
- !ruby/object:Gem::Dependency
|
212
276
|
prerelease: false
|
213
277
|
type: :runtime
|
278
|
+
requirement: *id017
|
279
|
+
- !ruby/object:Gem::Dependency
|
214
280
|
name: yajl-ruby
|
215
|
-
version_requirements: &
|
281
|
+
version_requirements: &id018 !ruby/object:Gem::Requirement
|
216
282
|
none: false
|
217
283
|
requirements:
|
218
284
|
- - ~>
|
@@ -223,12 +289,12 @@ dependencies:
|
|
223
289
|
- 7
|
224
290
|
- 7
|
225
291
|
version: 0.7.7
|
226
|
-
requirement: *id013
|
227
|
-
- !ruby/object:Gem::Dependency
|
228
292
|
prerelease: false
|
229
293
|
type: :runtime
|
294
|
+
requirement: *id018
|
295
|
+
- !ruby/object:Gem::Dependency
|
230
296
|
name: memcached
|
231
|
-
version_requirements: &
|
297
|
+
version_requirements: &id019 !ruby/object:Gem::Requirement
|
232
298
|
none: false
|
233
299
|
requirements:
|
234
300
|
- - ~>
|
@@ -239,12 +305,12 @@ dependencies:
|
|
239
305
|
- 20
|
240
306
|
- 1
|
241
307
|
version: 0.20.1
|
242
|
-
requirement: *id014
|
243
|
-
- !ruby/object:Gem::Dependency
|
244
308
|
prerelease: false
|
245
|
-
type: :
|
309
|
+
type: :runtime
|
310
|
+
requirement: *id019
|
311
|
+
- !ruby/object:Gem::Dependency
|
246
312
|
name: mysql
|
247
|
-
version_requirements: &
|
313
|
+
version_requirements: &id020 !ruby/object:Gem::Requirement
|
248
314
|
none: false
|
249
315
|
requirements:
|
250
316
|
- - ~>
|
@@ -255,12 +321,12 @@ dependencies:
|
|
255
321
|
- 8
|
256
322
|
- 1
|
257
323
|
version: 2.8.1
|
258
|
-
requirement: *id015
|
259
|
-
- !ruby/object:Gem::Dependency
|
260
324
|
prerelease: false
|
261
325
|
type: :development
|
326
|
+
requirement: *id020
|
327
|
+
- !ruby/object:Gem::Dependency
|
262
328
|
name: rspec
|
263
|
-
version_requirements: &
|
329
|
+
version_requirements: &id021 !ruby/object:Gem::Requirement
|
264
330
|
none: false
|
265
331
|
requirements:
|
266
332
|
- - ~>
|
@@ -271,12 +337,12 @@ dependencies:
|
|
271
337
|
- 1
|
272
338
|
- 0
|
273
339
|
version: 2.1.0
|
274
|
-
requirement: *id016
|
275
|
-
- !ruby/object:Gem::Dependency
|
276
340
|
prerelease: false
|
277
341
|
type: :development
|
342
|
+
requirement: *id021
|
343
|
+
- !ruby/object:Gem::Dependency
|
278
344
|
name: bundler
|
279
|
-
version_requirements: &
|
345
|
+
version_requirements: &id022 !ruby/object:Gem::Requirement
|
280
346
|
none: false
|
281
347
|
requirements:
|
282
348
|
- - ~>
|
@@ -287,12 +353,12 @@ dependencies:
|
|
287
353
|
- 0
|
288
354
|
- 0
|
289
355
|
version: 1.0.0
|
290
|
-
requirement: *id017
|
291
|
-
- !ruby/object:Gem::Dependency
|
292
356
|
prerelease: false
|
293
357
|
type: :development
|
358
|
+
requirement: *id022
|
359
|
+
- !ruby/object:Gem::Dependency
|
294
360
|
name: jeweler
|
295
|
-
version_requirements: &
|
361
|
+
version_requirements: &id023 !ruby/object:Gem::Requirement
|
296
362
|
none: false
|
297
363
|
requirements:
|
298
364
|
- - ~>
|
@@ -303,12 +369,12 @@ dependencies:
|
|
303
369
|
- 5
|
304
370
|
- 1
|
305
371
|
version: 1.5.1
|
306
|
-
requirement: *id018
|
307
|
-
- !ruby/object:Gem::Dependency
|
308
372
|
prerelease: false
|
309
373
|
type: :development
|
374
|
+
requirement: *id023
|
375
|
+
- !ruby/object:Gem::Dependency
|
310
376
|
name: rcov
|
311
|
-
version_requirements: &
|
377
|
+
version_requirements: &id024 !ruby/object:Gem::Requirement
|
312
378
|
none: false
|
313
379
|
requirements:
|
314
380
|
- - ">="
|
@@ -317,12 +383,12 @@ dependencies:
|
|
317
383
|
segments:
|
318
384
|
- 0
|
319
385
|
version: "0"
|
320
|
-
requirement: *id019
|
321
|
-
- !ruby/object:Gem::Dependency
|
322
386
|
prerelease: false
|
323
387
|
type: :development
|
388
|
+
requirement: *id024
|
389
|
+
- !ruby/object:Gem::Dependency
|
324
390
|
name: database_cleaner
|
325
|
-
version_requirements: &
|
391
|
+
version_requirements: &id025 !ruby/object:Gem::Requirement
|
326
392
|
none: false
|
327
393
|
requirements:
|
328
394
|
- - ~>
|
@@ -333,7 +399,9 @@ dependencies:
|
|
333
399
|
- 5
|
334
400
|
- 0
|
335
401
|
version: 0.5.0
|
336
|
-
|
402
|
+
prerelease: false
|
403
|
+
type: :development
|
404
|
+
requirement: *id025
|
337
405
|
description: Pattern to add fields to ActiveRecord models, using an associated document, without needing schema migrations.
|
338
406
|
email: istvan.hoka@gmail.com
|
339
407
|
executables: []
|
@@ -342,18 +410,19 @@ extensions: []
|
|
342
410
|
|
343
411
|
extra_rdoc_files:
|
344
412
|
- LICENSE.txt
|
345
|
-
- README.
|
413
|
+
- README.md
|
346
414
|
files:
|
347
415
|
- CHANGELOG.md
|
348
416
|
- LICENSE.txt
|
349
|
-
- README.rdoc
|
350
417
|
- lib/friendly-attributes.rb
|
351
418
|
- lib/friendly_attributes.rb
|
419
|
+
- lib/friendly_attributes/base.rb
|
352
420
|
- lib/friendly_attributes/class_methods.rb
|
353
|
-
- lib/friendly_attributes/
|
421
|
+
- lib/friendly_attributes/configuration.rb
|
354
422
|
- lib/friendly_attributes/details_delegator.rb
|
355
423
|
- lib/friendly_attributes/instance_methods.rb
|
356
424
|
- lib/friendly_attributes/test/matchers.rb
|
425
|
+
- README.md
|
357
426
|
has_rdoc: true
|
358
427
|
homepage: http://github.com/ihoka/friendly-attributes
|
359
428
|
licenses:
|
@@ -384,7 +453,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
384
453
|
requirements: []
|
385
454
|
|
386
455
|
rubyforge_project:
|
387
|
-
rubygems_version: 1.
|
456
|
+
rubygems_version: 1.5.0
|
388
457
|
signing_key:
|
389
458
|
specification_version: 3
|
390
459
|
summary: Extend ActiveRecord models using Friendly ORM delegate models
|
data/README.rdoc
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
= friendly-attributes
|
2
|
-
|
3
|
-
Pattern to add fields to ActiveRecord models, using an associated document, without needing schema migrations.
|
4
|
-
|
5
|
-
Uses http://friendlyorm.com/
|
6
|
-
|
7
|
-
== Contributing to friendly-attributes
|
8
|
-
|
9
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
10
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
11
|
-
* Fork the project
|
12
|
-
* Start a feature/bugfix branch
|
13
|
-
* Commit and push until you are happy with your contribution
|
14
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
15
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
16
|
-
|
17
|
-
== Copyright
|
18
|
-
|
19
|
-
Copyright (c) 2010 Istvan Hoka. See LICENSE.txt for
|
20
|
-
further details.
|
21
|
-
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module FriendlyAttributes
|
2
|
-
class Details
|
3
|
-
class << self
|
4
|
-
def find_or_build_by_active_record_id(active_record_id, options={})
|
5
|
-
active_record_id && first(active_record_key => active_record_id) || new(options.merge(active_record_key => active_record_id))
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
def attributes
|
10
|
-
{}.tap do |attributes|
|
11
|
-
self.class.attributes.keys.each do |attr|
|
12
|
-
attributes[attr] = self.send(attr)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|