代码之家  ›  专栏  ›  技术社区  ›  tybro0103

Rails通过多个属性查找或创建?

  •  195
  • tybro0103  · 技术社区  · 15 年前

    在活动记录中有一个方便的动态属性,称为find_或\ create_by:

    Model.find_or_create_by_<attribute>(:<attribute> => "")

    但是如果我需要找到由多个属性创建的\或\怎么办?

    假设我有一个模型来处理组和名为group member的成员之间的m:m关系。我可以有许多member_id=4的实例,但我从来都不想要member_id=4和group_id=7的多个实例。我想知道是否可以这样做:

    GroupMember.find_or_create(:member_id => 4, :group_id => 7)
    

    我意识到也许有更好的方法来处理这个问题,但我喜欢“发现”或“创造”这个概念的便利性。

    5 回复  |  直到 7 年前
        1
  •  455
  •   Deepak Mahakale    8 年前

    多个属性可以与 and :

    GroupMember.find_or_create_by_member_id_and_group_id(4, 7)
    

    (使用) find_or_initialize_by 如果不想立即保存记录)

    编辑: 上述方法在Rails 4中已弃用。新的方法是:

    GroupMember.where(:member_id => 4, :group_id => 7).first_or_create
    

    GroupMember.where(:member_id => 4, :group_id => 7).first_or_initialize
    

    编辑2: 并不是所有这些都是从Rails中分解出来的,只是特定于属性的。

    https://github.com/rails/rails/blob/4-2-stable/guides/source/active_record_querying.md

    例子

    group member.find_or_create_by_member_id_and_group_id(4,7)
    

    成为

    GroupMember.find_or_create_by(member_id: 4, group_id: 7)
    
        2
  •  31
  •   Marco    13 年前

    对于任何其他遇到此线程但需要查找或创建属性可能随环境变化的对象的人,请将以下方法添加到模型中:

    # Return the first object which matches the attributes hash
    # - or -
    # Create new object with the given attributes
    #
    def self.find_or_create(attributes)
      Model.where(attributes).first || Model.create(attributes)
    end
    

    优化提示: 无论您选择哪种解决方案,请考虑为您最经常查询的属性添加索引。

        3
  •  27
  •   Juanito Fatas    11 年前

    在Rails 4中,您可以执行以下操作:

    GroupMember.find_or_create_by(member_id: 4, group_id: 7)
    

    使用 where 不同:

    GroupMember.where(member_id: 4, group_id: 7).first_or_create
    

    这将呼叫 create GroupMember.where(member_id: 4, group_id: 7) :

    GroupMember.where(member_id: 4, group_id: 7).create
    

    相反,在 find_or_create_by(member_id: 4, group_id: 7) 将呼叫 创造 GroupMember :

    GroupMember.create(member_id: 4, group_id: 7)
    

    请查看相关信息 commit 在栏杆上。

        4
  •  14
  •   Daniel Murphy    12 年前

    通过一个街区 find_or_create ,可以传递其他参数,这些参数将在对象新建时添加到该对象中。如果您正在验证不通过搜索的字段是否存在,则此选项非常有用。

    假设:

    class GroupMember < ActiveRecord::Base
        validates_presence_of :name
    end
    

    然后

    GroupMember.where(:member_id => 4, :group_id => 7).first_or_create { |gm| gm.name = "John Doe" }
    

    如果找不到名为“john doe”的新groupmember, member_id 4 and group_id 7

        5
  •  4
  •   Dorian    10 年前

    你可以做到:

    User.find_or_create_by(first_name: 'Penélope', last_name: 'Lopez')
    User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_create
    

    或者只是初始化:

    User.find_or_initialize_by(first_name: 'Penélope', last_name: 'Lopez')
    User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_initialize