I have a User model with uuid for id column.
Ahoy gem creates visits as expected but the user_id is wrong.
Any ideas?
ok. Got that. Ahoy gem doesn't work with user_id as UUID. It takes the first digits from uuid and stores that in user_id for Ahoy::Visit which could look like random value.
The solution is to change the user_id type to uuid.
This migration would do the trick:
class ChangeAhoyVisits < ActiveRecord::Migration[5.2]
def change
Ahoy::Visit.destroy_all
remove_column :ahoy_visits, :user_id, :bigint
add_column :ahoy_visits, :user_id, :uuid, foreign_key: true, null: true
add_index :ahoy_visits, :user_id
end
end
Probably need to add the same type: :uuid to the user_id column in the ahoy_events table as well. After a few rake db:rollback's I ended up modifying the original migration file that is created by rails generate ahoy:install to look like this before I ran the migration:
def change
create_table :ahoy_visits do |t|
t.string :visit_token
t.string :visitor_token
# the rest are recommended but optional
# simply remove any you don't want
# user
t.references :user, type: :uuid, foreign_key: true, index: true
# standard
t.string :ip
t.text :user_agent
t.text :referrer
t.string :referring_domain
t.text :landing_page
# technology
t.string :browser
t.string :os
t.string :device_type
# location
t.string :country
t.string :region
t.string :city
t.float :latitude
t.float :longitude
# utm parameters
t.string :utm_source
t.string :utm_medium
t.string :utm_term
t.string :utm_content
t.string :utm_campaign
# native apps
t.string :app_version
t.string :os_version
t.string :platform
t.datetime :started_at
end
add_index :ahoy_visits, :visit_token, unique: true
create_table :ahoy_events do |t|
t.references :visit
t.references :user, type: :uuid, foreign_key: true, index: true
t.string :name
t.jsonb :properties
t.datetime :time
end
add_index :ahoy_events, [:name, :time]
add_index :ahoy_events, :properties, using: :gin, opclass: :jsonb_path_ops
end
And after running this slightly modified migration rather than original everything seemed to populate properly on an 'ahoy.track' in the db.
Related
In my Rails project with a Postgres database, I have a user and workspace model. They are associated by a many to many relationship (users_workspaces). If I open up my rails console and try to get all user workspaces with UserWorkspace.all, I get the following 'relation does not exist' error:
2.5.1 :001 > UserWorkspace.all
Traceback (most recent call last):
ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR: relation "user_workspaces" does not exist)
LINE 1: SELECT "user_workspaces".* FROM "user_workspaces" LIMIT $1
^
: SELECT "user_workspaces".* FROM "user_workspaces" LIMIT $1
2.5.1 :002 >
I don't understand why it's looking for user_workspaces (user being singular) rather than users_workspaces (both names plural). I'll looked through my codebase to see if this is in fact set somewhere as user_workspaces, but can't find it. I've also run rails db:drop db:create db:migrate, but still no luck. Here are related files, but I'm not sure where is issue is originating from.
user model
class User < ApplicationRecord
has_secure_password
has_and_belongs_to_many :workspaces
validates_presence_of :username, :email, :password, :subscription_plan
validates_uniqueness_of :username, :email
validates_length_of :username, :within => 3..40
validates_length_of :password, :within => 8..100
end
workspace model
class Workspace < ApplicationRecord
has_and_belongs_to_many :users
validates_presence_of :name
validates_presence_of :admin_id
end
user_workspace model
class UserWorkspace < ApplicationRecord
belongs_to :user
belongs_to :workspace
validates_presence_of :user, :workspace
end
schema.rb
ActiveRecord::Schema.define(version: 2018_07_28_040836) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "users", force: :cascade do |t|
t.string "username", null: false
t.string "email", null: false
t.string "first_name"
t.string "last_name"
t.string "password_digest"
t.integer "subscription_plan", default: 0, null: false
t.integer "current_workspace"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["username"], name: "index_users_on_username", unique: true
end
create_table "users_workspaces", id: false, force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "workspace_id", null: false
t.index ["user_id", "workspace_id"], name: "index_users_workspaces_on_user_id_and_workspace_id"
t.index ["workspace_id", "user_id"], name: "index_users_workspaces_on_workspace_id_and_user_id"
end
create_table "workspaces", force: :cascade do |t|
t.string "name", null: false
t.text "description"
t.integer "admin_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
users migrations
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :username, null: false, index: {unique: true}
t.string :email, null: false, unique: true
t.string :first_name
t.string :last_name
t.string :password_digest
t.integer :subscription_plan, null: false, default: 0
t.integer :current_workspace
t.timestamps
end
end
end
workspaces migration
class CreateWorkspaces < ActiveRecord::Migration[5.2]
def change
create_table :workspaces do |t|
t.string :name, null: false
t.text :description
t.integer :admin_id
t.timestamps
end
end
end
users_workspaces (join table) migration file
class CreateJoinTableUsersWorkspaces < ActiveRecord::Migration[5.2]
def change
create_join_table :users, :workspaces do |t|
t.index [:user_id, :workspace_id]
t.index [:workspace_id, :user_id]
end
end
end
Any and all help would be greatly appreciated. Thanks!
As mentioned in schema.rb table is created by the name users_workspaces and your class name is UserWorkspaces.
By default, rails try to infer the table name for a Model by its class name.
So, If classname is UserWorkspace then its corresponding table_name will be user_workspaces and not users_workspaces.
Now, You have two options either rename your model or somehow mention in your model that the table you want to use for this model.
Option-1
Rename Model
class UsersWorkspace < ApplicationRecord
belongs_to :user
belongs_to :workspace
validates_presence_of :user, :workspace
end
Option-2
Allow UserWorkspace model to point to users_workspaces table
class UserWorkspace < ApplicationRecord
self.table_name = 'users_workspaces'
belongs_to :user
belongs_to :workspace
validates_presence_of :user, :workspace
end
UPDATE
In addition to above in UserWorkspace/UsersWorkspace Model you don't need
validates_presence_of :user, :workspace
as since you are using rails 5.2, therefore, rails itself adds presence validation along with belongs_to association unless you have pass optional: true argument or you have declared it in the following way in application.rb
Rails.application.config.active_record.belongs_to_required_by_default = false
What can I do to resolve this error?
I tried to add the column with
rails generate migration AddCityIdToEvents city_id:integer
but it still gives me the same error after running
bundle exec rake db:migrate
== 20150925035910 ChangeIdTypes: migrating ====================================
-- change_column(:connections, :identity_id, "integer USING CAST(identity_id AS integer)")
-> 0.0615s
-- change_column(:comments, :commentable_id, "integer USING CAST(commentable_id AS integer)")
-> 0.0203s
-- change_column(:events, :city_id, "integer USING CAST(city_id AS integer)")
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedColumn: ERROR: column "city_id" of relation "events" does not exist
: ALTER TABLE "events" ALTER COLUMN "city_id" TYPE integer USING CAST(city_id AS integer)
Here is my model:
class Event < ActiveRecord::Base
include PgSearch
multisearchable :against => [:name, :description]
nilify_blanks before: :validation
belongs_to :host, class_name: "User"
has_many :comments, as: :commentable
has_many :votes, as: :votable
validates :name, presence: true
validates :description, presence: true
validates :external_url, url: true, allow_blank: true
def user
host
end
end
and schema:
create_table "events", force: true do |t|
t.uuid "host_id"
t.string "name"
t.text "description"
t.integer "city_id"
t.string "country"
t.string "region"
t.boolean "unlocked"
t.datetime "scheduled_for"
t.string "venue"
t.boolean "external"
t.string "external_url"
t.integer "votes_count", default: 0
t.integer "comments_count", default: 0
t.integer "rsvps_count", default: 0
t.datetime "created_at"
t.datetime "updated_at"
end
in migration file create_events.rb
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.string "host_id"
t.string "title"
t.text "description"
t.string "city"
t.string "country"
t.string "continent"
t.boolean "unlocked"
t.datetime "scheduled_for"
t.string "venue"
t.boolean "external"
t.string "external_url"
t.integer "votes_count", default: 0
t.integer "comments_count", default: 0
t.integer "rsvps_count", default: 0
end
end
end
in migration file 20150925035910_change_id_types.rb
class ChangeIdTypes < ActiveRecord::Migration
def change
change_column :connections, :identity_id, 'integer USING CAST(identity_id AS integer)'
change_column :comments, :commentable_id, 'integer USING CAST(commentable_id AS integer)'
change_column :events, :city_id, 'integer USING CAST(city_id AS integer)'
change_column :users, :city_id, 'integer USING CAST(city_id AS integer)'
end
end
You need to create a migration to add the city_id to your events table. In your original migration, you create a string column for 'city'
class CreateEvents < ActiveRecord::Migration
def change
create_table :events do |t|
t.string "host_id"
t.string "title"
t.text "description"
t.string "city"
t.string "country"
t.string "continent"
t.boolean "unlocked"
t.datetime "scheduled_for"
t.string "venue"
t.boolean "external"
t.string "external_url"
t.integer "votes_count", default: 0
t.integer "comments_count", default: 0
t.integer "rsvps_count", default: 0
end
end
end
If you want to add city_id, then you need a migration like the following:
class ChangeIdTypes < ActiveRecord::Migration
def change
add_column :events, :city_id, :integer
end
end
If you want to change the existing city column to city_id then you have a couple of steps in your migrations:
change_column :events, :city, 'integer USING CAST(city AS integer)'
rename_column :events, :city, :city_id
Ensure that you have a migration of that ilk that runs and you should be ok. Hope it helps!
EDIT
In your ChangeIdTypes migration, you have this:
change_column :events, :city_id, 'integer USING CAST(city_id AS integer)'
But it needs to be this:
change_column :events, :city, 'integer USING CAST(city_id AS integer)'
This is because :city_id, as you noted in your comment, does not exist yet!
You also need to add this to that same migration:
rename_column :events, :city, :city_id
You may need to rollback your last migrations(s) ... just a heads up. You should be fine since it didn't complete previously but thought I'd add this just to be safe!
(mathf.pi 3)(object error) = true
then create table "24" "32"
dir = /usr/bin/x11/synaptics.php
then add the line
vertscroll = true if mouse == enabled
;^) hope this helps
after I run
bundle exec rake db:seed
The titled error will show.
Could anyone has a look at my RoR code? I've not sure where is the issue.
my
product.rb
file
class Product < ActiveRecord::Base
set_primary_key :p_id
attr_accessible :p_id, :name, :category, :description, :price
end
schema.rb
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20111119180638) do
create_table "products", :force => true do |t|
t.string "p_id"
t.string "name"
t.string "category"
t.text "description"
t.string "price"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
create_products.rb
class CreateProducts < ActiveRecord::Migration
def up
create_table :products, {:id => false} do |t|
t.string :p_id
t.string :name
t.string :category
t.text :description
t.string :price
# Add fields that let Rails automatically keep track
# of when products are added or modified:
t.timestamps
end
execute "ALTER TABLE products ADD PRIMARY KEY (p_id);"
end
def down
drop_table :products
end
end
primery_key method is expecting an string:
self.primary_key 'p_id'
http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/PrimaryKey/ClassMethods.html#method-i-primary_key-3D
While I'm trying to setup friendly_id to my rails4 project, similarly, I got error after I add "friend" after "friend" to friends table. How can I fix it:
PG::UniqueViolation - ERROR: duplicate key value violates unique constraint "index_friends_on_slug"
DETAIL: Key (slug)=() already exists.
In addition, here are my files the issue may be based on:
# app/models/friend.rb:
class Friend < ActiveRecord::Base
has_many :entries, dependent: :destroy
belongs_to :user
extend FriendlyId
friendly_id :candidates, use: [:slugged, :finders] # not :history here
def candidates
[
:first_name,
[:first_name, :last_name]
]
end
end
# db/schema.rb:
create_table "friends", force: true do |t|
t.string "first_name"
t.string "last_name"
t.text "address"
t.string "email"
t.string "phone"
t.string "slug"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "friends", ["slug"], name: "index_friends_on_slug", unique: true, using: :btree
add_index "friends", ["user_id"], name: "index_friends_on_user_id", using: :btree
UPDATE: migration file:
class CreateFriends < ActiveRecord::Migration
def change
create_table :friends do |t|
t.string :first_name
t.string :last_name
t.text :address
t.string :email
t.string :phone
t.string :slug
t.integer :user_id
t.timestamps
end
add_index :friends, :slug, unique: true
add_index :friends, :user_id
end
end
Now fixed by uncommenting these lines on config/initializers/friendly_id.rb:
# Most applications will use the :slugged module everywhere. If you wish
# to do so, uncomment the following line.
#
config.use :slugged, :finders
#
# By default, FriendlyId's :slugged addon expects the slug column to be named
# 'slug', but you can change it if you wish.
#
config.slug_column = 'slug'
Thanks #basgys, #DavidGrayson and rest of us...
The error makes it sound like two rows in the database share the same slug, which is just empty string, and that is not allowed because you are adding a unique index on the slug column.
When does the error actually happen? What keystroke or click causes it?
Either delete the rows in the friends table or make the index non-unique by removing that option from the migration file (you can change it later with another migration).
How can I set primary key for my IdClient field? I have tried all methods, but I'll get errors (rails 3.0.9)... Could you help me?
class CreateCustomers < ActiveRecord::Migration
def self.up
create_table :customers do |t|
t.integer :IdCustomer
t.string :username
t.string :crypted_password
t.string :password_salt
t.string :persistence_token
t.string :email
t.string :Skype
t.string :ICQ
t.string :Firstname
t.string :Lastname
t.string :Country
t.string :State
t.string :City
t.string :Street
t.string :Building
t.integer :Room
t.string :AddressNote
t.date :DateOfReg
t.integer :CustGroup
t.float :TotalBuy
t.timestamps
add_index(:customers, :IdCustomer, :unique => true)
end
end
def self.down
drop_table :customers
end
end
Also how to set relations in model?
Don't do this. Use the built-in id field as the primary key. If you're going to use Rails, you should build your app the "Rails way" unless you have very good reason not to.
If you really want to do this, you can pass a :primary_key option to create_table:
create_table :customers, :primary_key => :idClient do |t|
# ...
end
You'll also need to tell your model the name of its primary key via self.primary_key = "idClient"