Mysql join in rails - mysql

I have two tables orientations and registrations that I would like to perform a join query on. Here is the schema for each of the tables...
create_table "orientations", :force => true do |t|
t.date "class_date"
t.text "class_time"
t.integer "seats"
t.boolean "active", :default => true
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "registrations", :force => true do |t|
t.integer "orientation_id"
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "student_id"
t.string "phone"
t.string "registration_cancellation_token"
t.datetime "registration_cancelled_at"
t.boolean "checked_in", :default => false
t.boolean "cancelled", :default => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.text "program"
end
What I am looking for is all registrations for all orientations between two dates. I came up with this...
Registration.where(Orientation.where created_at: => #start_date..#end_date)
Of course that syntax is bogus, but hopfully it will help get across what I am looking for.

Use this to get all registrations for all orientations between two dates:
Registration.joins(:orientation).where(orientations: {:class_date => #start_date..#end_date})
joins performs an INNER JOIN which filters the rows that don't have association.
But, if you wish to keep the rows that don't have associations then go for includes which performs a LEFT OUTER JOIN
Registration.includes(:orientation).where(orientations: {:class_date => #start_date..#end_date})

Related

In Ruby On Rails indexing required?

Table->
create_table "subscription_plans", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
t.string "name"
t.integer "business_id"
t.datetime "published_at"
t.datetime "signup_end_date"
t.datetime "start_time"
t.datetime "end_time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "deactivated_at"
t.index ["business_id", "end_time", "deactivated_at"], name: "index_plan_on_bid_published_deactivated"
t.index ["business_id", "published_at"], name: "index_subscription_plans_on_business_id_and_published_at"
t.index ["business_id", "signup_end_date", "end_time"], name: "index_plans_on_signup_end_date_and_end_time'"
end
When ever I hit query
SELECT `subscription_plans`.* FROM `subscription_plans` WHERE `subscription_plans`.`business_id` = 27 AND `subscription_plans`.`deactivated_at` IS NULL AND `subscription_plans`.`published_at` IS NOT NULL AND ((end_time > '2021-06-30 08:16:21.824452' OR end_time IS NULL))
It always uses index index_subscription_plans_on_business_id_and_published_at. Is there any combination where I can use index_plan_on_bid_published_deactivated?
Or there is not any combination of index with deactivated_at?

Sharing Address to two entities - Polymorphic association or two addresses tables?

I'm pretty new at Ruby on Rails and i'm not sure what is the best approach to modelling the application.
My app has an User model and a Restaurant model. Both of them has only one address.
Restaurants table
create_table "restaurants", force: :cascade do |t|
t.string "name"
t.text "description"
t.string "email"
t.string "phone"
t.integer "category_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
User table
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "surname"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The restaurants addresses must have two columns more than the users addresses ( lat and long)
FIRST APPROACH - Create two tables, one to the restaurant addresses and another to the user addressses.
User addresses table
create_table "user_addresses", force: :cascade do |t|
t.string "street"
t.string "city"
t.string "zip_code"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_addresses_on_user_id"
end
restaurant addresses table
create_table "restaurant_addresses", force: :cascade do |t|
t.string "street"
t.string "city"
t.string "zip_code"
t.decimal "longitude"
t.decimal "latitude"
t.integer "restaurant_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["restaurant_id"], name: "index_addresses_on_restaurant_id"
end
SECOND APPROACH -
Create a Polymorphic association for the User model and Restaurant model.
Create a separated table with the coordinates (associated just with the restaurant Model).
Polymorphic Association
class User
has_one :address, as: :addressable
end
class Restaurant
has_one :address, as: :addressable
has_one:coordinate
end
class Address
belongs_to :addressable, polymorphic: true
end
Any one of this approachs are good enough or is it a better way to do that?

Rails Associations Not working, user_id not showing in console

In console I get this error:
peegin.user
NameError: undefined local variable or method `peegin' for main:Object
Did you mean? #peegin
Also when i try to access Peegin in console it doesn't display user_id:
Peegin
=> Peegin(id: integer, title: string, meaning: string, example: string, created_at: datetime, updated_at: datetime, permalink: string)
2.3.0 :039 >
User Class
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :peegins
end
Peegin Class
class Peegin < ActiveRecord::Base
belongs_to :user
before_create :generate_permalink
def to_param
permalink
end
private
def generate_permalink
pattern=self.title.parameterize
duplicates = Peegin.where(permalink: pattern)
if duplicates.present?
self.permalink = "#{pattern}-#{duplicates.count+1}"
else
self.permalink = self.title.parameterize
end
end
end
Schema
ActiveRecord::Schema.define(version: 20160804115242) do
create_table "peegins", force: :cascade do |t|
t.string "title"
t.string "meaning"
t.string "example"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "permalink"
t.integer "user_id"
end
add_index "peegins", ["user_id"], name: "index_peegins_on_user_id", unique: true
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
Make sure your database is up to date.
$ bin/rake db:migrate
Then.. you have to create a Peegin object and then you can access the user:
peegin = Peegin.create(title: "something")
peegin.user # => nil
peegin.user = User.first # Or take any user you want.
peegin.save # => user_id is updated in the database
In your rails console please try this:
#peegin = Peegin.find(1) //IF one doesn't work make sure if database has a record with this id and try with id that exists.
then use
#peegin.user
Instead of
peegin.user

Using named scopes in Ruby on Rails 4 on associated models

My app consists of 3 models:
FashionModel
Measurement
ModelProfile
class FashionModel < ActiveRecord::Base
has_secure_password
has_one :model_profile
has_one :measurement
accepts_nested_attributes_for :model_profile
accepts_nested_attributes_for :measurement
end
class ModelProfile < ActiveRecord::Base
belongs_to :fashion_model
end
class Measurement < ActiveRecord::Base
belongs_to :fashion_model
end
The schema is roughly as follows:
create_table "fashion_models", force: :cascade do |t|
t.string "first_name", limit: 25
t.string "last_name", limit: 25
t.string "email", limit: 255, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest", limit: 255
t.string "password_reset_token", limit: 255
t.datetime "password_reset_sent_at"
end
create_table "measurements", force: :cascade do |t|
t.integer "fashion_model_id", limit: 4
t.decimal "feet", precision: 10
t.decimal "inches", precision: 10
t.decimal "bust", precision: 10, default: 36
t.decimal "waist", precision: 10, default: 28
t.decimal "hips", precision: 10, default: 36
t.decimal "shoes", precision: 10
t.integer "dress", limit: 4
t.string "eyes", limit: 255
t.string "hair", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "model_profiles", force: :cascade do |t|
t.integer "fashion_model_id", limit: 4
t.string "phone_number", limit: 255
t.date "birthdate"
t.text "bio", limit: 65535
t.string "location", limit: 255, default: "Venice"
t.string "gender", limit: 255
t.decimal "rate", precision: 10, default: 100
t.string "profile_picture", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "model_profiles", ["fashion_model_id"], name: "index_model_profiles_on_fashion_model_id", using: :btree
add_foreign_key "bookings", "fashion_models"
add_foreign_key "fashion_model_photos", "fashion_models"
end
I am trying to filter out data based on the input. For example someone searches for a model with height 5'8", with black eyes, and brown hair, I should display only those models by querying the database.
Therefore, I am trying to use named scopes in the model. I am not sure how do I scope the attributes of the measurement table by writing a scope in the FashionModel model.
I read a few resources online and from what I understood, I wrote something like
scope :eye_color, includes(:measurement).where(measurement: { eyes: "Amber" })
Though I don't want to hardcode Amber into the eyes field, I get an error in my console when trying to access this scope. I do something like
a = FashionModel.all
a.eye_color
This gives me an and ArgumentError: wrong number of arguments (given 0, expected 1).
I also tried doing this
scope :eye_color, -> (eye_color) { where eyes: eye_color }
and then calling it by a.eye_color("Amber"), which in turn gave me a NoMethodError: undefined method 'measurement' for Class.
So basically I want to scope into the child models from the parent model.
Any help is much appreciated! Thanks
Define your scope as:
scope :eye_color, ->(eye_color) {
includes(:measurements).where(measurements: {eyes: eye_color})
}
And then query with a param like:
FashionModel.eye_color("Amber")

Rails date properties won't save to MySQL database

I have a rails application which is running MySQL in production and SQLite in development. In development mode everything is working fine, but in production datetime properties just won't get saved to the database (even the created_at and updated_at won't). The field is not null, but 0000-00-00 00:00:00. How is this possible? I did some research but I can't fix it.
schema.rb:
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130306100623) do
create_table "announcements", :force => true do |t|
t.string "title"
t.text "text"
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "delayed_jobs", :force => true do |t|
t.integer "priority", :default => 0
t.integer "attempts", :default => 0
t.text "handler"
t.text "last_error"
t.datetime "run_at"
t.datetime "locked_at"
t.datetime "failed_at"
t.string "locked_by"
t.string "queue"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority"
create_table "document_categories", :force => true do |t|
t.string "title"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "documents", :force => true do |t|
t.string "file_file_name"
t.string "file_content_type"
t.integer "file_file_size"
t.datetime "file_updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
t.string "title"
t.text "description"
t.string "ancestry"
t.boolean "folder"
end
add_index "documents", ["ancestry"], :name => "index_documents_on_ancestry"
create_table "inventory_items", :force => true do |t|
t.string "object"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "reservation_items", :force => true do |t|
t.integer "reservation_id"
t.integer "inventory_item_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "reservations", :force => true do |t|
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "start_time"
t.datetime "end_time"
end
create_table "users", :force => true do |t|
t.string "first_name"
t.string "insertion"
t.string "last_name"
t.string "telephone_prefix"
t.string "telephone_suffix"
t.string "address"
t.string "number"
t.string "postal_code"
t.string "city"
t.date "birthdate"
t.string "email", :default => "", :null => false
t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "telephone_mobile"
t.integer "admin"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
t.string "sex"
t.string "lovo_email"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
end
Thank a lot!