【问题标题】:Many-to-one association where the association ID (rather than values) is changed更改关联 ID(而不是值)的多对一关联
【发布时间】:2011-11-30 03:48:53
【问题描述】:

我有一个User 模型belongs_to :location(即每个用户只能有一个位置,但一个位置可以由多个用户共享)。 users 表有一个 location_id 列来跟踪这一点。

但是,如果用户想要更改他们的位置,我相信 Rails 关联的默认行为是更改实际关联;但是,在这种情况下,我希望现有关联(即现有 Location 记录)保持不变,并创建一个新关联。

例如,假设我们有用户 Alice、Bob、Charley 和 Dave,他们都有location_id == 1,对应于位置 123 Sesame St. 然后当 Dave 将其位置更改为 124 Sesame St. 时,Location 1 不应受到任何影响或更改,Location 2 应使用新信息创建,并且 Dave 的用户记录已更新以反映 location_id 现在是 2 而不是 1。

我想在模型级别进行更改(大概是 User 模型),以便如果更改任何位置信息(Useraccepts_nested_attributes_for :location),Location 关联会正确更新而不会覆盖现有信息。

有没有办法做到这一点,内置到 Rails 或插件中?

【问题讨论】:

    标签: ruby-on-rails associations


    【解决方案1】:

    accepts_nested_attributes_for 创建了一些用于处理嵌套表单的辅助方法。在您的情况下,您需要覆盖 setter。这应该可以帮助您入门。

    class User
    
      accepts_nested_attributes_for :location
    
      def location_attributes= attrs
        new_location   = Location.where(attrs).first
        new_location ||= Location.create attrs
    
        self.location = new_location
      end
    
    end
    

    在你的表单中像这样的东西

    = f.fields_for :location do |lf|
      .field
        = lf.label      :address
        = lf.text_field :address
      .field
        = lf.label      :city
        = lf.text_field :city
    

    一些注意事项:

    • 如果您的用户根本没有位置,则不会显示该位置的字段。在您的表单或控制器中添加对 @user.build_location 的调用。
    • 您可能想要改进查找/创建逻辑,这是一个非常人为的示例

    如果您的位置模型是单个字段,则可以通过使用虚拟属性来简化整个事情

    class User
      def location_address= address
        new_location = Location.find_or_create_by_address(address)
        self.location = new_location
      end
    
      def location_address
        location.address
      end
    end
    

    在这种情况下,您只需要在表单中添加一个文本字段

    = f.text_field :location_address
    

    【讨论】:

    • Location 不仅仅是一个字段(它有国家、州、城市、地址等),但这是一个有趣的见解 - 我不知道 location_attributes= 方法。我在想我必须以某种方式更改记录(例如,可能使用find_or_create_by(...)),比如before_save,但这可能是一个更好的主意!
    • 我能预见的唯一问题是如果直接访问/更改 user.location.attribute 会怎样?有什么办法保护它?
    猜你喜欢
    • 2021-09-22
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多