Thinking Sphinx "no field found in schema" error - mysql

I am pretty new to Sphinx.
Trying to find user with name "bob" and company_id "14".
Controller:
#users = User.search 'bob', :conditions => { :company_id => '14'}
Model:
define_index do
indexes :name
indexes :company_id
end
Error:
index user_core: query error: no field 'company_id' found in schema
I have the 'company_id' in table & I re-indexed everything several times.
When I am just searching for the 'name' everything works properly.

Just as another helpful hint: turns out I had to change the way I called Model.search(), since my field was listed as an attribute (i.e. using has), I needed to call the search method with :with instead of :conditions (for fields).

Attributes should be declared as:
has company_id
So, in you case:
Model:
define_index do
indexes :name
has :company_id
end

And one more helpful hint, if you happen to be an idiot like me:
If you are getting this error and you are correctly using attributes and fields, it may be that you forgot to restart your dev server after adding a new field to the index.

Related

ActiveRecord not behaving as I expect it

Ruby 2.0
Windows 8.1
Rails 4.1
MySQL2 gem
To avoid an error, I am using the following code to check for an existing payment, prior to creating a new payment record:
payment = {"organization_id" => organization_id,
"date" => row[1],
"amount" => row[2],
"description" => row[3]}
slug = "#{organization_id.to_s}_#{row[1].to_s}_#{row[2].to_s}_#{row[3]})
organization_payment = OrganizationPayment.where(:slug => slug)[0]
if !organization_payment
new_organization_payment = OrganizationPayment.create(payment)
end
Every once in a while, I am getting the following error:
Mysql2::Error at /process_uploaded_payments_data
Duplicate entry 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx' for key 'index_organization_payments_on_slug'
I also have the following in my model:
validates_uniqueness_of :slug
Is there any reason why the entry causing the duplicate error would not have been caught by the code above? Any ideas?
Solution
I am still not certain what caused the problem, but I learned the hard way that validating uniqueness does not really work, if you also have a before_save call in your model that creates the slug in question. The workaround is an exception handler:
begin
new_organization_payment = OrganizationPayment.create(payment)
rescue ActiveRecord::RecordNotUnique
next
end
I don't know if this is your problem but a possible cause of this could be race condition -- when your code is running in a process it can be interrupted right after the if condition before it creates the new record.
Putting a unique constraint on the column in the database is a fine way of dealing with this problem, though. You can catch the exception and deal with it that way. You also don't have to manually check for the duplicity, you can use active record validations; fetching the entire record just to check if it exists is not the best practice anyway. More info:
http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of

Rails + Postgres Relation Issue With Custom Foreign Key

I'm in the middle of a migration to Postgres from MySQL and i'v hit an issue that I just can't solve. I'm sure there is simple answer, but i'm stuck.
The Problem
I have a step model that belongs to a template model, but specifies a foreign key called template_uuid to match on the template tables uuid column.
This all worked fine on MySQL but now does not work on Postgres. Calling step.template would return the relevant template but now it returns nil
Both the uuid column on the template table and the template_uuid column on the step are UUID data types.
Example:
class Step < ActiveRecord::Base
belongs_to :template, :foreign_key => :template_uuid
So, I get nil when trying to call the association
step = Step.last
step.template => nil
But, I can query for the template using the template_uuid column, and it works just fine
Template.where(:uuid => step.template_uuid).first
So .. What am I missing here. The records and UUID's clearly line up so why does this relationship break now that i'm using Postgres. There is no physical foreign key on the database, but that's never mattered before.
Does anyone have any ideas?
I can't say why it worked before, but as long as you have also a custom primary_key on the associated model (other than :id), you have to provide that either
belongs_to :template, :primary_key => :uuid, :foreign_key => :template_uuid

What is the easiest way to insert data in MySQL using a ruby script

