friendly-attributes 0.7.1.1 → 0.7.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.
@@ -0,0 +1,45 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
18
+ #
19
+ # * Create a file at ~/.gitignore
20
+ # * Include files you want ignored
21
+ # * Run: git config --global core.excludesfile ~/.gitignore
22
+ #
23
+ # After doing this, these files will be ignored in all your git projects,
24
+ # saving you from having to 'pollute' every project you touch with them
25
+ #
26
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
27
+ #
28
+ # For MacOS:
29
+ #
30
+ #.DS_Store
31
+ #
32
+ # For TextMate
33
+ #*.tmproj
34
+ #tmtags
35
+ #
36
+ # For emacs:
37
+ #*~
38
+ #\#*
39
+ #.\#*
40
+ #
41
+ # For vim:
42
+ #*.swp
43
+ spec/config.yml
44
+ log
45
+ friendly-attributes.tmproj
@@ -0,0 +1 @@
1
+ ruby-1.9.3
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ before_script:
5
+ - mysql -e 'create database friendly_attributes_test;'
6
+ - cp spec/config.sample.yml spec/config.yml
@@ -0,0 +1 @@
1
+ --no-private lib/**/*.rb - CHANGELOG.md LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ friendly-attributes (0.7.2)
5
+ activerecord (~> 2.3.18)
6
+ ihoka-friendly (~> 0.7.0)
7
+ memcached (~> 0.20.1)
8
+ yajl-ruby (~> 0.7.7)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ activerecord (2.3.18)
14
+ activesupport (= 2.3.18)
15
+ activesupport (2.3.18)
16
+ database_cleaner (0.5.2)
17
+ diff-lcs (1.1.3)
18
+ ihoka-friendly (0.7.0)
19
+ activesupport (~> 2.3.18)
20
+ rufus-json (~> 0.2.3)
21
+ sequel (~> 3.16.0)
22
+ will_paginate (~> 2.3.15)
23
+ memcached (0.20.1)
24
+ mysql (2.8.1)
25
+ rspec (2.5.0)
26
+ rspec-core (~> 2.5.0)
27
+ rspec-expectations (~> 2.5.0)
28
+ rspec-mocks (~> 2.5.0)
29
+ rspec-core (2.5.2)
30
+ rspec-expectations (2.5.0)
31
+ diff-lcs (~> 1.1.2)
32
+ rspec-mocks (2.5.0)
33
+ rufus-json (0.2.7)
34
+ sequel (3.16.0)
35
+ will_paginate (2.3.16)
36
+ yajl-ruby (0.7.9)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ database_cleaner (~> 0.5.0)
43
+ friendly-attributes!
44
+ mysql (~> 2.8.1)
45
+ rspec (~> 2.5.0)
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Friendly Attributes
2
2
 
