【问题标题】:simplified 'logical' models to cleanly access highly normalized database简化的“逻辑”模型以干净地访问高度规范化的数据库
【发布时间】:2012-10-02 19:18:11
【问题描述】:

我知道使用表单添加/编辑/删除(嵌套)记录的一种方法是在相应的模型中使用 :accepts_nested_attributes_for: 。但是,当这种嵌套扩展到大约 4 级时(由于数据库的规范化),并且我想在网站上显示所有这些级别以进行编辑,这种方法似乎相当麻烦(而且丑陋)。

我想知道是否有一种方法可以使用 getter 和 setter 方法定义“超级”模型,允许我在一个地方编辑必要的数据。作为一个简化示例,请考虑:

class Person < ActiveRecord::Base
  attr_accessible :name, :age

  has_one :address
end

class Address < ActiveRecord::Base
  attr_accessible :street, :zip, :country

  belongs_to :person
end

我想以一种形式显示/编辑/更新/等姓名、年龄、街道、邮编、国家。很清楚如何使用 Accepts_nested_attributes_for 执行此操作。但是我想要一个类,比如 PersonalInformation,它通过传入 Person 的 id 来结合两个类中的字段名称、年龄、街道、邮编、国家/地区。然后我想用这个类作为网站的接口。

【问题讨论】:

    标签: ruby-on-rails ruby forms simple-form


    【解决方案1】:

    类似于此处描述的表单对象:

    http://robots.thoughtbot.com/activemodel-form-objects

    我一直在尝试各种实现,但没有找到完美的解决方案,但它们确实简化了“将一堆模型放在一起”。 codeclimate 博客也涉及到它(第 3 项):

    http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models

    codeclimate 帖子使用包含 ActiveModel 模块的旧方法(除非您现在想单独包含它们,否则无需单独包含它们),但概念是相同的。

    【讨论】:

      【解决方案2】:

      我会推荐simple form gem。我从他们的文档中修改了一个示例,以反映您的模型完全符合您的要求:

      型号:

      class Person < ActiveRecord::Base
        attr_accessible :name, :age
      
        has_one :address
      end
      
      class Address < ActiveRecord::Base
        attr_accessible :street, :zip, :country
      
        belongs_to :person
      end
      

      查看:

      <%= simple_form_for @person do |f| %>
        <%= f.input :name %>
        <%= f.input :age %>
        <%= f.association :street %>
        <%= f.association :zip %>
        <%= f.association :country %>
        <%= f.button :submit %>
      <% end %>
      

      【讨论】:

      • 据我所知,f.association to 不支持 has_one 关联。我也知道如何让它与 simple_form 和不同类型的多个嵌套关联一起工作。但我不想一直思考数据库是如何组织的。我想创建新模型,为代表数据库的物理模型提供一个很好的接口。
      【解决方案3】:

      您可以在 Person 模型上使用虚拟属性,并将自定义分配逻辑放入每个可编辑的 Address 属性的 getter/setter 中。

      class Person < ActiveRecord::Base
        attr_accessible :name, :age
      
        has_one :address
      
        def street=(new_street)
          # ...
        end
      end
      

      从长远来看,这最终可能会变得更加复杂。

      【讨论】:

        猜你喜欢
        • 2017-09-09
        • 2014-07-15
        • 2011-03-03
        • 2010-10-22
        • 2012-03-03
        • 1970-01-01
        • 2014-08-10
        • 2011-11-04
        相关资源
        最近更新 更多