This gem adds class methods to ActiveRecord::Base to enable list-like relations.
Add it to your gemfile:
gem "ar-lists"
Update your bundle:
bundle install
Define your array-like relation in your Model, like any other relation. Elements will be stored as String elements so usually you will use it to store String content, such as phone numbers:
#File : app/models/user.rb
class User < ActiveRecord::Base
array_accessible :phone_numbers
end
Then access the lists like any other attribute:
#File : app/controllers/users_controller.rb
...
@user = User.first
@user.phone_numbers = [
"+33 6 12 34 56 78",
"+33 1 98 76 54 32"
]
@user.phone_numbers
# -> ["+33 6 12 34 56 78", "+33 1 98 76 54 32"]
...
This other method provides you with a useful means to store a list of relations in one place. The class of your elements will be guessed from the attribute name, and elements will be stored with their ID.
#File : app/models/users_group.rb
class UsersGroup < ActiveRecord::Base
has_list :users
end
Then access the lists like any other attribute:
#File : app/controllers/users_groups_controller.rb
...
@group = UsersGroup.first
@group.users = [User.find(2), User.find(25), User.find(5)]
@group.users
# -> [#<User:0x... @id=2>, #<User:0x... @id=25>, #<User:0x... @id=5>]
...
:class_name => 'Toto'
allows you to force which class name to use (Toto, here):uniq => true
allows your list to act like a group with only one instance of each element max in the list:strict => true
allows you to throw an error whenever a related record cannot be found anymore (cf. Non-existing instances):polymorphic => true
allows you to type the elements so that you can store different types of elements in the same list (cf. Polymorphic records list)
By passing the option :polyprophic => true
to a relation, you can use your list as a way to store different types of elements. See the example bellow:
#File : app/models/boy.rb
class Boy < ActiveRecord::Base
end
#File : app/models/girl.rb
class Girl < ActiveRecord::Base
end
#File : app/models/group.rb
class Group < ActiveRecord::Base
has_list :members,
:polymorphic => true, # to save the type of each element
:uniq => true # to store only one instance of each element max
end
#File : app/controllers/groups_controller.rb
...
@group = Group.first
@group.members = [Boy.find(2), Girl.find(25), Boy.find(5)]
@group.members
# -> [#<Boy:0x... @id=2>, #<Girl:0x... @id=25>, #<Boy:0x... @id=5>]
...
When manipulating :has_list
relations, you can use ID-methods instead of standard methods to improve performance.
Of course, this only works with non-polymorphic relations.
#File : app/models/users_group.rb
class UsersGroup < ActiveRecord::Base
has_list :users
end
#File : app/controllers/users_groups_controller.rb
...
@group = UsersGroup.first
@group.users_ids = [13,42]
@group.users
# -> [#<User:0x... @id=13>, #<User:0x... @id=42>]
@group.users_ids
# -> [13,42]
...
When IDs you provide don’t exist in your Database, the default behaviour is to ignore them. If you want, you can force an error to be thrown when this happens by using the :strict
option:
#File : app/models/users_group.rb
class UsersGroup < ActiveRecord::Base
has_list :users,
:strict => true
end
Thus whenever your DB object contains old IDs that have been removed or you try to add by hand an ID that doesn’t exist, an error will be thrown:
#File : app/controllers/users_groups_controller.rb
...
@group = UsersGroup.first
@group.users = [User.find(2), User.find(3)]
User.find(3).destroy
@group.users
# -> throws "Unable to build list: RecordNotFound"
...
Happy listing =)