Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the `<>` in Rails query mean?

I am having a hard time searching meaning of symbols like what <> means in rails querying. So what does <> mean? (or in general, how do you google search for things like <>?)

Nutshell

In plain English, what do the following queries mean?

Query 1:

@profile.socials.all.where.not(kind: [2, 3])

Query 2:

@profile.socials.where("kind <> ?", "[:facebook, :linked_in]")

Note 1: kind is of data type enum that looks like this:

enum kind: [ :twitter, :google_plus, :facebook, :linked_in, :skype, :yahoo ]

Note 2: both queries produce the same result in console window. I believe both queries aims to do a where query to subset data (with the not-equal-to operator). I just have no clues on know how to interpret that <>.

Detail Rails App

These are my models:

Model Profile:

class Profile < ActiveRecord::Base
  has_many :socials, as: :sociable, dependent: :destroy
  accepts_nested_attributes_for :socials, allow_destroy: true
end

Model Social:

class Social < ActiveRecord::Base
  enum kind: [ :twitter, :google_plus, :facebook, :linked_in, :skype, :yahoo ]
  belongs_to :sociable, polymorphic: true
  validates_presence_of :kind
  validates_presence_of :username
end

Migration files:

class CreateProfiles < ActiveRecord::Migration
  def change
    create_table :profiles do |t|
      t.string :first_name
      t.string :last_name
      t.timestamps null: false
    end
  end
end


class CreateSocials < ActiveRecord::Migration
  def change
    create_table :socials do |t|
      t.integer :kind, null: false
      t.string :username
      t.references :sociable, polymorphic: true, index: true

      t.timestamps null: false
    end
    add_index :socials, :kind
    add_index :socials, :username
  end
end

This is what my schema looks like:

ActiveRecord::Schema.define(version: 20160311132502) do

  create_table "profiles", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "socials", force: :cascade do |t|
    t.integer  "kind",          null: false
    t.string   "username"
    t.integer  "sociable_id"
    t.string   "sociable_type"
    t.datetime "created_at",    null: false
    t.datetime "updated_at",    null: false
  end

  add_index "socials", ["kind"], name: "index_socials_on_kind"
  add_index "socials", ["sociable_type", "sociable_id"], name: "index_socials_on_sociable_type_and_sociable_id"
  add_index "socials", ["username"], name: "index_socials_on_username"

end

 Console input

@profile = Profile.new
@profile.first_name = parameter[:profile][:first_name]
@profile.last_name = parameter[:profile][:last_name]
@profile.socials_attributes = parameter[:profile][:socials_attributes]
@profile.save
@profile = Profile.last
@profile.socials.kinds
@profile.socials.all.where(kind: 2) # => gives you the user facebook account
@profile.socials.all.where(kind: :facebook) # => Apparently only works in Rails 5 or above.

@profile.socials.all.where(kind: [2, 3]) # => gives you the user facebook and linked_in account
@profile.socials.all.where(kind: [:facebook, :linked_in]) # => Apparently only works in Rails 5 or above.

Console Tips - Rails 4 workaround (no need in Rails 5)

These two queries are equivalent (select only the user's facebook account):

@profile.socials.all.where(kind: 2)

@profile.socials.all.where(kind: @profile.socials.kinds.keys.find_index("facebook"))

These two queries are equivalent (select only the user's facebook and linked_in account):

@profile.socials.all.where(kind: [2, 3])

@profile.socials.all.where(kind: [@profile.socials.kinds.keys.find_index("facebook"), @profile.socials.kinds.keys.find_index("linked_in")])
like image 360
Atlas7 Avatar asked Oct 19 '25 14:10

Atlas7


1 Answers

The <> is SQL syntax, not Ruby or Rails. It means not equal to. It is basically the same as != in Ruby.

One subtlety of <> in SQL is its behavior with NULLs. In SQL, comparing anything to NULL gives NULL. For instance in Postgres:

=> select 1<>1, 1<>2, 1<>null, null<>1, null<>null;
 ?column? | ?column? | ?column? | ?column? | ?column? 
----------+----------+----------+----------+----------
 f        | t        | NULL     | NULL     | NULL

Notice how even the last expression is NULL! Often this is not what you want, and you can instead use IS DISTINCT FROM:

=> select null is distinct from 1, null is distinct from null;
 ?column? | ?column? 
----------+----------
 t        | f

EDIT: To address your follow-up question: in your database kind is an integer. So you want to compare it with integers:

@profile.socials.where.not(kind: [2, 3])

Or if you are using Rails 5:

@profile.socials.where.not(kind: [:facebook :linked_in])

The above works because Rails 5 will automatically use your enum declaration to convert those symbols into the appropriate integers.

like image 96
Paul A Jungwirth Avatar answered Oct 22 '25 03:10

Paul A Jungwirth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!