Check If a Table Exists in Rails

Check if a table exists in Rails

In Rails 5 the API became explicit regarding tables/views, collectively data sources.

# Tables and views
ActiveRecord::Base.connection.data_sources
ActiveRecord::Base.connection.data_source_exists? 'kittens'

# Tables
ActiveRecord::Base.connection.tables
ActiveRecord::Base.connection.table_exists? 'kittens'

# Views
ActiveRecord::Base.connection.views
ActiveRecord::Base.connection.view_exists? 'kittens'

In Rails 2, 3 & 4 the API is about tables.

# Listing of all tables and views
ActiveRecord::Base.connection.tables

# Checks for existence of kittens table/view (Kitten model)
ActiveRecord::Base.connection.table_exists? 'kittens'

Getting the status of migrations:

# Tells you all migrations run
ActiveRecord::Migrator.get_all_versions

# Tells you the current schema version
ActiveRecord::Migrator.current_version

If you need more APIs for migrations or metadata see:

  • ActiveRecord::SchemaMigration

    this is the ActiveRecord::Base class for the schema_migrations table
  • ActiveRecord::Migrator

    where all the action happens when migrations are run

how do i check if name exists in Associations table before create

You can add a custom validation for your Item model. Before saving it it will run and create if your conditions is met or just will give an error like you wrote in question.

class Item < ApplicationRecord
belongs_to :prom

validate :validate_prom_exist

def validate_prom_exist
prom = Prom.where(promname: self.prom.promname)
if prom.blank?
errors.add(:item, 'i dont have that prom')
end
end
end

How iterate to find if any record in a table exists

That's a wicked XY Problem you have there. You don't want to know how to "How iterate to find if any record in a table exists". You want to know "How to conditionally generate a link?"

In your case, just do:

<!DOCTYPE html>
<html>
<head>
<title>Bar Reviews</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= favicon_link_tag asset_path('favicon.ico') %>

</head>

<body>
<a href="/">
<h1 id="title-top">
Bar Reviews
</h1>
</a>
<header>
<nav class="navBar">
<%= link_to "Home", root_path %>
<%= link_to "Bars", bars_path %>
<%= link_to("No Reviews", bars_norev_path) if @bars_needing_review.any? %>
<%= link_to "About", pages_about_url %>
</nav>
</header>

<%= yield %>
</body>

</html>

Naturally, you'll need to set the @bars_needing_review variable somewhere appropriate in your controller (could be in ApplicationController - depends). Something, perhaps like:

@bars_needing_review = Bar.with_name.not_flagged_as_inappropriate.without_any_reviews

This implies that you've set up the with_name, not_flagged_as_inappropriate, and without_any_reviews methods on your Bar class, something like:

class Bar < ApplicationRecord

class << self

def with_name
where.not(name: nil)
end

def not_flagged_as_inappropriate
where.not(flagged_inappropriate: true)
end

def without_any_reviews
left_joins(:reviews).where(reviews: {id: nil})
end

end

end

A note here... Someone will come along and say those should be scopes, not class methods. They would not necessarily be wrong. That is a matter of some opinion and you should do what makes you happy. If that sort of things floats your boat, then maybe something like:

class Bar < ApplicationRecord

scope :with_name, -> { where.not(name: nil) }
scope :not_flagged_as_inappropriate, -> { where.not(flagged_inappropriate: true) }
scope :without_any_reviews, -> { left_joins(:reviews).where(reviews: {id: nil}) }

end

Credit to max's answer for the left_joins(:reviews).where(reviews: {id: nil}) bit.

Also, this bit:

<div id="norev-container">
<% @bars.each do |bar| %>
<% if bar.name? && !bar.flagged_innapropriate && bar.reviews.length == 0 %>
<div class="bar-container">
<%= link_to image_tag(bar.picture.thumb.url), %`/bars/#{bar.id}/reviews/new`%>
</div>
<% end %>
<% end %>
</div>

