# μ-attributes (Micro::Attributes) This gem allows defining read-only attributes, that is, your objects will have only getters to access their attributes data. ## Installation Add this line to your application's Gemfile: ```ruby gem 'u-attributes' ``` And then execute: $ bundle Or install it yourself as: $ gem install u-attributes ## Usage ### How to require? ```ruby # Bundler will do it automatically, but if you desire to do a manual require. # Use one of the following options: require 'micro/attributes' # or require 'u-attributes' ``` ### How to define attributes? ```ruby # By default you must to define the class constructor. class Person include Micro::Attributes attribute :name attribute :age def initialize(name: 'John Doe', age:) @name, @age = name, age end end person = Person.new(age: 21) puts person.name # John Doe puts person.age # 21 # By design, the attributes expose only reader methods (getters). # If you try to call a setter, you will see a NoMethodError. # # person.name = 'Rodrigo' # NoMethodError (undefined method `name=' for #) #------------------# # self.attributes= # #------------------# # This protected method is added to make easier the assignment in a constructor. class Person include Micro::Attributes attribute :name attribute :age def initialize(options) self.attributes = options end end person = Person.new('name' => 'John', age: 20) puts person.name # John puts person.age # 20 #--------------# # #attribute() # #--------------# # # Use the #attribute() method with a valid attribute name to get its value puts person.attribute(:name) # John puts person.attribute('age') # 20 puts person.attribute('foo') # nil # # If you pass a block, it will be executed only if the attribute is valid. person.attribute(:name) { |value| puts value } # John person.attribute('age') { |value| puts value } # 20 person.attribute('foo') { |value| puts value } # !! Nothing happened, because of the attribute not exists. #--------------# # #attribute() # #--------------# # # Works like the #attribute() method, but will raise an exception when the attribute not exist. puts person.attribute!('foo') # NameError (undefined attribute `foo) person.attribute!('foo') { |value| puts value } # NameError (undefined attribute `foo) ``` ### How to define multiple attributes? ```ruby # Use .attributes with a list of attribute names. class Person include Micro::Attributes attributes :name, :age def initialize(options) self.attributes = options end end person = Person.new('Serradura', 32) puts person.name # Serradura puts person.age # 32 ``` ### How to define attributes with a constructor to assign them? A: Use `Micro::Attributes.to_initialize` ```ruby class Person include Micro::Attributes.to_initialize attributes :age, name: 'John Doe' # Use a hash to define a default value # attribute name: 'John Doe' # attribute :age end person = Person.new(age: 18) puts person.name # John Doe puts person.age # 18 ############################################## # Assigning new values to get a new instance # ############################################## #-------------------# # #with_attribute() # #-------------------# another_person = person.with_attribute(:age, 21) puts another_person.name # John Doe puts another_person.age # 21 puts another_person.equal?(person) # false #--------------------# # #with_attributes() # #--------------------# # # Use it to assign multiple attributes other_person = person.with_attributes(name: 'Serradura', age: 32) puts other_person.name # Serradura puts other_person.age # 32 puts other_person.equal?(person) # false # If you pass a value different of a Hash, an ArgumentError will be raised. # # Person.new(1) # ArgumentError (argument must be a Hash) ################ # Inheritance # ################ class Subclass < Person # Will preserve the parent class attributes attribute :foo end instance = Subclass.new({}) puts instance.name # John Doe puts instance.respond_to?(:age) # true puts instance.respond_to?(:foo) # true #---------------------------------# # .attribute!() or .attributes!() # #---------------------------------# # The methods above allow redefining the attributes default data class AnotherSubclass < Person attribute! name: 'Alfa' end alfa_person = AnotherSubclass.new({}) p alfa_person.name # "Alfa" p alfa_person.age # nil class SubSubclass < Subclass attributes! name: 'Beta', age: 0 end beta_person = SubSubclass.new({}) p beta_person.name # "Beta" p beta_person.age # 0 ``` ### How to query the attributes? ```ruby class Person include Micro::Attributes attributes :age, name: 'John Doe' def initialize(options) self.attributes = options end end #---------------# # .attributes() # #---------------# p Person.attributes # ["name", "age"] #---------------# # .attribute?() # #---------------# puts Person.attribute?(:name) # true puts Person.attribute?('name') # true puts Person.attribute?('foo') # false puts Person.attribute?(:foo) # false # --- person = Person.new(age: 20) #---------------# # #attribute?() # #---------------# puts person.attribute?(:name) # true puts person.attribute?('name') # true puts person.attribute?('foo') # false puts person.attribute?(:foo) # false #---------------# # #attributes() # #---------------# p person.attributes # {"age"=>20, "name"=>"John Doe"} p Person.new(name: 'John').attributes # {"age"=>nil, "name"=>"John"} ``` ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/serradura/u-attributes. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). ## Code of Conduct Everyone interacting in the Micro::Attributes project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/serradura/u-attributes/blob/master/CODE_OF_CONDUCT.md).