-1

How do I select a single entity from a relation? I’m using Rails 4.2.3. I have the below query, which joins on another table, but I only wish to delete one of the objects (the object of type “UserMyObjectTimeMatch”) …

      user_my_object_time_match = UserMyObjectTimeMatch.joins(:my_object_time)
                                              .select(:user_my_object_time_match)   
                                              .where("race_time_id = ?", linked_my_object.race_times[0].id)
      if !user_my_object_time_match.nil?
        user_my_object_time_match.destroy
      end

Unfortunately, when the “user_my_object_time_match.destroy” line is called, a “wrong number of arguments (given 0, expected 1)” error is resulting and I believe it is because the object I’m selecting is not of the right type. How do I properly select an object from a relation?

Dave
  • 15,639
  • 133
  • 442
  • 830
  • Have you read the [documentation](http://guides.rubyonrails.org/active_record_querying.html)? Take a look at the find_by method. – hypern Jun 17 '16 at 15:22
  • Yeah but I was reading the section in the documentation about "joins" since I'm using criteria from a relation of the object in question. I'm not clear how I would combine joins with find_by to get the record of the object type I want. – Dave Jun 17 '16 at 15:28

2 Answers2

0

With .where query you will get back an ActiveRecord relation object, which you can loop over, but looking at your query the results that you will get would be

#<ActiveRecord::Relation [#<UserMyObjectTimeMatch id: nil, user_my_object_time_match: some_id>]

even if you loop over this object and do a destroy, the query that is going to run is

DELETE FROM "user_my_object_time_matches" WHERE "user_my_object_time_match"."id" = $1  [["id", nil]]

id is nil so this is not going to delete anything from your database. You will need to remove that select method, and then do a loop over whatever you get, but since you want a single object try #find_by(race_time_id: id) and then in from the result you can directly do a .destroy.

If you still want to use .destroy using the select query then do a .select(:id, :user_my_object_time_match)) and then loop over each and destroy.

Saad
  • 1,856
  • 1
  • 22
  • 28
0

Using things like where will always give you a collection of objects, not just one. (Technically it is not yet an array but a Relation, so that you can keep calling more methods like where, select, includes, etc and build up the SQL query before running it.) Also you'll never get nil from methods like where; it will just be a Relation that yields zero records (Foo.where("1=0").to_a is [] not nil). So if you "know" you're only going to get zero or one objects, you can do Foo.where("bar").first. Then you'll get the object or nil.

You may also want to look at find_by and find_by! which return a single object instead of a relation. You can even use that at the end of other ActiveRecord methods, like Foo.where("bar").find_by(what: "ever").

Paul A Jungwirth
  • 23,504
  • 14
  • 74
  • 93