 
     for klass in @has_many()
       do(klass) ->
+        #FIXME : maybe normalize class name
         self["_#{klass}"] = []
         self.attributes.push("#{klass}")
-        self["add_#{klass}"] = (z) ->
+        self["add_#{klass}"] = (z) =>
           name = z.constructor.name
-          me = self.normal_name()
+          me   = self.normal_name()
+          m_name = self.constructor.name
+
           expected = klass.charAt(0).toUpperCase() + klass.slice(1)
           throw "Expected #{expected}, but given: #{name}" if name isnt expected
+          self.get("#{klass}").push(z)
+
           #feedback
-          if z.attributes.indexOf(me) > -1
-            if z.has_one().indexOf(me) > -1
-              m = z.get("#{me}")
-              z.set("#{me}", self) if !m
-            else if z.has_many().indexOf(me) > -1
-              z.get("#{me}").push(self)
-
-
-          self.get("#{klass}").push(z)
+          b_model = (for i in z.belongs_to()
+            do(i) ->
+              i if i['model'] == me
+          )[0]
+
+          if !b_model
+            throw "Model #{name} must contain '@belongs_to: [{model: #{me}, back: #{me}_id]'"
+
+          if !(back = b_model['back'])
+            throw "Define 'back' property for @belongs_to"
+
+          if self.attributes.indexOf(back) == -1
+            throw "Foreign key: '#{back}' not contain in a '#{m_name}' model"
+
+          key = "#{me}_#{back}"
+          if z.attributes.indexOf(key) == -1
+            throw "Define #{key} in @attrs for '#{expected}' model"
+
+          z.set("#{key}", self.get(back))
+          #TODO: logs
+
 
     for klass in @has_one()
       do(klass) ->
         self["_#{klass}"] = null
         self.attributes.push("#{klass}")
-        self["add_#{klass}"] = (z) ->
+        self["add_#{klass}"] = (z) =>
           name = z.constructor.name
-          me = self.normal_name()
+          me   = self.normal_name()
+          m_name = self.constructor.name
+
           expected = klass.charAt(0).toUpperCase() + klass.slice(1)
           throw "Expected #{expected}, but given: #{name}" if name isnt expected
 
-          t = self.get("#{klass}")
-          throw "Model #{klass} exist" if t
-
-          if z.attributes.indexOf(me) > -1
-            if z.has_one().indexOf(me) > -1
-              m = z.get("#{me}")
-              z.set("#{me}", self) if !m
-            else if z.has_many().indexOf(me) > -1
-              z.get("#{me}").push(self)
+          if self.get("#{klass}")
+            throw "Model #{expected} already exist for #{m_name}"
 
           self.set("#{klass}", z)
+
+          #feedback
+          b_model = (for i in z.belongs_to()
+            do(i) ->
+              i if i['model'] == me
+          )[0]
+
+          if !b_model
+            throw "Model #{name} must contain '@belongs_to: [{model: #{me}, back: #{me}_id]'"
+
+          if !(back = b_model['back'])
+            throw "Define 'back' property for @belongs_to"
+
+          if self.attributes.indexOf(back) == -1
+            throw "Foreign key: '#{back}' not contain in a '#{m_name}' model"
+
+          key = "#{me}_#{back}"
+          if z.attributes.indexOf(key) == -1
+            throw "Define #{key} in @attrs for '#{expected}' model"
+
+          z.set("#{key}", self.get(back))
+          #TODO: logs
 
 
     if Object.keys(obj).length != 0

    @.from_json(SiriusApplication.adapter.form_to_json("form[name='#{form_name}'"))



    @attrs: ["name"]
    has_one: Person

has_one, has_many must take arrays with models

belongs_to must take a array with objects as { :model => modelName[String] } with optional
  argument a foreign key :

  belongs_to { model => "person", :back => "name" }
  generate next methods:
    model_back ~> person_name

  if a belongs_to not present must be a throw exception



###

class BaseModel

  attrs: () ->
    @constructor.attrs || []

  #normalize model name: UserModel => user_model
  normal_name: () ->
    @constructor.name.replace(/([A-Z])/g, '_$1').replace(/^_/,"").toLowerCase()

