I have a has_many :through association.
#app/user.rb
class User < ApplicationRecord
has_many :members
has_many :projects, :through => :members
end
#app/project.rb
class Project < ApplicationRecord
has_many :members
has_many :users, :through => :members
end
#app/member.rb
class Member < ApplicationRecord
belongs_to :user
belongs_to :project
end
I have the database schema as follows:
create_table "members", force: :cascade do |t|
t.integer "user_id"
t.integer "project_id"
t.integer "is_owner"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["project_id"], name: "index_members_on_project_id"
t.index ["user_id"], name: "index_members_on_user_id"
end
create_table "projects", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "password_digest"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
I can get Member ID, User_ID, Project_ID, and is_owner when I use the command #project.members
I can get user_id, first_name, last_name, email, and password when I use the command #project.users
What command should I use to get member_id, first_name, last_name?
I can get what I want using the SQL query SELECT * FROM members INNER JOIN users ON users.id = members.user_id but I don't want to use raw SQL.
Can someone tell me how to convert that query into a Ruby on rails command?
You can get your desired result using following code
Member.joins(:user)
It will generate the same query what you are specifying in your question i.e.
SELECT * FROM members INNER JOIN users ON users.id = members.user_id
Related
I'm building three models in my rails application. One model references the same model twice as shown in my DB Schema. The only problem is that when I make a POST Request to create a new record in my shipment table. I get this error:
#<ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: users.sender_id: SELECT \"users\".* FROM \"users\" WHERE \"users\".\"sender_id\" = ? LIMIT ?>
I don't think that I need to add a sender_id & receiver_id column in my users table because the sender_id & receiver_id are basically the User_ID in the users column. Any help would be much appreciated it!
This is my user.rb file:
class User < ApplicationRecord
has_many :shipments
end
This is my shipment.rb
class Shipment < ApplicationRecord
belongs_to :sender, class_name: "User", primary_key: "sender_id"
belongs_to :receiver, class_name: "User", primary_key: "receiver_id"
validates_uniqueness_of :tntcode
end
This is my shipments_controller:
class ShipmentsController < ApplicationController
def index
shipments = Shipment.all
end
def show
shipment = Shipment.find(params[:id])
end
def create
shipment = Shipment.new(shipment_params)
if shipment.save
render json: {status: 'Shipment created successfully'}, status: :created
else
render json: { errors: shipment.errors.full_messages }, status: :bad_request
end
end
def shipment_params
params.require(:shipment).permit(:tntcode, :status, :shipment_type, :weight, :content, :price, :sender_id, :receiver_id)
end
end
And my schema.rb:
ActiveRecord::Schema.define(version: 20180826123320) do
create_table "shipments", force: :cascade do |t|
t.integer "tntcode"
t.string "status"
t.string "shipment_type"
t.integer "weight"
t.string "content"
t.integer "price"
t.integer "sender_id"
t.integer "receiver_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["receiver_id"], name: "index_shipments_on_receiver_id"
t.index ["sender_id"], name: "index_shipments_on_sender_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email", null: false
t.string "role"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "photourl"
t.string "userid"
end
end
You don't want to change the primary_key on your belongs_to associations: that's the other table's ID column (id).
You instead want:
belongs_to :sender, class_name: "User", foreign_key: "sender_id"
belongs_to :receiver, class_name: "User", foreign_key: "receiver_id"
... which is the default, so this should work too:
belongs_to :sender, class_name: "User"
belongs_to :receiver, class_name: "User"
I have three models in context of this question:
class ClearanceBatch < ActiveRecord::Base
has_many :items
belongs_to :user
end
class Item < ActiveRecord::Base
belongs_to :style
belongs_to :user
belongs_to :clearance_batch
validates :id, :uniqueness => true
end
class User < ActiveRecord::Base
has_many :items, dependent: :destroy
has_many :clearance_batches, dependent: :destroy
enum role: {staff: 0, vendor: 1, admin: 2}
end
Schema:
create_table "clearance_batches", force: :cascade do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "status", default: false
t.string "boughtby", default: ""
t.integer "user_id"
end
add_index "clearance_batches", ["user_id"], name: "index_clearance_batches_on_user_id"
create_table "items", force: :cascade do |t|
t.string "size"
t.string "color"
t.string "status"
t.decimal "price_sold"
t.datetime "sold_at"
t.integer "style_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "clearance_batch_id"
t.integer "user_id"
end
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.integer "role", default: 0
end
I want to find all items in a batch of the currently logged in user(mainly vendor) with the status "clearanced", and get their details in a loop from controller to my view
Can anyone please help me out with the active record query? Please! :)
The SQLite Query I think would be:
Select I.id from clearance_batches C INNER JOINS Items I on C.id = I.clearance_batch_id where C.user_id = "1" and I.status = "clearanced"
(If 1 is the current user, keeping in mind I am only allowing user of role vendors to be a user in clearance_batch table)
(1) Query:
Items.where(status: "clearanced")
.joins(:clearance_batches)
.where(clearance_batches: {user_id: current_user})
(2) Controller:
#clearanced_items = query(1)
(3) View:
<% #clearanced_items.each do |c_item| %>
...
<% end %>
im trying to make a search form in a table that contains two ids as values, one of them is the id of an user and the other is the id of a project.
Here is my database schema:
create_table "users", force: :cascade do |t|
t.string "name"
t.string "email"
t.text "bio"
t.float "lastLatitude"
t.float "lastLongitude"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "swipes"
t.string "profile_image"
end
create_table "projects", force: :cascade do |t|
t.string "name"
t.text "bio"
t.integer "user_id"
t.string "salary"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "likes"
t.string "image"
t.float "latitude"
t.float "longitude"
end
create_table "matches", force: :cascade do |t|
t.integer "user_id"
t.integer "project_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
What i want to do is to create a search form in the matches index view to filter the matches by the user name or the project name, but i don't know how to do it, this is what i have right now:
def self.search(search)
if search
where('User(user_id).name LIKE :search OR Project.name LIKE :search', search: "%#{search}%")
else
where(nil)
end
end
Is it possible to do that?
Any help is welcome
I suggest a scope approach
class Match < ActiveRecord::Base
belongs_to :project
belongs_to :user
scope name, ->(n) {
joins(:user, :project).where("users.name like ? or projects.name like ? ", "%#{n}%", "%#{n}%")
}
end
class User < ActiveRecord::Base
has_many :projects
scope :name, ->(n) {
where("users.name like ?", "%n%")
}
end
class Project < ActiveRecord::Base
scope :name, ->(n) {
where("projects.name like ?", "%n%")
}
end
I have a question associated with moving data from one table to another. I am using Postgres as a database.
I have two models:
class User < ActiveRecord::Base
has_many :emails
end
class Email < ActiveRecord::Base
belongs_to :user
end
schema looks like this:
create_table "users", force: :cascade do |t|
t.string "first_name", limit: 255
t.string "last_name", limit: 255
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "emails", force: :cascade do |t|
t.string "email", null: false
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Now I want to move the latest email for the user and save it in users table email column. I can easily do it using Rails models in migration but then when I rename model or remove it. Migration will fail. Is there any easy way to do it with raw sql?
You can use window functions. The example below is a starting point.
UPDATE users u
SET u.email = (SELECT
MAX(FIRST_VALUE(email)) OVER (PARTITION BY user_id ORDER BY created_at DESC)
FROM emails e
WHERE e.user_id = u.id);
You can still use ActiveRecord with fake classes just for the purpose of migration. Something like:
class YourMigration < ActiveRecord::Migration
class FakeUser < ActiveRecord::Base
self.table_name = 'users'
has_many :fake_emails, foreign_key: 'user_id'
end
class FakeEmail < ActiveRecord::Base
self.table_name = 'emails'
belongs_to :fake_user, foreign_key: 'user_id'
end
def change
FakeUser.all.each do |user|
[...]
end
end
end
I just want to make a little join table, eventually storing extra info on that join (which is why I'm not using HABTM). From the rails documentation of associations I've created the following models:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, :through => :appointments
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, :through => :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physicians
belongs_to :patients
end
my schema looks like this:
ActiveRecord::Schema.define(:version => 20130115211859) do
create_table "appointments", :force => true do |t|
t.datetime "date"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "patient_id"
t.integer "physician_id"
end
create_table "patients", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "physicians", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
When I'm in the console and I create a physician and patient instance:
#patient = Patient.create!
#physician = Physician.create!
And try to associate one to the other
#physician.patients << #patient
I get
NameError: uninitialized constant Physician::Patients
Questions about this example have been asked before but none have address my scenario. Any ideas?
Thanks,
Neil, rails newbie.
The belongs_to calls in your Appointment model should take a singular form, not a plural form:
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end