I'm using the pg_search gem for Rails (Ruby 2.1.1, Rails 4.1.4) and trying to implement a global multisearch for some of my models but I keep getting
PG::UndefinedFunction: ERROR: operator does not exist: text % unknown
when I run the multisearch command.
Here are my models:
# name :text
class Animal < ActiveRecord::Base
has_one :expression
multisearchable against: :name
end
# type :text
class Expression < ActiveRecord::Base
belongs_to :animal
multisearchable against: :type
end
My search query is then something like Happy Tiger
When I run PgSearch.multisearch("Happy Tiger") though, I get that above error.
I also have an initializer that tells PgSearch to use trigram
Any ideas???
I realized I needed to install trigram in postgres :P
Related
My application has two models: Service and User. A service may have and assigned driver or not. I have implemented this as:
class User < ApplicationRecord
end
and:
class Service < ApplicationRecord
has_and_belongs_to_many :users
belongs_to :driver, class_name: "User", optional: true
end
Note that since a particular service may or may not have a driver, I have marked the association as optional. And I don't have any pointer from the User model to Service.
I have the following migration implementing this association:
class AddOPtionalDriverToService < ActiveRecord::Migration[5.0]
def change
add_reference :services, :driver, references: :users, index: true
add_foreign_key :services, :users, column: :driver_id
end
end
The relevant part of my schema when I run the migration is:
create_table "services", force: :cascade do |t|
t.string "destination"
....
t.text "comments"
t.index ["driver_id"], name: "index_tdy_requests_on_driver_id", using: :btree
end
...
add_foreign_key "tdy_requests", "users", column: "driver_id"
end
My problem is that when I try to create a new service without a driver my params contains a value of "0" for the driver:
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"kVC53huZYZxuF4akSiqkGkSvoo5p2f4dQ==",
"service"=>{
"destination"=>"Some where", ... ,
"driver_id"=>"0",
"comments"=>""},
"commit"=>"Create Service"}
But since driver_id is "0" I get the following exception:
PG::ForeignKeyViolation: ERROR: insert or update on
table "services" violates foreign key constraint
"fk_rails_15497e1c36" DETAIL: Key (driver_id)=(0) is
not present in table "users"
This makes lots of sense but the funny thing is that I have discovered this when I move from SQLite to PostgreSQL because it was working fine with SQLite. At least the application was doing what I wanted to do. I'm using Rail 5.0.2.
I would like to know how can modify my models or migrations to avoid this exception. Any ideas?
Thank you very much in advance.
I'm sorry. I have just realized the solution. Something that I didn't say was that I enter the driver using a select element. Since the driver is optional I was adding and "empty" using:
<option value="0"></option>
changing to:
<option value=""></option>
solves the problem.
I'd prefer to remove the question since doesn't offer any value.
In my application I have models Visit & Post.
class Post < ActiveRecord::Base
has_many :visits
class Visit < ActiveRecord::Base
belongs_to :post, :counter_cache => true
Im trying to get all visits a post has in visits table. I did:
- a = Visit.joins(:post).group(:post_id).select(:post_id, :title, 'count(visits.id) as total_views').where(user: current_user)
- a.each do |a|
%tr
%td= a.title
%td= a.total_views
This works find in my development env/localhost (I think since I use sqlite3), butI am using PostgreSql in my production and I got this error:
PG::GroupingError: ERROR: column "posts.title" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ...ECT count(visits.id) as total_views, "visits"."post_id", "title", c...
What am I doing wrong and how to fix it?
As the answer says "posts.title" must appear in the GROUP BY. In group add :title along with :post_id
Visit.joins(:post).group([:post_id, :title]).select('sum(cpc_bid) as earnings', :post_id, :title, 'count(visits.id) as total_views').where(influencer: current_user)
I am learning Phoenix using the book 'Programming Phoenix'. The first project has creating a postgres db and this is our migration. I cannot get rid of a warning for timestamps in my schema.
defmodule Rumbl.Repo.Migrations.CreateUser do
use Ecto.Migration
def change do
create table(:users) do
add :name, :string
add :username, :string, null: false
add :password_hash, :string
timestamps
end
create unique_index(:users, [:username])
end
end
Then our model corresponding to this migration is:
defmodule Rumbl.User do
use Rumbl.Web, :model
schema "users" do
field :name, :string
field :username, :string
field :password, :string, virtual: true
field :password_hash, :string
timestamps
end
end
Now I run the migration, followed by mix phoenix.server.
And I get this warning:
warning: variable "timestamps" does not exist and is being expanded to "timestamps()",
please use parentheses to remove the ambiguity or change the variable name
web/models/user.ex:10
If I change timestamps in the schema to timestamps() it doesn't complain, anymore, but the book never shows what the model's schema looks like after running the migration. Is that supposed to be right, or is there something else that fixes that? What is the 'timestamps' representation in an Ecto/Phoenix schema supposed to look like?
Elixir 1.4 added a warning on calling an imported or locally defined function with 0 arguments without a parentheses, as it is ambiguous on what it should mean when you have a local variable with the same name as the function and you write the variable name without parentheses.
[Kernel] Warn if variable is used as a function call
Source
The book probably hasn't been updated for Elixir 1.4 yet. Phoenix generators were updated to add the parentheses in June 2016.
In a model definition can you have more than one belongs_to statement? If the answer is no, read no further. I am trying to create three 1-n referenced relationships with mongoid in a sinatra app.
models
class SkillTrack
include Mongoid::Document
belongs_to :student
belongs_to :grading_period
belongs_to :teacher
end
class Student
include Mongoid::Document
field :name
field :nickname
field :dob, type: Date
has_many :skill_tracks
end
class GradingPeriod
include Mongoid::Document
field :school_year
field :period_name
field :signing_date, type: Date
has_many :skill_tracks
end
class Teacher
include Mongoid::Document
field :name
has_many :skill_tracks
end
routes
post "/skill_track/new" do
form = params[:formdata] # using sinatra form helpers gem
student = Student.find("#{formdata["student_mongo_id"]}")
working = (student.skill_tracks.create).id
??? what do I do with working to make it a child of a teacher and of a grading_period?
end
what I have tried
The thing that looked the most promising to me from the mongoid docs was:
band.member_ids = [ id ] #Set the related document ids.
I mucked about in irb and tried lots of variations in my models but I could not set a parent teacher or grading period for the newly created skilltracking object. The student foreign key was set properly on creation.
I am hoping I have a simple syntax ignorance, but I tried so many variations I wonder if I can do this at all.
UPDATE:
I just needed to add working.save to David Troyer answer and boom working.
post "/skill_track/new" do
form = params[:formdata]
student = Student.find("#{formdata["student_mongo_id"]}")
working = student.skill_tracks.create
working.teacher = Teacher.create # or find
working.grading_period = GradingPeriod.create # or find
working.save
end
I believe so. If I understand your question correctly, try using some setters on the child SkillTrack document.
post "/skill_track/new" do
form = params[:formdata]
student = Student.find("#{formdata["student_mongo_id"]}")
working = student.skill_tracks.create
working.teacher = Teacher.create # or find
working.grading_period = GradingPeriod.create # or find
end
Dig a little bit further into the Operations section of the mongoid docs you referenced
I'm using Mongoid on Sinatra . And I use
Dir.glob(File.join(File.dirname(__FILE__),'models','*.rb')).each do |file|
require file
end
to load mongoid model files.
I tried to add a model B inherit from A ,like:
models/a.rb:
class A
include Mongoid::Document
include Mongoid::Timestamps
field :custom_id, type: Integer
end
models/b.rb
class B < A
field :title , type: String
field :body , type: String
end
But when I exec the App , I got errors :
uninitialized constant A (NameError)
So I'm trying to find a solution for this,
it could be fixed by add:
require A
at the top of model B , But I think it may not be a good way to solve it.
So , is there anyother way to fix this??
Regards
You just require your file where you A class is define.
Sinatra has no auto_load system like rails have. So you need doing all of your require needed.
require 'a'
class B < A
field :title , type: String
field :body , type: String
end