I did a ruby script that parses a lot of files in ruby data structures, like hashes for example.
I need to insert all this data in a MySQL database.
What I found:
mysql2
tmtm
dbi
Is there some native way to do this?
Thanks for any help
EDIT
Lets say that I have a hash with 100 entries like this:
hash = {"a" => 1, "b" => 2 ..., "c" => 100}
I would like to create a table at mysql with all this columns. I am afraid of Active Record is gonna be hard to do that.
PS: Im not using Rails, just a simple ruby script
If I were you, I would prefer ActiveRecord, because I don't have to clutter my code with lots of SQL statements. Besides activerecord makes life easier.
Set it up like this
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "host",
:username=>"user",
:password=>"user",
:database => "your_db"
)
Then use tables like this
class SingularTableName < ActiveRecord::Base
has_many :table_relationship
end
Then query like this
SingularTableName.all #=> all records
SingularTableName.first #=> first record
SingularTableName.where("query")
SingularTableName.create("...) #=> create a record/row
You can find more methods here => http://api.rubyonrails.org/classes/ActiveRecord/Base.html
Update:
To overcome plural table names and default primary key, you can use
class AnyName < ActiveRecord::Base
self.table_name = 'your table name'
self.primary_key = 'your primary key'
...
end

How to configure transient fields with Korma

I am using Clojure with korma to store Clojure maps in a Mysql database, e.g storing maps with this structure:
(defentity users
(table :user)
(entity-fields :email
:password
:name))
In a table with four columns id (implicitly defined), email, password and name.
So, when I call this piece of code everything works fine:
(insert users (values {:email "john#example.com"
:password "____hashed_passw___"
:name "J"}))
The problem I have is that my maps may contain some keys which do not have their corresponding columns in the database (and I do not want to persist these values). For example:
(insert users (values {:email "john#example.com"
:password "____hashed_passw___"
:name "J"
:something "else"}))
Would throw an error MySQLSyntaxErrorException Unknown column 'something' in 'field list'.
Ideally, what I would like to know is if there is an option somewhere in Korma to ignore the extra keys present in the map. The problem could be solved by dissoc-ing all of them on save, but I'd prefer to find out if there is a built in way to do it before I do that (or any other better idea).
No, you have to remove extra key/value pairs from the map. Arguably Korma could be made to remove them, based on defentities.
I suggest you either bring it up on https://github.com/korma/Korma as a feature request or look into adding it yourself. Chris Granger, the maintainer, is easy to talk to and would probably consider your idea.

How do I use a Rails ActiveRecord migration to insert a primary key into a MySQL database?

I need to create an AR migration for a table of image files. The images are being checked into the source tree, and should act like attachment_fu files. That being the case, I'm creating a hierarchy for them under /public/system.
Because of the way attachment_fu generates links, I need to use the directory naming convention to insert primary key values. How do I override the auto-increment in MySQL as well as any Rails magic so that I can do something like this:
image = Image.create(:id => 42, :filename => "foo.jpg")
image.id #=> 42
Yikes, not a pleasant problem to have. The least-kludgy way I can think of to do it is to have some code in your migration that actually "uploads" all the files through attachment-fu, and therefore lets the plugin create the IDs and place the files.
Something like this:
Dir.glob("/images/to/import/*.{jpg,png,gif}").each do |path|
# simulate uploading the image
tempfile = Tempfile.new(path)
tempfile.set_encoding(Encoding::BINARY) if tempfile.respond_to?(:set_encoding)
tempfile.binmode
FileUtils.copy_file(path, tempfile.path)
# create as you do in the controller - may need other metadata here
image = Image.create({:uploaded_data => tempfile})
unless image.save
logger.info "Failed to save image #{path} in migration: #{image.errors.full_messages}"
end
tempfile.close!
end
A look at attachment-fu's tests might be useful.
Unlike, say Sybase, in MySQL if you specify the id column in the insert statement's column list, you can insert any valid, non-duplicate value in the id. No need to do something special.
I suspect the rails magic is just to not let rails know the id is auto-increment. If this is the only way you'll be inserting into this table, then don't make the id auto_increment. Just make in an int not null primary key.
Though frankly, this is using a key as data, and so it makes me uneasy. If attachment_fu is just looking for a column named "id", make a column named id that's really data, and make a column named "actual_id" the actual, synthetic, auto_incremented key.
image = Image.create(:filename => "foo.jpg") { |r| r.id = 42 }
Here's my kluge:
class AddImages < ActiveRecord::Migration
def self.up
Image.destroy_all
execute("ALTER TABLE images AUTO_INCREMENT = 1")
image = Image.create(:filename => "foo.jpg")
image.id #=> 1
end
def self.down
end
end
I'm not entirely sure I understand why you need to do this, but if you only need to do this a single time, for a migration, just use execute in the migration to set the ID (assuming it's not already taken, which I can't imagine it would be):
execute "INSERT INTO images (id, filename) VALUES (42, 'foo.jpg')"
I agree with AdminMyServer although I believe you can still perform this task on the object directly:
image = Image.new :filename => "foo.jpg"
image.id = 42
image.save
You'll also need to ensure your id auto-increment is updated at the end of the process to avoid clashes in the future.
newValue = Images.find(:first, :order => 'id DESC').id + 1
execute("ALTER TABLE images AUTO_INCREMENT = #{newValue}")
Hope this helps.