attribute_choices 1.0.1 → 1.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.
@@ -0,0 +1,3 @@
1
+ test/*.log
2
+ rdoc
3
+ *.gem
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - rbx
5
+ - rbx-2.0
6
+ - ree
7
+ - jruby
8
+ - ruby-head
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ attribute_choices (1.0.2)
5
+ activerecord
6
+ activesupport
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ activemodel (3.1.0)
12
+ activesupport (= 3.1.0)
13
+ bcrypt-ruby (~> 3.0.0)
14
+ builder (~> 3.0.0)
15
+ i18n (~> 0.6)
16
+ activerecord (3.1.0)
17
+ activemodel (= 3.1.0)
18
+ activesupport (= 3.1.0)
19
+ arel (~> 2.2.1)
20
+ tzinfo (~> 0.3.29)
21
+ activesupport (3.1.0)
22
+ multi_json (~> 1.0)
23
+ arel (2.2.1)
24
+ bcrypt-ruby (3.0.1)
25
+ builder (3.0.0)
26
+ i18n (0.6.0)
27
+ multi_json (1.0.3)
28
+ rake (0.9.2)
29
+ sqlite3 (1.3.4)
30
+ tzinfo (0.3.29)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ attribute_choices!
37
+ rake
38
+ sqlite3
data/README.md CHANGED
@@ -1,62 +1,101 @@
1
- # AttributeChoices
1
+ ## AttributeChoices
2
2
 
3
- AttributeChoices is a plugin that simplifies the common pattern of mapping a set of discreet values for an ActiveRecord model attribute, to a set of display values for human consumption.
3
+ [![Build Status](https://secure.travis-ci.org/christos/attribute_choices.png)](http://travis-ci.org/christos/attribute_choices)
4
4
 
5
- # Installation
5
+ Extends ActiveRecord attributes with a `:choices` pseudo-type that provides convenient methods for mapping each choice to its human readable form.
6
6
 
7
- ## Rails 3
7
+ ## Examples
8
+
9
+ By defining the available choices for the `gender` attribute in your `User` model,
10
+
11
+ class User < ActiveRecord::Base
12
+ attribute_choices :gender, [ ['m', "Male"], ['f', 'Female'] ],
13
+ :validate => true
14
+ end
15
+
16
+ ...for any given `User` instance,
17
+
18
+ @john = User.new(:gender => 'm')
19
+ @john.gender
20
+ => 'm'
21
+
22
+ ...you can access the human readable attribute value like this:
23
+
24
+ @john.gender_display
25
+ => 'Male'
26
+
27
+ If you need to provide the available choices in a `select` tag, you can simply use `User#gender_choices`,
28
+
29
+ <%= select("user", "gender", User.gender_choices) %>
30
+
31
+ ...which would give you the following HTML snippet
32
+
33
+ <select name="user[gender]">
34
+ <option value="m">Male</option>
35
+ <option value="f">Femail</option>
36
+ </select>
37
+
38
+ Validation is also taken care of, if you specify `:validate => true` in the options
39
+
40
+ @john.gender = 'x'
41
+ @john.valid?
42
+ => false
43
+
44
+ And if you work with multiple languages, given the following `es.yml`
45
+
46
+ es:
47
+ user:
48
+ gender_choices:
49
+ male: 'Hombre
50
+ female: 'Mujer'
51
+
52
+ ...you can specify the attribute choices like this:
53
+
54
+ class User < ActiveRecord::Base
55
+ attribute_choices :gender, [ ['m', 'user.gender_choices.male'], ['f', 'user.gender_choices.female'] ],
56
+ :validate => true, :localize => true
57
+ end
58
+
59
+ Then, provided that `I18n.locale == :es`, you are good to go:
60
+
61
+ @john.gender_display
62
+ => 'Hombre'
63
+
64
+ User.gender_choices
65
+ => [["Hombre", 'm'], ['Mujer', 'f']]
66
+
67
+
68
+ ## Installation
69
+
70
+ #### Rails 3.x
8
71
 
9
72
  In your `Gemfile` add
10
73
 
11
74
  gem 'attribute_choices'
12
75
 
13
- ## Rails 2
76
+ #### Rails 2.x
14
77
 
15
78
  In `environment.rb` add:
16
79
 
17
80
  config.gem 'attribute_choices'
18
81
 
19
- # Usage
82
+ ## Changelog
20
83
 
21
- Define your model:
84
+ #### V1.0.2
22
85
 
23
- class User < ActiveRecord::Base
24
- attribute_choices :gender, { 'm' => "Male", 'f' => 'Female'}, :validate => true
25
- attribute_choices :age_group, [
26
- ['18-24', '18 to 24 years old'],
27
- ['25-45', '25 to 45 years old']
28
- ]
29
- end
86
+ * Works correctly with overridden ActiveRecord attribute accessors
87
+ * Multi-ruby integration testing with Travis-CI
30
88
 
31
- Then try this in the console:
32
-
33
- >> @john # User.new :gender => 'm', :age_group => '18-24', :name => 'John'
34
- >> @john.gender
35
- => 'm'
36
- >> @john.gender_display
37
- => 'Male'
38
- >> User.gender_choices
39
- => [["Male", 'm'], ['Female', 'f']]
40
-
41
- >> @john.valid?
42
- => true
43
- >> @john.gender # 'o'
44
- >> @john.valid?
45
- => false
46
-
47
- => I18n.locale # :es
48
- >> @john.gender_display
49
- => "translation missing: es, Male"
50
-
51
- >> @john.age_group_display
52
- => '18 to 24 years old'
53
- >> User.age_group_choices
54
- => [['18-24', '18 to 24 years old], ['25-45', '25 to 45 years old']]
55
-
56
- # ToDo
89
+ #### v1.0.1
57
90
 
58
- * Validate absence of _display and _choices methods
59
- * Consider the usefulness of _choices# method
91
+ * Refactor to eliminate deprecation warnings in Rails 3.1 (@porras)
60
92
 
93
+ #### v1.0.0
94
+
95
+ * Initial release
96
+
97
+ ## ToDo
98
+
99
+ * Validate absence of _display and _choices methods
61
100
 
62
101
  Copyright (c) 2009-2011 Christos Zisopoulos, released under the MIT license
@@ -0,0 +1,15 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require "bundler/gem_tasks"
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the attribute_choices plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "attribute_choices/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "attribute_choices"
7
+ s.version = AttributeChoices::VERSION
8
+
9
+ s.authors = ["Christos Zisopoulos"]
10
+ s.date = "2011-05-12"
11
+ s.email = "christos@me.com"
12
+
13
+
14
+ s.rubyforge_project = "attribute_choices"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.homepage = "http://github.com/christos/attribute_choices"
22
+
23
+ s.rdoc_options = ["--main", "README.md"]
24
+ s.extra_rdoc_files = ["README.md"]
25
+ s.summary = s.description = "Extends ActiveRecord attributes with a `:choices` pseudo-type that provides convenient methods for mapping each choice to its human readable form."
26
+
27
+ s.add_development_dependency "rake"
28
+ s.add_development_dependency "sqlite3"
29
+
30
+ s.add_dependency "activesupport"
31
+ s.add_dependency "activerecord"
32
+ end
@@ -7,7 +7,8 @@ module AttributeChoices
7
7
 
8
8
  module AttributeChoicesMacro
9
9
 
10
- # Associate a list of display values for an attribute with a list of discreet values
10
+ # Extends ActiveRecord attributes with a `:choices` pseudo-type that provides convenient methods for mapping
11
+ # each choice to its human readable form.
11
12
  #
12
13
  # The arguments are:
13
14
  #
@@ -61,7 +62,7 @@ module AttributeChoices
61
62
 
62
63
  define_method("#{attribute.to_s}_display") do
63
64
  # The local variable `choices` is saved inside this Proc
64
- tupple = choices.assoc(read_attribute(attribute))
65
+ tupple = choices.assoc(send(attribute))
65
66
  tupple && tupple.last
66
67
  end
67
68
 
@@ -74,14 +75,23 @@ module AttributeChoices
74
75
  end
75
76
 
76
77
  end
77
-
78
+
79
+ #:nodoc:
78
80
  def attribute_choices_options
79
81
  @attribute_choices_options ||= {}
80
82
  end
81
83
 
82
84
  private
83
85
  def assert_valid_attribute(attr_name)
84
- unless column_names.include?(attr_name.to_s)
86
+
87
+ if /1\.9/.match(RUBY_VERSION)
88
+ getter = attr_name.to_sym
89
+ setter ="#{attr_name}=".to_sym
90
+ else
91
+ getter = setter = attr_name.to_s
92
+ end
93
+
94
+ unless column_names.include?(attr_name.to_s) || (instance_methods.include?(getter) && instance_methods.include?(setter))
85
95
  raise ArgumentError, "Model attribute '#{attr_name.to_s}' doesn't exist"
86
96
  end
87
97
  end
@@ -0,0 +1,3 @@
1
+ module AttributeChoices
2
+ VERSION = "1.0.2"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :attributes_with_choices do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,142 @@
1
+ require 'test_helper'
2
+
3
+ class AttributeChoicesTest < ActiveSupport::TestCase
4
+
5
+ class Person < ActiveRecord::Base
6
+ attribute_choices :gender, {'m' => 'Male', 'f' => 'Female'}
7
+ end
8
+
9
+ class Adult < Person
10
+ attribute_choices :gender , {'m' => 'Man', 'f' => 'Woman', 'o' => 'Other'}
11
+ attribute_choices :salutation, [
12
+ ["mr", 'Mister'],
13
+ ["mrs", 'Misses'],
14
+ ["ms", 'Miss'],
15
+ ]
16
+ end
17
+
18
+ test "It should add a class method to all ActiveRecord objects" do
19
+ assert_respond_to(Person, :attribute_choices)
20
+ end
21
+
22
+ test "It should add a class and an instance method for each attribute" do
23
+ assert_respond_to(Person, :gender_choices)
24
+ assert_respond_to(Person.new, :gender_display)
25
+
26
+ assert_raise(NoMethodError) do
27
+ Object.gender_choices
28
+ end
29
+
30
+ end
31
+
32
+ test "A child AR object should not share the parent's choices" do
33
+ assert_not_equal Adult.gender_choices, Person.gender_choices
34
+ end
35
+
36
+ test "Does not allow specifying non-existent attributes" do
37
+ assert_raise ArgumentError do
38
+ class Person < ActiveRecord::Base
39
+ attribute_choices :non_existent_attribute, []
40
+ end
41
+ end
42
+ end
43
+
44
+ test "Allow specifying virtual attributes" do
45
+ assert_nothing_raised do
46
+ class Person < ActiveRecord::Base
47
+ attr_accessor :virtual_attribute
48
+ attribute_choices :virtual_attribute, {'w' => 'Wadus'}
49
+ end
50
+ end
51
+
52
+ @person = Person.new(:virtual_attribute => 'w')
53
+
54
+ assert_equal('Wadus', @person.virtual_attribute_display)
55
+ end
56
+
57
+ test "Does not allow invalid option keys" do
58
+ assert_raise ArgumentError do
59
+ class Person < ActiveRecord::Base
60
+ attribute_choices :gender, {'m' => 'Male', 'f' => 'Female'}, :not_a_real_option => true
61
+ end
62
+ end
63
+ end
64
+
65
+ test "given a valid value for an attribute the correct display value is returned " do
66
+ @person = Person.new(:gender => 'm', :salutation => 'mr')
67
+ assert @person.valid?
68
+
69
+ assert_equal 'Male', @person.gender_display
70
+ end
71
+
72
+ test "a localized version of the display value is returned when :localize => true" do
73
+ class Human < Person
74
+ attribute_choices :gender, [['m', 'Male'], ['f', 'Female']], :localize => true
75
+ end
76
+ @human = Human.new(:gender => 'm', :salutation => 'mr')
77
+
78
+ assert_equal I18n.translate('Male'), @human.gender_display
79
+ end
80
+
81
+ test "a localized version of the attribute choices is returned when :localize => true" do
82
+ class Human < Person
83
+ attribute_choices :gender, [['m', 'Male'], ['f', 'Female']], :localize => true
84
+ end
85
+ @human = Human.new(:gender => 'm', :salutation => 'mr')
86
+
87
+ assert_equal [[I18n.translate('Male'), 'm'], [I18n.translate('Female'), 'f']], Human.gender_choices
88
+ end
89
+
90
+ test "nil is returned as the display value of an attribute without a value to display mapping" do
91
+ @adult = Adult.new(:salutation => 'master')
92
+ assert_nil @adult.salutation_display
93
+
94
+ @adult.gender = 'unknown'
95
+ assert_nil @adult.gender_display
96
+
97
+ end
98
+
99
+ test "Multiple calls to attribute_choices update the attribute choices" do
100
+ class Medic < Adult; end
101
+ assert_equal [['Mister', 'mr'], ['Misses', 'mrs'], ["Miss", 'ms']], Medic.salutation_choices
102
+
103
+ class Medic < Adult
104
+ attribute_choices :salutation, [ ["dr", 'Doctor'] ]
105
+ end
106
+
107
+ assert_equal [ ['Doctor', 'dr'] ], Medic.salutation_choices
108
+ end
109
+
110
+ test "It should store an options Hash if passed as the the optional third parameter" do
111
+ class Person < ActiveRecord::Base
112
+ attribute_choices :gender, {'m' => 'Male', 'f' => 'Female'}, :localize => true, :validate => false
113
+ end
114
+ assert_equal Hash[:localize, true, :validate, false], Person.attribute_choices_options[:gender]
115
+ end
116
+
117
+ test "Default values are assigned for any options that are not specified" do
118
+ class Person < ActiveRecord::Base
119
+ attribute_choices :gender, {'m' => 'Male', 'f' => 'Female'}, :localize => true
120
+ end
121
+
122
+ assert_equal Hash[:localize, true, :validate, false], Person.attribute_choices_options[:gender]
123
+ end
124
+
125
+ test "Doesn't validate inclusion of attribute value in choices values by default" do
126
+ @person = Person.new(:gender => 'trans', :salutation => 'mr')
127
+ assert @person.valid?
128
+ end
129
+
130
+ test "Validates inclusion of attribute value in choices values when :localize => true" do
131
+ class Person < ActiveRecord::Base
132
+ attribute_choices :gender, {'m' => 'Male', 'f' => 'Female'}, :validate => true
133
+ end
134
+
135
+ @person = Person.new(:gender => 'm', :salutation => 'mr')
136
+ assert @person.valid?
137
+
138
+ @person.gender = 'trans'
139
+ assert !@person.valid?
140
+ end
141
+
142
+ end
@@ -0,0 +1,3 @@
1
+ sqlite3mem:
2
+ :adapter: sqlite3
3
+ :database: ":memory:"
@@ -0,0 +1,22 @@
1
+ # This file is auto-generated from the current state of the database. Instead of editing this file,
2
+ # please use the migrations feature of Active Record to incrementally modify your database, and
3
+ # then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6
+ # to create the application database on another system, you should be using db:schema:load, not running
7
+ # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
9
+ #
10
+ # It's strongly recommended to check this file into your version control system.
11
+
12
+ ActiveRecord::Schema.define(:version => 20090418155608) do
13
+
14
+ create_table "people", :force => true do |t|
15
+ t.string "salutation"
16
+ t.string "name"
17
+ t.string "gender"
18
+ t.datetime "created_at"
19
+ t.datetime "updated_at"
20
+ end
21
+
22
+ end
@@ -0,0 +1,19 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+
3
+ require 'rubygems'
4
+
5
+ require 'attribute_choices'
6
+
7
+ require 'test/unit'
8
+
9
+ require 'active_support/test_case'
10
+ require 'active_record/fixtures'
11
+
12
+
13
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
14
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
15
+ ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite3mem'])
16
+
17
+ ActiveRecord::Migration.verbose = false
18
+ load(File.dirname(__FILE__) + "/schema.rb")
19
+
metadata CHANGED
@@ -1,8 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attribute_choices
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 19
4
5
  prerelease:
5
- version: 1.0.1
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 2
10
+ version: 1.0.2
6
11
  platform: ruby
7
12
  authors:
8
13
  - Christos Zisopoulos
@@ -10,8 +15,7 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2011-05-12 00:00:00 +02:00
14
- default_executable:
18
+ date: 2011-05-12 00:00:00 Z
15
19
  dependencies:
16
20
  - !ruby/object:Gem::Dependency
17
21
  name: rake
@@ -21,6 +25,9 @@ dependencies:
21
25
  requirements:
22
26
  - - ">="
23
27
  - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
24
31
  version: "0"
25
32
  type: :development
26
33
  version_requirements: *id001
@@ -32,6 +39,9 @@ dependencies:
32
39
  requirements:
33
40
  - - ">="
34
41
  - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
35
45
  version: "0"
36
46
  type: :development
37
47
  version_requirements: *id002
@@ -43,6 +53,9 @@ dependencies:
43
53
  requirements:
44
54
  - - ">="
45
55
  - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
46
59
  version: "0"
47
60
  type: :runtime
48
61
  version_requirements: *id003
@@ -54,10 +67,13 @@ dependencies:
54
67
  requirements:
55
68
  - - ">="
56
69
  - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
57
73
  version: "0"
58
74
  type: :runtime
59
75
  version_requirements: *id004
60
- description: AttributeChoices is a plugin that simplifies the common pattern of mapping a set of discreet values for an ActiveRecord model attribute, to a set of display values for human consumption.
76
+ description: Extends ActiveRecord attributes with a `:choices` pseudo-type that provides convenient methods for mapping each choice to its human readable form.
61
77
  email: christos@me.com
62
78
  executables: []
63
79
 
@@ -66,10 +82,21 @@ extensions: []
66
82
  extra_rdoc_files:
67
83
  - README.md
68
84
  files:
85
+ - .gitignore
86
+ - .travis.yml
87
+ - Gemfile
88
+ - Gemfile.lock
69
89
  - License.md
70
90
  - README.md
91
+ - Rakefile
92
+ - attribute_choices.gemspec
71
93
  - lib/attribute_choices.rb
72
- has_rdoc: true
94
+ - lib/attribute_choices/version.rb
95
+ - tasks/attributes_with_choices_tasks.rake
96
+ - test/attribute_choices_test.rb
97
+ - test/database.yml
98
+ - test/schema.rb
99
+ - test/test_helper.rb
73
100
  homepage: http://github.com/christos/attribute_choices
74
101
  licenses: []
75
102
 
@@ -84,19 +111,28 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
111
  requirements:
85
112
  - - ">="
86
113
  - !ruby/object:Gem::Version
114
+ hash: 3
115
+ segments:
116
+ - 0
87
117
  version: "0"
88
118
  required_rubygems_version: !ruby/object:Gem::Requirement
89
119
  none: false
90
120
  requirements:
91
121
  - - ">="
92
122
  - !ruby/object:Gem::Version
123
+ hash: 3
124
+ segments:
125
+ - 0
93
126
  version: "0"
94
127
  requirements: []
95
128
 
96
- rubyforge_project:
97
- rubygems_version: 1.6.2
129
+ rubyforge_project: attribute_choices
130
+ rubygems_version: 1.8.9
98
131
  signing_key:
99
132
  specification_version: 3
100
- summary: AttributeChoices is a plugin that simplifies the common pattern of mapping a set of discreet values for an ActiveRecord model attribute, to a set of display values for human consumption.
101
- test_files: []
102
-
133
+ summary: Extends ActiveRecord attributes with a `:choices` pseudo-type that provides convenient methods for mapping each choice to its human readable form.
134
+ test_files:
135
+ - test/attribute_choices_test.rb
136
+ - test/database.yml
137
+ - test/schema.rb
138
+ - test/test_helper.rb