I have this code:
require 'bundler/setup'
require 'sequel'
require 'sequel-rails'
require_relative 'support/benchmark_rails'
DB = Sequel.connect('sqlite::memory:')
COUNT=25
Sequel.extension :migration
Sequel.migration do
change do
create_table(:users) do
primary_key :id
COUNT.times do |i|
column :"column#{i}", "varchar(255)"
end
end
end
end
class User < Sequel::Model; end
attributes = {}
COUNT.times do |i|
attributes[:"column#{i}"] = "Some string #{i}"
end
Benchmark.rails("sequel/#{db_adapter}_create_string_columns", time: 5) do
User.create(attributes)
end
But when I try to run this, it gives the following error:
/home/aaditya/Downloads/ruby-bench-suite/rails/vendor/bundle/ruby/2.3.0/gems/sequel-3.40.0/lib/sequel/model/base.rb:1759:in `block in set_restricted': method name= doesn't exist (Sequel::Error)
from /home/aaditya/Downloads/ruby-bench-suite/rails/vendor/bundle/ruby/2.3.0/gems/sequel-3.40.0/lib/sequel/model/base.rb:1746:in `each'
from /home/aaditya/Downloads/ruby-bench-suite/rails/vendor/bundle/ruby/2.3.0/gems/sequel-3.40.0/lib/sequel/model/base.rb:1746:in `set_restricted'
from /home/aaditya/Downloads/ruby-bench-suite/rails/vendor/bundle/ruby/2.3.0/gems/sequel-3.40.0/lib/sequel/model/base.rb:1257:in `set'
from /home/aaditya/Downloads/ruby-bench-suite/rails/vendor/bundle/ruby/2.3.0/gems/sequel-3.40.0/lib/sequel/model/base.rb:1715:in `initialize_set'
from /home/aaditya/Downloads/ruby-bench-suite/rails/vendor/bundle/ruby/2.3.0/gems/sequel-3.40.0/lib/sequel/model/base.rb:899:in `initialize'
from benchmarks/bm_sequel_create_string_columns.rb:34:in `new'
from benchmarks/bm_sequel_create_string_columns.rb:34:in `<main>'
I tried to simplify this and tried to run only User.create(:name=>'Bob') but with no successful results. What mistake am I making?
There are no problems with the other methods as the same code is running for Active Record.
You are just defining the migration, you aren't actually running the CREATE TABLE on the database. Remove the migration code and just call DB.create_table.
You're creating user with name attribute but you don't have name column in your users table created.
Related
I just installed the camt_parser gem (https://github.com/Barzahlen/camt_parser)
With the following test program, no way to get the iban out of the substructre "transactions" from the structure "entry" from the structure "statement"
I get the following error:
in `block (2 levels) in <main>': undefined method `iban' for #<Array:0x007f9003a2ce30> (NoMethodError)
In the code I see that this class has a field called iban
Here is the code
require 'camt_parser'
camt = CamtParser::File.parse 'myCamt.xml'
camt.statements.each do |statement|
statement.entries.each do |entry|
# Access individual entries/bank transfers
puts entry.description
puts entry.debit
puts entry.transactions.iban
end
end
Thanks a lot guys!
It should be entry.transactions[0].iban as per the documentation. Check the Transaction#iban method. And the spec how to extract iban.
let(:transactions) { ex_entry.transactions }
let(:ex_transaction) { transactions[0] }
# .......
specify { expect(ex_transaction.iban).to eq("DE09300606010012345671") }
You called the iban on the collection of Transaction instances, but it should be on the instance of Transaction.
Im doing an assignment for a class and it uses column_types method in a rspec test.
it "User database structure in place" do
expect(User.column_names).to include "password_digest", "username"
expect(User.column_types["username"].type).to eq :string
expect(User.column_types["password_digest"].type).to eq :string
expect(User.column_types["created_at"].type).to eq :datetime
expect(User.column_types["updated_at"].type).to eq :datetime
end
Error: when i run rpsec in the command line.
Rails 5.0
Ubuntu 14.10
Failure/Error: expect(User.column_types["username"].type).to eq :string
NoMethodError:
undefined method `column_types' for #<Class:0x000000053a0188>
Did you mean? columns
column_names
# ./spec/assignment_spec.rb:67:in `block (5 levels) in <top (required)>'
# ./spec/assignment_spec.rb:14:in `block (2 levels) in <top (required)>'
The method was removed in this commit. It's not so easy to find it.
But, the reason is was not documented, it's because the method itself is not documented (Maybe it's just for internal use).
See this comment :nodoc: on the method when it existed:
def column_types # :nodoc:
#column_types ||= columns_hash.transform_values(&:cast_type).tap do |h|
h.default = Type::Value.new
end
end
You can read through the commit's description to understand the why and maybe see if there's something else you can do.
EDIT
Take a look at these lines maybe attributes_types or columns_hash can solve your problem.
The method column_types is removed in Rails 5.
To get the type of column you can try following code:
User.column_for_attribute('username').type
This will return the type, here in your case: :string
looks like in rails 5, column_types method no longer exist
You can use this to get a hash of all the column_types
User.columns_hash.each_with_object({}) { |obj, h| h[obj[1].name] = obj[1].sql_type }
So I'm working on an existing app and for some reason I was able to get it working and mirrored on my local environment however when I try migrating on heroku I get the below error, any ideas?
Error:
== 20141119113015 CreateReleasedInventoryStatus: migrating ====================
-- create_enum("eh_released_inventory_status", ["rejected", "pending", "allocated", "released", "transferred"])
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
no implicit conversion of Symbol into Integer/app/vendor/bundle/ruby/2.0.0/gems/power_enum-2.8.0/lib/power_enum/schema/schema_statements.rb:84:in `[]'
/app/vendor/bundle/ruby/2.0.0/gems/power_enum-2.8.0/lib/power_enum/schema/schema_statements.rb:84:in `create_enum'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/migration.rb:662:in `block in method_missing'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/migration.rb:632:in `block in say_with_time'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/migration.rb:632:in `say_with_time'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/migration.rb:652:in `method_missing'
/app/db/migrate/20141119113015_create_released_inventory_status.rb:3:in `change'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/migration.rb:606:in `exec_migration'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/migration.rb:590:in `block (2 levels) in migrate'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/migration.rb:589:in `block in migrate'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/connection
Migration file:
class CreateReleasedInventoryStatus < ActiveRecord::Migration
def change
create_enum("eh_released_inventory_status", ["rejected", "pending", "allocated", "released", "transferred"])
end
end
I'm also using the following gem:
gem 'power_enum'
Your migration syntax seems to be incorrect for the power_enum gem that you're using.
The gem's README says the syntax uses a name, then an options hash, such as:
create_enum("status", {…})
Whereas you're using a name, then an array:
create_enum("eh_released_inventory_status", […])
As far as I can tell, the solution is to change your migration line from what you posted to the power_enum syntax. The README has a bunch of examples, and also looks like it's thorough and very well documented.
I think you migration should look like this
class CreateReleasedInventoryStatus < ActiveRecord::Migration
def change
create_enum :released_inventory_status, name_column: :status, description: true, name_limit: 5
["rejected", "pending", "allocated", "released", "transferred"].each do |status|
ReleasedInventoryStatus.update_enumerations_model do |klass|
#0.8.1 < version < 0.9.3 does not yield the klass
#in this case use:
#ReleasedInventoryStatus.create
#in place of klass.create
klass.create :name => status,
:description => status.capitalize
end
end
end
end
This will create the table released_inventory_statuses with status and description columns with a limit of 5 unique statuses. Then it will populate status and description for each item in you list through update_enumeration_model. This should work for your use case but I have not tested this theory. My answer is purely based on how create_enum works and then this section of the README
update_enumerations_model (since version 0.8.1)
The preferred mechanism to update an enumerations model in migrations and similar. Pass in a block to this method to to perform any updates.
this is the first time I try to write a ruby migration script (I want to update the value of a col for a specific row).
I have a table called "events" with cols "e_id" and "e_text_en". I want to update the "e_text_en" value of the row with ID 6.
In SQL it would be
update events set e_text_en = 'blabla' where e_id = 6;
My ruby approach: (20141013130000_update_broken_event_texts.rb)
class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
def Events.up
Events.where('e_id', 6).update_all(e_text_en: "blablabla")
end
end
But this gives me the error ´NameError: uninitialized constant´
rake aborted!
NameError: uninitialized constant UpdateBrokenTextsEventInEvent::Events
/var/.../20141013130000_update_broken_event_texts.rb:2:in `<class:UpdateBrokenTextsEventInEvent>'
/var/.../20141013130000_update_broken_event_texts.rb:1:in `<top (required)>'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:718:in `load_migration'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:714:in `migration'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:708:in `disable_ddl_transaction'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:1012:in `use_transaction?'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:922:in `rescue in block in migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:919:in `block in migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:916:in `each'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:916:in `migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:764:in `up'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:742:in `migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/railties/databases.rake:42:in `block (2 levels) in <top (required)>'
Tasks: TOP => db:migrate
While I searched for a solution I found some advises that tables are called in singular, but even when I try Event instead of Events I get the same error.
Can anyone help me to correct my ruby?
Versions used:
$ rails -v
Rails 4.0.1
$ gem -v
1.8.23.2
$ ruby -v
ruby 1.9.3p545 (2014-02-24) [i686-linux] Brightbox
edit: Addional infos
Our Schema is created via sql-File. We started to use migrations a short time ago and this is the first update-one. The first two migrations where table-changes. We don't have any ´app/model´ files yet, becuase the other migrations worked without any, e.g.:
class AddDeliveriesToEmailQueue < ActiveRecord::Migration
def change
add_column :email_queue, :deliveries, :int, :null => false, :default => 0, :after => :error
end
end
Firstly your migration class name must match the file name (rails will load the migration file and then assume it created a class of the corresponding name). Assuming you don't change your file name, it means that you need to have
class UpdateBrokenEventTexts < ActiveRecord::Migration
...
end
Since you say that you have no model classes, you'll have to use raw SQL, for example
class UpdateBrokenEventTexts < ActiveRecord::Migration
def change
execute "UPDATE events SET e_text_en = 'blablabla'"
end
end
This is pretty much the same as using ActiveRecord::Base.connection.execute but saves a little on the typing and makes sure Rails understands you're making an irreversible change.
This is a common problem when you create migration and then deside to rename it. Class name in migration should be the same as the filename. You have migration with class UpdateBrokenTextsEventInEvent and filename 20141013130000_update_broken_event_texts.rb, but the class name should be UpdateBrokenEventTexts.
Create Event model:
$ rails g model Event
Assuming that you have a model class Event(inside app/models/event.rb) now, then change these lines:
class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
def Events.up
Events.where('e_id', 6).update_all(e_text_en: "blablabla")
end
end
to:
class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
def self.up
Event.where('e_id', 6).update_all(e_text_en: "blablabla")
end
end
Also, I'd recommend you to move such operations in a rake tasks instead of moving them in a migration file:
namespace :events do
desc "Update e_text_en field with blablabla"
task :update_e_text_en => :environment do
Event.where('e_id', 6).update_all(e_text_en: "blablabla")
end
end
and then from your terminal:
$ rake events:update_e_text_en
UPDATE: Don't plan to have a model class for now? No worries, you can still update the column but with a SQL query:
class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
def self.up
ActiveRecord::Base.connection.execute("UPDATE events SET e_text_en = 'blablabla'")
end
end
Please note that these actions are irreversible(since you don't know what was the previous data in the column you're updating) and that's why they shouldn't be in a migration file. You probably be better with a rake task or something for such operations.
Im working on a legacy oracle database with a slightly odd table naming convention where each column name is prefixed with the tables initial letters - eg policy.poli_id.
To make this database easier to work with I have a method set_column_prefix that creates accessors for each column with the prefix removed. ie:
# Taken from wiki.rubyonrails.org/rails/pages/howtouselegacyschemas
class << ActiveRecord::Base
def set_column_prefix(prefix)
column_names.each do |name|
next if name == primary_key
if name[/#{prefix}(.*)/e]
a = $1
define_method(a.to_sym) do
read_attribute(name)
end
define_method("#{a}=".to_sym) do |value|
write_attribute(name, value)
end
define_method("#{a}?".to_sym) do
self.send("#{name}?".to_sym)
end
end
end
end
end
This is in a file (insoft.rb) in my lib/ directory, and required from from my config/environment.rb after the Rails::Initializer.run block.
This has been working fine in development, but when I try to run the application in production mode, I get the following error in all of my models:
dgs#dgs-laptop:~/code/voyager$ RAILS_ENV=production script/server
=> Booting Mongrel
=> Rails 2.3.2 application starting on http://0.0.0.0:3000
/usr/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:1964:in `method_missing':
undefined method `set_column_prefix' for #<Class:0xb3fb81d8> (NoMethodError)
from /home/dgs/code/voyager/app/models/agent.rb:16
This error is triggered by the 'config.cache_classes = true' line in config/environments/production.rb.
If I set this to false, then rails will start up, but won't be caching classes. I'm guessing this makes rails cache all the models before it runs the Initializer block
If I move the 'require "insoft.rb'" to before the start of the Rails::Initializer.run block, then I get errors because ActiveRecord hasn't been initialized yet:
usr/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:443:in `load_missing_constant': uninitialized constant ActiveRecord (NameError)
from /usr/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:80:in `const_missing'
from /usr/lib/ruby/gems/1.8/gems/activesupport-2.3.2/lib/active_support/dependencies.rb:92:in `const_missing'
from /home/dgs/code/voyager/lib/insoft.rb:1
Where should I be including this custom lib and set_column_prefix method in order for it to be picked up before the models are cached, but after all the activerecord files have loaded?
Cheers
Dave Smylie
Where should I be including this custom lib and set_column_prefix method in order for it to be picked up before the models are cached, but after all the activerecord files have loaded?
Try setting up an initializer. You can call it config/initializers/insoft.rb with the contents of your monkey patch:
class << ActiveRecord::Base
def set_column_prefix(prefix)
column_names.each do |name|
next if name == primary_key
if name[/#{prefix}(.*)/e]
a = $1
define_method(a.to_sym) do
read_attribute(name)
end
define_method("#{a}=".to_sym) do |value|
write_attribute(name, value)
end
define_method("#{a}?".to_sym) do
self.send("#{name}?".to_sym)
end
end
end
end
end