# CleanModel Extensions for ActiveModel to implement multiple types of models ## Installation Add this line to your application's Gemfile: gem 'clean_model' And then execute: $ bundle Or install it yourself as: $ gem install clean_model ## Basic models ### Class definitions class Person include CleanModel::Base attribute :first_name attribute :last_name end ### Usage person = Person.new first_name: 'John', last_name: 'Doe' person.first_name -> 'John' person.last_name -> 'Doe' person.attributes -> {first_name: 'John', last_name: 'Doe'} person.assign_attributes first_name: 'Jorge' person.attributes -> {first_name: 'Jorge', last_name: 'Doe'} ### Active Model validations class Person include CleanModel::Base attribute :first_name attribute :last_name validates_presence_of :first_name, :last_name end person = Person.new person.valid? -> false ### Strong typing class Engine include CleanModel::Base attribute :power, class_name: :numeric attribute :cylinders, class_name: :integer attribute :valves, class_name: 'Integer' end engine = Engine.new engine.power = 130 engine.cylinders = 6.1 -> Raise error CleanModel::InvalidTypeAssignment ### Transformations class Car include CleanModel::Base attribute :brand attribute :model attribute :engine, class_name: 'Engine' attribute :comfort, transformation: lambda { |v| v.is_a?(String) ? v.split(',').map(&:strip) : v } end car = Car.new do |c| c.engine = {power: 110, cylinders: 16, valves: 6} end car.engine -> car = Car.new do |c| c.comfort = 'bluetooth, gps, electric pack' end car.comfort -> ['bluetooth', 'gps', 'electric pack'] ### Collections class Factory include CleanModel::Base attribute :cars, collection: 'Car' end factory = Factory.new do |f| f.cars = [ {brand: 'Honda', model: 'Civic'}, {brand: 'Toyota', model: 'Corolla'}, ] end factory.cars -> [, ] ## Models with custom persistence ### Definition class Post include CleanModel::Persistent attribute :subject attribute :content private def create ... end def update ... end def delete ... end end ### Usage Post.create(subject: 'Title', content: 'Some text') or post = Post.new subject: 'Title', content: 'Some text' post.save post.content = 'Another text' post.save post.update_attributes(title: 'Another title') post.destroy ## Remote models (for REST APIs) ### Definition class User include CleanModel::Remote connection host: 'localhost', port: 9999 attribute :first_name attribute :last_name attribute :email def self.find(id) http_get "/users/#{id}.json" do |response| new JSON.parse(response.body) emd end private def create http.post '/users/create.json', wrapped_attributes end def update http.put "/users/#{id}.json", wrapped_attributes(except: :id) end def delete http.delete("/users/#{id}.json") end end ### Usage User.create first_name: 'John', last_name: 'Doe' user = User.find(1) user.update_attributes(first_name: 'Jorge') user.destroy ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Added some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request