3
+ [![Build Status](https://travis-ci.org/ihoka/friendly-attributes.png)](https://travis-ci.org/ihoka/friendly-attributes)
4
+
5
+
3
6
  Extend your ActiveRecord models with attributes dynamically, without any schema migrations.
4
7
 
5
8
  ## Description
@@ -0,0 +1,25 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec) do |spec|
6
+ spec.pattern = FileList['spec/**/*_spec.rb']
7
+ end
8
+
9
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
10
+ spec.pattern = FileList['spec/**/*_spec.rb']
11
+ spec.rcov = true
12
+ spec.rcov_opts = %w{-I spec:lib --exclude gems\/,spec\/}
13
+ end
14
+
15
+ task :default => :spec
16
+
17
+ require 'rdoc/task'
18
+ Rake::RDocTask.new do |rdoc|
19
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
20
+
21
+ rdoc.rdoc_dir = 'rdoc'
22
+ rdoc.title = "friendly-attributes #{version}"
23
+ rdoc.rdoc_files.include('README*')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.7.2
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{friendly-attributes}
7
+ s.version = "0.7.1.1"
8
+
9
+ s.authors = ["Istvan Hoka"]
10
+ s.date = %q{2011-04-10}
11
+ s.description = %q{Pattern to add fields to ActiveRecord models, using an associated document, without needing schema migrations.}
12
+ s.email = %q{istvan.hoka@gmail.com}
13
+ s.homepage = %q{http://github.com/ihoka/friendly-attributes}
14
+ s.licenses = ["MIT"]
15
+ s.summary = %q{Extend ActiveRecord models using Friendly ORM delegate models}
16
+ s.version = File.read(File.dirname(__FILE__) + '/VERSION')
17
+
18
+ s.add_development_dependency 'mysql', '~> 2.8.1'
19
+ s.add_development_dependency 'rspec', '~> 2.5.0'
20
+ s.add_development_dependency 'database_cleaner', '~> 0.5.0'
21
+ s.add_dependency 'ihoka-friendly', '~> 0.7.0'
22
+ s.add_dependency 'activerecord', '~> 2.3.18'
23
+ s.add_dependency 'yajl-ruby', '~> 0.7.7'
24
+ s.add_dependency 'memcached', '~> 0.20.1'
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- spec/*`.split("\n")
28
+ s.require_paths = ["lib"]
29
+ end
30
+
@@ -0,0 +1,6 @@
1
+ test:
2
+ :adapter: "mysql"
3
+ :host: "localhost"
4
+ :user: "root"
5
+ :password:
6
+ :database: "friendly_attributes_test"
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+
3
+ describe FriendlyAttributes::Base do
4
+ use_database_cleanup
5
+
6
+ let(:friendly_model) {
7
+ Class.new(FriendlyAttributes::Base) do
8
+ cattr_accessor :active_record_key
9
+ end.tap { |c| c.active_record_key = active_record_key }
10
+ }
11
+ let(:active_record_key) { :ar_id }
12
+ let(:details) { mock(FriendlyAttributes::Base) }
13
+
14
+ describe ".find_or_build_by_active_record_id" do
15
+
16
+ context "when the record does not exist" do
17
+ before(:each) do
18
+ friendly_model.should_receive(:first).with(:ar_id => 42).and_return(nil)
19
+ end
20
+
21
+ it "builds a new record with the active_record_id" do
22
+ friendly_model.should_receive(:new).with(:ar_id => 42).and_return(details)
23
+ friendly_model.find_or_build_by_active_record_id(42).should == details
24
+ end
25
+
26
+ it "with options present, it builds a new record with the options and active_record_id" do
27
+ friendly_model.should_receive(:new).with(:ar_id => 42, :foo => "foo").and_return(details)
28
+ friendly_model.find_or_build_by_active_record_id(42, :foo => "foo").should == details
29
+ end
30
+ end
31
+
32
+ context "when the record exists" do
33
+ it "finds the record" do
34
+ friendly_model.should_receive(:first).with(:ar_id => 42).and_return(details)
35
+ friendly_model.find_or_build_by_active_record_id(42).should == details
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "#write_active_record_id" do
41
+ let(:friendly_instance) { friendly_model.new }
42
+
43
+ it "sets the active_record_id using the configured attribute writer" do
44
+ friendly_instance.should_receive(:"#{active_record_key}=").with(42).and_return(42)
45
+ friendly_instance.write_active_record_id(42).should == 42
46
+ end
47
+ end
48
+
49
+ describe "#read_active_record_id" do
50
+ let(:friendly_instance) { friendly_model.new }
51
+
52
+ it "sets the active_record_id using the configured attribute writer" do
53
+ friendly_instance.should_receive(active_record_key).and_return(42)
54
+ friendly_instance.read_active_record_id.should == 42
55
+ end
56
+ end
57
+
58
+ describe "#update_if_changed_with_model" do
59
+ let(:friendly_instance) { friendly_model.new }
60
+
61
+ before(:each) do
62
+ friendly_instance.stub(:save => false, :changed? => false, :read_active_record_id => 42)
63
+ end
64
+
65
+ context "when the active_record_id is not set" do
66
+ before(:each) do
67
+ friendly_instance.should_receive(:read_active_record_id).and_return(nil)
68
+ end
69
+
70
+ it "sets the active_record_id" do
71
+ friendly_instance.should_receive(:write_active_record_id).with(42)
72
+ friendly_instance.update_if_changed_with_model(42)
73
+ end
74
+ end
75
+
76
+ context "when the active_record_id is set" do
77
+ before(:each) do
78
+ friendly_instance.should_receive(:read_active_record_id).and_return(42)
79
+ end
80
+
81
+ it "does not reset the active_record_id" do
82
+ friendly_instance.should_not_receive(:write_active_record_id)
83
+ friendly_instance.update_if_changed_with_model(42)
84
+ end
85
+ end
86
+
87
+ context "when changed" do
88
+ before(:each) do
89
+ friendly_instance.should_receive(:changed?).and_return(true)
90
+ end
91
+
92
+ it "saves the record" do
93
+ friendly_instance.should_receive(:save).and_return(true)
94
+ friendly_instance.update_if_changed_with_model(42).should be_true
95
+ end
96
+ end
97
+
98
+ context "when not changed" do
99
+ before(:each) do
100
+ friendly_instance.should_receive(:changed?).and_return(false)
101
+ end
102
+
103
+ it "saves the record" do
104
+ friendly_instance.should_not_receive(:save)
105
+ friendly_instance.update_if_changed_with_model(42).should be_false
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "#attributes" do
111
+ let(:details) { UserDetails.create(attributes) }
112
+ let(:attributes) { { :name => "Foo", :birth_year => 1970, :shoe_size => 42, :subscribed => true, UserDetails.active_record_key => 55 } }
113
+
114
+ it "returns a hash of all the model's attributes" do
115
+ actual = details.attributes
116
+ actual.should include(attributes)
117
+ actual[:created_at].should be_an_instance_of(Time)
118
+ actual[:updated_at].should be_an_instance_of(Time)
119
+ actual[:id].should be_an_instance_of(Friendly::UUID)
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe FriendlyAttributes::ClassMethods do
4
+ let(:friendly_model) { mock_friendly_model }
5
+ let(:ar_model) {
6
+ Class.new {
7
+ include ActiveRecordFake
8
+ extend FriendlyAttributes::ClassMethods
9
+ }
10
+ }
11
+
12
+ let(:details_delegator) { mock(FriendlyAttributes::DetailsDelegator) }
13
+
14
+ class FakeUploader; end
15
+
16
+ describe ".friendly_details" do
17
+ let(:attributes) do
18
+ {
19
+ String => :foo,
20
+ Integer => [:bar, :baz]
21
+ }
22
+ end
23
+
24
+ before(:each) do
25
+ details_delegator.stub(:setup_delegated_attributes)
26
+ end
27
+
28
+ context "with an initializer block" do
29
+ def yielded_inside(instance)
30
+ @yielded_instance = instance
31
+ end
32
+
33
+ let(:initializer) do
34
+ example = self
35
+
36
+ proc {
37
+ example.yielded_inside(self)
38
+ }
39
+ end
40
+
41
+ it "instance_evals the initializer block on the DetailsDelegator instance" do
42
+ FriendlyAttributes::DetailsDelegator.
43
+ should_receive(:new).
44
+ with(friendly_model, ar_model, attributes, {}).
45
+ and_return(details_delegator)
46
+
47
+ ar_model.friendly_details(friendly_model, attributes, &initializer).should == details_delegator
48
+ @yielded_instance.should == details_delegator
49
+ end
50
+ end
51
+
52
+ context "with attributes and options" do
53
+ let(:options) { { :active_record_key => :user_id } }
54
+
55
+ before(:each) do
56
+ FriendlyAttributes::DetailsDelegator.stub(:new => details_delegator)
57
+ end
58
+
59
+ def do_details
60
+ ar_model.friendly_details(friendly_model, attributes, options).should == details_delegator
61
+ end
62
+
63
+ it "instantiates a new DetailsDelegator" do
64
+ FriendlyAttributes::DetailsDelegator.should_receive(:new).with(friendly_model, ar_model, attributes, options).and_return(details_delegator)
65
+ do_details
66
+ end
67
+
68
+ it "sets up the delegated attributes" do
69
+ details_delegator.should_receive(:setup_delegated_attributes)
70
+ do_details
71
+ end
72
+ end
73
+
74
+ context "without a block" do
75
+ it "instantiates a new DetailsDelegator" do
76
+ FriendlyAttributes::DetailsDelegator.should_receive(:new).with(friendly_model, ar_model, attributes, {}).and_return(details_delegator)
77
+ ar_model.friendly_details(friendly_model, attributes).should == details_delegator
78
+ end
79
+ end
80
+ end
81
+
82
+ describe ".friendly_mount_uploader" do
83
+ let(:foo_value) { mock("Friendly attribute value") }
84
+
85
+ before(:each) do
86
+ ar_model.stub(:mount_uploader => nil)
87
+
88
+ foo = foo_value
89
+
90
+ ar_model.class_eval do
91
+ define_method(:read_friendly_attribute) do |attribute|
92
+ attribute.should == :foo
93
+ foo
94
+ end
95
+
96
+ define_method(:write_friendly_attribute) do |attribute, value|
97
+ value.tap do
98
+ attribute.should == :foo
99
+ value.should == foo
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ it "mounts the uploader" do
106
+ ar_model.should_receive(:mount_uploader).with(:foo, FakeUploader)
107
+ ar_model.friendly_mount_uploader :foo, FakeUploader
108
+ end
109
+
110
+ it "aliases #read_friendly_attribute to #read_uploader" do
111
+ ar_model.friendly_mount_uploader :foo, FakeUploader
112
+ ar_object = ar_model.new
113
+
114
+ ar_object.read_uploader(:foo).should == foo_value
115
+ end
116
+
117
+ it "aliases #read_friendly_attribute to #read_uploader" do
118
+ ar_model.friendly_mount_uploader :foo, FakeUploader
119
+ ar_object = ar_model.new
120
+
121
+ ar_object.write_uploader(:foo, foo_value).should == foo_value
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe FriendlyAttributes::Configuration do
4
+ subject { configuration }
5
+
6
+ let(:configuration) { FriendlyAttributes::Configuration.new(active_record_model) }
7
+ let(:active_record_model) { User }
8
+
9
+ describe "#initialize" do
10
+ its(:model) { should == active_record_model }
11
+ its(:details_delegators) { should == [] }
12
+ its(:attributes) { should == {} }
13
+ end
14
+
15
+ describe "#add" do
16
+ let(:delegator) { mock(FriendlyAttributes::DetailsDelegator, :delegated_attributes => delegated_attributes, :friendly_model => UserDetails) }
17
+ let(:delegated_attributes) { { :foo => Integer, :bar => String } }
18
+
19
+ it "adds a delegator to the details_delegators collection" do
20
+ configuration.add(delegator)
21
+ configuration.details_delegators.should == [delegator]
22
+ end
23
+ end
24
+
25
+ describe "#add_attribute" do
26
+ it "adds the attribute to the attributes collection" do
27
+ configuration.add_attribute(:foo, UserDetails)
28
+ configuration.attributes.should == { :foo => UserDetails }
29
+ end
30
+ end
31
+
32
+ describe "Configuration with delegators added" do
33
+ let(:friendly_models) { [UserDetails, UserSecondDetails] }
34
+ let(:delegated_attributes) {
35
+ {
36
+ UserDetails => { :foo => Integer, :bar => String },
37
+ UserSecondDetails => { :baz => Date }
38
+ }
39
+ }
40
+ let(:details_delegators) {
41
+ friendly_models.map do |fm|
42
+ mock(FriendlyAttributes::DetailsDelegator,
43
+ :friendly_model => fm,
44
+ :delegated_attributes => delegated_attributes[fm])
45
+ end
46
+ }
47
+
48
+ before(:each) do
49
+ details_delegators.each do |delegator|
50
+ configuration.add(delegator)
51
+ end
52
+ end
53
+
54
+ describe "#model_for_attribute" do
55
+ it "returns the FriendlyAttributes model associated with the attribute" do
56
+ configuration.add_attribute(:foo, UserDetails)
57
+ configuration.model_for_attribute(:foo).should == UserDetails
58
+ end
59
+ end
60
+
61
+ describe "#friendly_models" do
62
+ its(:friendly_models) { should == friendly_models }
63
+ end
64
+
65
+ describe "#map_models" do
66
+ let(:map_model_map) {
67
+ {}.tap do |h|
68
+ friendly_models.each_with_index do |m, i|
69
+ h[m] = i
70
+ end
71
+ end
72
+ }
73
+
74
+ it "maps over the friendly models" do
75
+ configuration.map_models do |model|
76
+ map_model_map[model]
77
+ end.sort.should == map_model_map.values.sort
78
+ end
79
+ end
80
+
81
+ describe "#each_model" do
82
+ let(:each_model_map) {
83
+ {}.tap do |h|
84
+ friendly_models.each_with_index do |m, i|
85
+ h[m] = i
86
+ end
87
+ end
88
+ }
89
+
90
+ it "iterates over the friendly models" do
91
+ result = []
92
+ configuration.each_model do |model|
93
+ result << each_model_map[model]
94
+ end
95
+ result.sort.should == each_model_map.values.sort
96
+ end
97
+ end
98
+ end
99
+ end