attribute_choices 1.0.1 → 1.0.2

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