...is really terrible:

  1. You shouldn't have that much logic in the view,
  2. You've got a N+1 problem
  3. You're handcrafting a link!

So, instead, try something like:

<div id="norev-container">
<% @bars_needing_review.each do |bar| %>
<div class="bar-container">
<%= link_to new_bar_review_path(bar) do %>
<%= image_tag(bar.picture.thumb.url) %>
<% end %>
</div>
<% end %>
</div>

Syntax may be a little off. Again, sorry for the rush. You'll still have an N+1 problem b/c of that bar.picture call. So, you may need to do something like:

@bars_needing_review = Bar.includes(:picture).with_name.not_flagged_as_inappropriate.without_any_reviews

Also, you'll need to set up your routes.rb to include something like:

resources :bars do 
resources :reviews, shallow: true
end

Activerecord Model.table_exists? does not give correct results

ActiveRecord::ModelSchema::ClassMethods#table_exists? is a wrapper around ActiveRecord::ConnectionAdapters::SchemaCache#data_source_exists?.

As the name implies, this is a cache, probably populated when the Rails app starts. If you modify the database schema the old schema will still be cached (arguably a bug or missing feature). You can reload User's schema cache with User.reload_schema_from_cache or possibly connection.schema_cache.clear_data_source_cache(Users.table_name.

How to return true if string exists in table, Ruby on Rails

You can check whether Robert exists or not by using .where().present

if @my_friends.where(:friend_id => 'Robert').present?
# Robert exists
else
# Robert doesn't exist
end

See this answer for more ways to check if a record exists.

Check row exist or not in Ruby on Rails

If you want to find if a user with the given name and password exists using Ruby on Rails, then you can do this:

User.where(user_name: params[:user_name], password: params[:password]).exists?

See the RailsGuides: Existence of Objects.

The Cause of the Original Problem?

So this it the code that the original poster originally submitted:

User.find_by("user_name = ? AND password = ?", "#{params[:user_name]}", "#{params[:password]}")

I removed the string interpolation because it was unnecessary

User.find_by("user_name = ? AND password = ?", params[:user_name], params[:password])

and apparently that fixed the problem. I'm not sure why it would make a difference though, the interpolated string should be the same value as the values in the params dictionary.

Rails Migrations: Check Existence and Keep Going?

As of Rails 3.0 and later, you can use column_exists? to check for the existance of a column.

unless column_exists? :statuses, :hold_reason
add_column :statuses, :hold_reason, :string
end

There's also a table_exists? function, which goes as far back as Rails 2.1.

Check if record exists from controller in Rails

Why your code does not work?

The where method returns an ActiveRecord::Relation object (acts like an array which contains the results of the where), it can be empty but it will never be nil.

Business.where(id: -1) 
#=> returns an empty ActiveRecord::Relation ( similar to an array )
Business.where(id: -1).nil? # ( similar to == nil? )
#=> returns false
Business.where(id: -1).empty? # test if the array is empty ( similar to .blank? )
#=> returns true


How to test if at least one record exists?

Option 1: Using .exists?

if Business.exists?(user_id: current_user.id)
# same as Business.where(user_id: current_user.id).exists?
# ...
else
# ...
end

Option 2: Using .present? (or .blank?, the opposite of .present?)

if Business.where(:user_id => current_user.id).present?
# less efficiant than using .exists? (see generated SQL for .exists? vs .present?)
else
# ...
end

Option 3: Variable assignment in the if statement

if business = Business.where(:user_id => current_user.id).first
business.do_some_stuff
else
# do something else
end

This option can be considered a code smell by some linters (Rubocop for example).

Option 3b: Variable assignment

business = Business.where(user_id: current_user.id).first
if business
# ...
else
# ...
end

You can also use .find_by_user_id(current_user.id) instead of .where(...).first


Best option:

  • If you don't use the Business object(s): Option 1
  • If you need to use the Business object(s): Option 3


Related Topics



Leave a reply



Submit