I'm creating a form using Ruby Rails. It has a checkbox that when checked denotes the entry should be hidden (true or bit 1. vs false/bit 0), however, when I submit the checkbox I receive an error:
Mysql2::Error: Data too long for column 'hidden_status' at row 1: INSERT INTO `entries` ( 'hidden_status') VALUES (x'30')
The schema for entries and hidden_status is:
t.binary "hidden_status", limit: 1
The checkbox is:
<%= newEntry.check_box(:hidden_status,{checked:true},1,0)%>
I suspect this has something to do with the datatype being "bit"? However I'm not sure as I'm new to Ruby Rails and from what I looked up BIT is the only way to do a boolean/true vs false value in SQL. Looks like the value is coming up as as x'30'. Not sure what that means. Is there a way to allow the checkbox to capture 1 or 0?
Also, the parameters in the error shows that the value of the checkbox always returns 0 whether the box is checked or not. Not sure if this is a separate issue or related to the error.
MySQL still as of 2020 has not implemented a real boolean column type. But it does let you declare tables with BOOLEAN/BOOL:
CREATE TABLE tasks (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
completed BOOLEAN
);
Whats actually created is a tiny_int(1) column. Although the current advice is to use a bit column I doubt the Rails adapter knows how to map this to booleans.
You can just create the migration in Rails like you would in a real grown-up database (laughs in Postgres):
class CreateTasks < ActiveRecord::Migration[6.0]
def change
create_table :tasks do |t|
t.string :title
t.boolean :completed
t.timestamps
end
end
end
schema.rb will still list it as a boolean column as its an abstract polyglot representation of the database schema but MySQL will store it as tiny_int(1) and the database driver will take care of casting it to a boolean so you don't have to deal with 1 and 0 in Rails.
Related
I'm a bit stuck on a problem here in Rails that I feel may have a simple solution.
I have a class called "CircuitVw" which looks like the following
class CircuitVw < ActiveRecord::Base
self.table_name = 'mvw_circuits'
self.primary_key = :serv_item_id
Inside the controller, I've been able to pull back data using the following format
CircuitVw.all().order("customer_name DESC").each do | circuit |
#customer[ "#{circuit.customer_name}" ] = circuit.psr
end
However, when I try and access the table written this way, I get an uninitialized constant
MVW_CIRCUITS.where("activity_ind IN ( 'Pending', 'In Progress')").order("document_number DESC").each do | circuit |
#psr[ "#{circuit.psr} - #{circuit.customer_name}" ] = circuit.psr
end
Even though I can say something like
SELECT * FROM MVW_CIRCUITS
And return the entire table in the console for my staging environment.
What am I doing wrong here?
The table exists in the schema as
create_table "mvw_circuits", id: false, force: true do |t|
for reference.
Thanks for any insights you might have! Maybe I'm forgetting something dumb. Appreciate any and all help.
You have to use CircuitVw to access or refer to the table mvw_circuits. You specified that in the CircuitVw class. So MVW_CIRCUITS is an uninitialized constant.
Try this one
CircuitVw.where("activity_ind IN ('Pending', 'In Progress')")
Quick question on :null option in ActiveRecord table creation.
Let's say I was to create a new table with a column description.
def change
create_table :products do |t|
t.string :name
t.text :description, null: false
end
end
If I don't have any :presence validation in my model regarding the description column, then shouldn't "nothing" be able to be passed into the description column? I'm not sure what null: false can do to stop me from passing nothing in since I don't have any validation in place.
Rails migration or schema options like null: false operate on database level (storage). If you tried to save record with empty description field, you would receive a database error (e.g. generated by PostgreSQL) wrapped in a ActiveRecord::StatementInvalid:. On calling object.valid? the object would have been valid from the application point of view (Rails).
Rails validations like :presence operate on application level. In this case passing a null value would create an object which would return false on valid? and you could easily access error messages from the object by calling object.errors. If not bypassing validations, Rails would not allow you to save such a record to the database.
I have an Item model:
class Item < ActiveRecord::Base
...
define_index do
...
has deleted_at
indexes deleted_at
end
...
Then I stop the server, run rake ts:rebuild && rake ts:reindex && rake ts:restart, restart the server. And I still get the error.
The query that triggers the error is this:
Item.search({conditions: {deleted_at: nil}})
What's wrong ?
Note: I am using acts_as_paranoid. My database is migrated, the table items has the column deleted_at.
Somewhere in schema.rb:
...
create_table "items", :force => true do |t|
...
t.datetime "deleted_at"
There's a couple of related issues here:
You've got an attribute and a field with the same name (deleted_at) - you should alias one to have a different name using the :as option. Otherwise, Sphinx gets confused when reading the generated SQL data.
You've got a date column as a field, when it almost certainly isn't required - do you want users searching by deleted_at, or is it purely something for you to manage internally? I'm guessing the latter. So, remove the indexes deleted_at line.
You're setting a field condition in your search call when it should really be an attribute filter - which is done using the :with option.
Sphinx has no concept of nil, but should translate NULL values from the database into zeros.
So, with all that in mind, your index definition should rather be:
define_index do
# ...
has deleted_at
end
Run rake ts:rebuild to ensure Sphinx is aware of the changes and your index files are updated.
Then your search call is:
Item.search with: {deleted_at: 0}
Edit:
Is it possible to create a unique auto increment field that will be incremented on creates and updates in SQL using Rails (similar to an id field but incremented and re-assigned after an update)? For example:
Create Record A (Value: 1)
Create Record B (Value: 2)
Update Record A (Value: 3)
Update Record B (Value: 4)
I'm trying to setup pull synchronization and need a way to grab all records that have been created or updated since a previous synchronization.
I initially used the 'created_at' and 'updated_at' fields, but found them to be difficult to work with and somewhat inaccurate for partial synchronizations.
Edit:
I'm using Postgresql and Sqlite as my databases, so hopefully a solution exists that will work for both systems.
Edit:
To clarify, I want to pass a single integer to my server from the client (the largest 'sync' integer) and get back all the records created or updated after that record was created or updated.
Ended up adding a sequence integer field to my model and setup the following migration:
class CreateSequence < ActiveRecord::Migration
def self.up
begin
execute "CREATE SEQUENCE sequence"
rescue
end
end
def self.down
begin
execute "DROP SEQUENCE sequence"
rescue
end
end
end
Then, in my model I added:
before_save do
self.sequence = self.class.sequence
end
def self.sequence
s ||= self.connection.select_value("SELECT nextval('sequence') ") rescue nil
s ||= self.connection.select_value("SELECT strftime('%s','now')") rescue nil
return
end
Note: For Sqlite sequences are not supported so instead a selection of an 'epoch' form the database is required. However, this has the negative side effect of causing the sequence to be non-unique for rapid creation. However, in my case this was not an issue.
You could use a before_save callback, like so:
class MyModel < ActiveRecord::Base
before_save :increment
...
protected
def increment
self.revision ||= 1
self.revision += 1
end
end
You could make this more reusable by defining and using a Callback Class.
Another option it to use a Gem/plugin that does automatic versioning (and thus maintains a version field).
Whoops, didn't read too carefully.
If you want to grab the records that have been modified since the last sync you could create a boolean field for determining if the current record was synced. Set it to false by default and set it to false on any edit. That should allow you to pull only the items you need.
There is an id attribute that is provided by default and it auto increments. By default it is an integer, however if you were looking for a guid then let me know and I can point you to some good resources.
As far as pulling records since the last sync you could just grab the last id when you run the sync and use it as a starting value when you sync again.
So... the serial number is not associated with a row so much as a table, right?
class SerialNumber < AR::Base
has_many :thingies
# just has an integer serial number field
end
class Thingie < AR::Base
belongs_to :serial_number # probably want to include this in default scope
before_create :bump_serial
before_save : bump_serial
private
def bump_serial
self.serial_number ||= 0
self.serial_number += 1
end
end
This would appear to handle the cases of create, new/save, and update. But not destroy.
Try using the act_as_versioned gem.
It sets a version field for each record that you could use for synchronization. And I think that this would be a better way to synchronize across clients since you can compare the version on the server and client and synchronize those that are higher on the server.
The docs are here.
And the rubygem page is here.
I asked a question regarding this yesterday, but it was muddled and didn't make sense, so I'm going to boil it down to the core issue.
I have an entries table. When a new record is saved, the entries_controller adds a time to the date column, which is recorded as a datetime. In the new method, I declare a new DateTime as so:
#entry.date = DateTime.new( params[:year].to_i, params[:month].to_i, params[:day].to_i )
I then include it as a hidden field with formtastic:
<%= f.input :date, :as => :hidden %>
Once the entry is saved to the database, the date field looks like 2011-02-10 00:00:00. Everything is working as planned so far, but when I try to retrieve that entry by querying against the date field, I get nil.
I've tried:
search_date = DateTime.new(2011,2,10)
Entry.find_by_date(search_date)
=> nil
I've even tried to search by string, which doesn't make sense since it's a datetime field.
search_time = '2010-02-10 00:00:00'
Entry.find_by_date(search_date)
=> nil
What am I doing wrong here? Why can't I retrieve the record by date?
Would this work for you?
Entry.where("date = #{search_date}")
I just tested this in Rails 3.0.4, mysql2 0.2.6 and
Entry.find_by_date(DateTime.new(2011,2,10))
works.
Having said that, why are you using a datetime column to save a date? Other than it just being a bad idea, you possibly could be running into some kind of timezone issues based on your rails and sql settings. Some automatic timezone conversion could explain the behaviour you are observing but that's just a guess. Please check the development server logs to see if rails is indeed generating the query you wish it to generate.