Created a simple rake task to find Bikes for Sale in the USA. It works when i want to extract heading details but when I add other parameters like location, price , etc and save it to the Posts db I get error Can't cast Hash to string
Neils-MacBook-Pro-2:bike_scraper neilpatel$ rake scraper:scrape
rake aborted!
TypeError: can't cast Hash to string
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/abstract/quoting.rb:76:in `type_cast'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/sqlite3_adapter.rb:261:in `type_cast'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/sqlite3_adapter.rb:295:in `block in exec_query'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/sqlite3_adapter.rb:294:in `map'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/sqlite3_adapter.rb:294:in `exec_query'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:68:in `exec_insert'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:95:in `insert'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/relation.rb:64:in `insert'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/persistence.rb:503:in `_create_record'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/attribute_methods/dirty.rb:87:in `_create_record'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/callbacks.rb:306:in `block in _create_record'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.1.7/lib/active_support/callbacks.rb:82:in `run_callbacks'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/callbacks.rb:306:in `_create_record'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/timestamp.rb:57:in `_create_record'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/persistence.rb:483:in `create_or_update'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/callbacks.rb:302:in `block in create_or_update'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.1.7/lib/active_support/callbacks.rb:82:in `run_callbacks'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/callbacks.rb:302:in `create_or_update'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/persistence.rb:103:in `save'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/validations.rb:51:in `save'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/attribute_methods/dirty.rb:21:in `save'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/transactions.rb:268:in `block (2 levels) in save'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `block in transaction'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `within_new_transaction'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `transaction'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/transactions.rb:208:in `transaction'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/transactions.rb:268:in `block in save'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/transactions.rb:283:in `rollback_active_record_state!'
/usr/local/rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.1.7/lib/active_record/transactions.rb:267:in `save'
/Users/neilpatel/Desktop/Rails/bike_scraper/lib/tasks/scraper.rake:53:in `block (3 levels) in <top (required)>'
/Users/neilpatel/Desktop/Rails/bike_scraper/lib/tasks/scraper.rake:38:in `each'
/Users/neilpatel/Desktop/Rails/bike_scraper/lib/tasks/scraper.rake:38:in `block (2 levels) in <top (required)>'
Tasks: TOP => scraper:scrape
(See full trace by running task with --trace)
scraper.rake
namespace :scraper do
desc "Fetch Craigslist posts from 3Taps"
task scrape: :environment do
require 'open-uri' #ruby gem
require 'JSON'
# Set API token and URL
auth_token = "fadddddddd4a23a1cc86e0d"
polling_url = "http://polling.3taps.com/poll"
# Specify request parameters
params = {
auth_token: auth_token,
anchor: 2109915749,
source: "CRAIG",
category_group: "SSSS",
category: "SBIK",
'location.country' => "USA",
retvals: "location,external_url,heading,body,timestamp,price,images,annotations"
}
# Prepare API request
uri = URI.parse(polling_url)
uri.query = URI.encode_www_form(params)
# Submit request -hitting enter
result = JSON.parse(open(uri).read)
# Display results to screen (put string - display information)
#puts result["postings"].second["location"]
#store results in database
# Create new Post
result["postings"].each do |posting|
# Create new Post
#post = Post.new
#post.heading = posting["heading"]
#post.body = posting["body"]
#post.price = posting["price"]
#post.state = posting["location"]
#post.external_url = posting["external_url"]
#post.timestamp = posting["timestamp"]
# Save Post
#post.save
end
end
desc "TODO"
task destroy_all_posts: :environment do
end
end
Posts.db
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :heading
t.text :body
t.decimal :price
t.string :state
t.string :external_url
t.string :timestamp
t.timestamps
end
end
end
The error is coming from your #post.save line, so one of those fields that came back in posting is a Hash, not a String as you expect. It won't be price, so just check all the others by putsing them.
Update
I just ran your code, it's posting["location"] that's a Hash
Further Update
Looks like you just want the state out of that hash, ie.
#post.state = posting["location"]["state"]
Related
I want to try the gem closure_tree to build a tree for my genealogy database.
I installed the gem under Ruby MRI 2.3.0 on a windows 7 box.
The versions of the dependencies are in the errorlog below.
$ gem install closure_tree
Fetching: with_advisory_lock-3.0.0.gem (100%)
Successfully installed with_advisory_lock-3.0.0
Fetching: closure_tree-6.2.0.gem (100%)
Successfully installed closure_tree-6.2.0
2 gems installed
When I try the most minimalistic code it fails, I suppose because I don't use Rails and don't do the migration which again I presume creates the table tag_hierachies
My question is: Can I use this gem without Rails and if so how ?
require 'active_record'
require 'closure_tree'
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database => "sample.db"
)
if !ActiveRecord::Base.connection.table_exists?('tags')
ActiveRecord::Schema.define do
create_table :tags do |table|
table.column :name, :string
table.column :parent_id, :integer
end
end
end
class Tag < ActiveRecord::Base
has_closure_tree
end
grandparent = Tag.create(name: 'Grandparent')
gives
d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/sqlite3_adapter.rb:513:in `table_structure': Could not find table 'tag_hierarchies' (ActiveRecord::StatementInvalid)
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/sqlite3_adapter.rb:387:in `columns'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/schema_cache.rb:43:in `columns'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/attributes.rb:93:in `columns'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/attributes.rb:98:in `columns_hash'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:205:in `subclass_from_attributes?'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:54:in `new'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/persistence.rb:50:in `create!'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/hierarchy_maintenance.rb:65:in `block in rebuild!'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/support.rb:108:in `block (2 levels) in with_advisory_lock'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `transaction'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:220:in `transaction'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/support.rb:108:in `block in with_advisory_lock'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/base.rb:77:in `yield_with_lock'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/base.rb:65:in `yield_with_lock_and_timeout'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/base.rb:48:in `with_advisory_lock_if_needed'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/concern.rb:16:in `with_advisory_lock_result'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/with_advisory_lock-3.0.0/lib/with_advisory_lock/concern.rb:10:in `with_advisory_lock'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/support.rb:107:in `with_advisory_lock'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/hierarchy_maintenance.rb:63:in `rebuild!'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/closure_tree-6.2.0/lib/closure_tree/hierarchy_maintenance.rb:39:in `_ct_after_save'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:432:in `block in make_lambda'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:228:in `block in halting_and_conditional'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:506:in `block in call'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:506:in `each'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:506:in `call'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:92:in `__run_callbacks__'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activesupport-4.2.6/lib/active_support/callbacks.rb:778:in `_run_save_callbacks'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/callbacks.rb:302:in `create_or_update'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/persistence.rb:120:in `save'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/validations.rb:37:in `save'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/attribute_methods/dirty.rb:21:in `save'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:286:in `block (2 levels) in save'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:220:in `transaction'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:286:in `block in save'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/transactions.rb:285:in `save'
from d:/Ruby/lib/ruby/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/persistence.rb:34:in `create'
from C:/Users/Gebruiker/BoxSync/ruby_werk/acts_as_tree/closure_tree.rb:22:in `<main>'
Seems the installation instructions in README is focused with only Rails in mind. It does however tell you that you need another table(in addition to your current tags table) with the name tag_hierarchies.
In Rails, generation of this table seems to be part of the installation steps; Step 5 in the linked documentation.
So, you should be creating tag_hierarchies table with the following content, which is what rails g closure_tree:migration tag generates as far as the table structure is concerned. See create_hierarchies_table.rb.erb, as you may also want to add index as shown in this linked file.
So, updating your script to following worked as expected for me:
require 'active_record'
require 'closure_tree'
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database => "sample.db"
)
if !ActiveRecord::Base.connection.data_source_exists?('tags')
ActiveRecord::Schema.define do
create_table :tags do |table|
table.column :name, :string
table.column :parent_id, :integer
end
end
end
# You also need a corresponding model's table name followed by "_hierarchies" table.
#
# Migration created based on
# `https://github.com/mceachen/closure_tree/blob/master/lib/generators/closure_tree/templates/create_hierarchies_table.rb.erb`
if !ActiveRecord::Base.connection.data_source_exists?(:tag_hierarchies)
ActiveRecord::Schema.define do
create_table :tag_hierarchies do |table|
table.integer :ancestor_id, null: false
table.integer :descendant_id, null: false
table.integer :generations, null: false
end
end
end
class Tag < ActiveRecord::Base
has_closure_tree
end
grandparent = Tag.create(name: 'Grandparent')
grandparent.children.create(name: 'Father')
grandparent.children.create(name: 'Uncle')
class AddOpenAttributeToCourses < ActiveRecord::Migration
def change
add_column :courses, :open, :boolean
change_column_default(:courses, :open, {:from=>true, :to=>false})
end
end
!!!!!then Operation!!!!!!
rake db:migrate
== 20161126133112 AddOpenAttributeToCourses: migrating ========================
-- add_column(:courses, :open, :boolean)
-> 0.1047s
-- change_column_default(:courses, :open, {:from=>true, :to=>false})
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::InvalidTextRepresentation: ERROR: invalid input syntax for type boolean: "---
:from: true
:to: false
"
: ALTER TABLE "courses" ALTER COLUMN "open" SET DEFAULT '---
:from: true
:to: false
'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `block in execute'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/abstract_adapter.rb:472:in `block in log'
/usr/local/rvm/gems/ruby-2.3.0/gems/activesupport-4.2.5.2/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `log'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:154:in `execute'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/postgresql/schema_statements.rb:455:in `change_column_default'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:665:in `block in method_missing'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:634:in `block in say_with_time'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:634:in `say_with_time'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:654:in `method_missing'
/home/ubuntu/workspace/db/migrate/20161126133112_add_open_attribute_to_courses.rb:4:in `change'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:608:in `exec_migration'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:592:in `block (2 levels) in migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:591:in `block in migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:292:in `with_connection'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:590:in `migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:768:in `migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:998:in `block in execute_migration_in_transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:1044:in `block in ddl_transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/transactions.rb:220:in `transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:1044:in `ddl_transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:997:in `execute_migration_in_transaction'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:959:in `block in migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:955:in `each'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:955:in `migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:823:in `up'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/migration.rb:801:in `migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/tasks/database_tasks.rb:137:in `migrate'
/usr/local/rvm/gems/ruby-2.3.0/gems/activerecord-4.2.5.2/lib/active_record/railties/databases.rake:44:in `block (2 levels) in <top (required)>'
/usr/local/rvm/gems/ruby-2.3.0/gems/rake-11.2.2/exe/rake:27:in `<top (required)>'
ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type boolean: "---
:from: true
:to: false
"
You're trying to use the Rails5 arguments to change_column_default:
change_column_default(table_name, column_name, default_or_changes)
[...]
Passing a hash containing :from and :to will make this change reversible in migration:
change_column_default(:posts, :state, from: nil, to: "draft")
with Rails4:
change_column_default(table_name, column_name, default)
Sets a new default value for a column: [...]
The funny looking stuff you see in the SQL:
---
:from: true
:to: false
is the YAML version of your { :from => true, :to => false } Ruby Hash BTW.
You need to use separate up and down methods and simpler version of change_column_default with Rails4:
def up
change_column_default(:courses, :open, false)
end
def down
change_column_default(:courses, :open, true)
end
or just set the default when you create the column:
class AddOpenAttributeToCourses < ActiveRecord::Migration
def change
add_column :courses, :open, :boolean, :default => false
end
end
BTW, since you didn't specify a :default when you added the column it would have a default of null, not true.
You can create the column and set a default in one line:
add_column :courses, :open, :boolean, default: true
Not sure exactly why you're getting that error. Maybe it's because you say "change the default from false to true" but the default was not false, actually it was nil.
I have the following setup in a rails app:
class Song < ActiveRecord::Base
after_commit :update_singable_index
belongs_to :singable, polymorphic: true
def update_singable_index
singable.update_index if singable.respond_to? :update_index
end
end
I've redacted the actual class heavily. Please let me know if any more information is needed.
But basically the Song model has a polymorphic association with a bunch of models. Some of them have elasticsearch indices and some of them don't. As a result some of them will accept the update_index message, while others will throw an NoMethodError: undefined method 'update_index'
The sing factory looks like this:
FactoryGirl.define do
factory :song do
album { create(:album) }
end
trait :for_updatable do
updatable_type 'Updatable'
association :singable, factory: :updatable
end
trait :for_unupdatable do
updatable_type 'Unupdatable'
association :singable, factory: :unupdatable
end
end
Then in the test I have the following setup:
RSpec.describe Song, type: :model do
describe '.update_index_of_updatable' do
it 'updates Updatable\'s index' do
song = create(:song, :for_updatable)
updatable = song.singable
expect(updatable).to receive(:update_index)
song.save
end
it 'doesn\'t attempt to update an Unupdatable\'s index' do
song = create(:song, :for_unupdatable)
unupdatable = song.singable
expect(unupdatable).not_to receive(:update_index)
song.save
end
end
end
The first test does indeed pass. The second test on the other hand fails
1) Song.update_singable_index doesn't attempt to update an Unupdatable's index
Failure/Error: update.save
(#<Unupdatable:0x0000000b39be98>).update_index(no args)
expected: 0 times with any arguments
received: 1 time
# ./app/models/song.rb:103:in `update_index_of_updatable'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:430:in `block in make_lambda'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:261:in `call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:261:in `block in simple'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `block in call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `each'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:88:in `run_callbacks'
# /usr/local/rvm/gems/ruby-2.2.3/gems/bugsnag-2.8.12/lib/bugsnag/rails/active_record_rescue.rb:8:in `run_callbacks'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:314:in `committed!'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:89:in `commit_records'
# /usr/local/rvm/gems/ruby-2.2.3/gems/test_after_commit-0.4.1/lib/test_after_commit.rb:47:in `test_commit_records'
# /usr/local/rvm/gems/ruby-2.2.3/gems/test_after_commit-0.4.1/lib/test_after_commit.rb:23:in `block in transaction_with_transactional_fixtures'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/test_after_commit-0.4.1/lib/test_after_commit.rb:9:in `transaction_with_transactional_fixtures'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:220:in `transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:286:in `block in save'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:285:in `save'
# ./spec/models/song_spec.rb:141:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:417:in `block (2 levels) in <top (required)>'
# ./spec/rails_helper.rb:192:in `block (2 levels) in <top (required)>'
# /usr/local/rvm/gems/ruby-2.2.3/gems/rspec-retry-0.4.2/lib/rspec/retry.rb:52:in `block (3 levels) in apply'
# /usr/local/rvm/gems/ruby-2.2.3/gems/rspec-retry-0.4.2/lib/rspec/retry.rb:43:in `times'
# /usr/local/rvm/gems/ruby-2.2.3/gems/rspec-retry-0.4.2/lib/rspec/retry.rb:43:in `block (2 levels) in apply'
You didn't show your :for_unupdatable trait, but it must be the flawed part here (meaning, a singable of a song with this trait still responds to update_index).
So, you should fix that.
Alternatively, provide a dummy implementation of that method for non-ES-capable models.
class ElasticSearchSingable
# your regular update_index
end
class SimpleSingable
def update_index
# do nothing here,
# purpose of this empty method is conformance to common API
end
end
I'm getting this error when trying to run a rake task using Nokogiri.
This is the code.
namespace :tops do
desc "Get Tops Description"
task get_description: :environment do
require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open("http://ceratoboutique.com/collections/tops"))
price = Array.new
items = Array.new
brands = Array.new
sale_price = Array.new
image = Array.new
item_url = Array.new
price = doc.xpath("//del").collect {|node| node.text.strip}
items = doc.xpath("//div/a/h4").collect {|node| node.text.strip}
brands = doc.xpath("//span[contains(#class,'vendor')]").collect {|node| node.text.strip}
sale_price = doc.xpath("//span[contains(#class, 'price')]/text()").collect {|node| node.text.strip}
image = doc.xpath("/div/a/img/#src").collect {|node| node.text.strip}
item_url = doc.css('div.details a').map { |link| link['href'] }.collect
price.each do |prices|
Tops.create(description: price)
end
end
end
This is the full error.
Rake aborted! TypeError: can't cast Array to string
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/abstract/quoting.rb:76:in type_cast'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/sqlite3_adapter.rb:261:intype_cast'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/sqlite3_adapter.rb:295:in block in exec_query'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/sqlite3_adapter.rb:294:inmap'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/sqlite3_adapter.rb:294:in exec_query'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/abstract/database_statements.rb:68:in
exec_insert'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/abstract/database_statements.rb:95:in
insert'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in
insert'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/relation.rb:64:in
insert'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/persistence.rb:502:in
_create_record'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/attribute_methods/dirty.rb:87:in
_create_record'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/callbacks.rb:306:in
block in _create_record'
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.1.5/lib/active_support/callbacks.rb:82:in
run_callbacks'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/callbacks.rb:306:in
_create_record'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/timestamp.rb:57:in
_create_record'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/persistence.rb:482:in
create_or_update'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/callbacks.rb:302:in
block in create_or_update'
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.1.5/lib/active_support/callbacks.rb:82:in
run_callbacks'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/callbacks.rb:302:in
create_or_update'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/persistence.rb:103:in
save'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/validations.rb:51:in
save'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/attribute_methods/dirty.rb:21:in
save'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/transactions.rb:268:in block (2 levels) in save'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/transactions.rb:329:inblock in with_transaction_returning_status'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in
block in transaction'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/abstract/database_statements.rb:209:in
within_new_transaction'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in
transaction'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/transactions.rb:208:intransaction'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/transactions.rb:326:in with_transaction_returning_status'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/transactions.rb:268:inblock in save'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/transactions.rb:283:in rollback_active_record_state!'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/transactions.rb:267:insave'
/Library/Ruby/Gems/2.0.0/gems/activerecord-4.1.5/lib/active_record/persistence.rb:34:in
create' /Users/Kcummings/Sites/rvm_tests/lib/tasks/tops.rake:24:in
block (3 levels) in '
/Users/Kcummings/Sites/rvm_tests/lib/tasks/tops.rake:23:in each'
/Users/Kcummings/Sites/rvm_tests/lib/tasks/tops.rake:23:inblock (2
levels) in '
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/task.rb:240:in
call'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/task.rb:240:in
block in execute'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/task.rb:235:in
each'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/task.rb:235:in
execute'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/task.rb:179:in
block in invoke_with_call_chain'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/monitor.rb:211:in
mon_synchronize'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/task.rb:172:in
invoke_with_call_chain'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/task.rb:165:in
invoke'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:150:in
invoke_task'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:106:in
block (2 levels) in top_level'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:106:in
each'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:106:in
block in top_level'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:115:in
run_with_threads'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:100:in
top_level'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:78:in
block in run'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:176:in
standard_exception_handling'
/Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/lib/rake/application.rb:75:in
run' /Library/Ruby/Gems/2.0.0/gems/rake-10.3.2/bin/rake:33:in' /usr/bin/rake:23:in load' /usr/bin/rake:23:in'
Edit: TOPS TABLE SCHEMA
ActiveRecord::Schema.define(version: 20140824150641) do
create_table "tops", force: true do |t|
t.string "brand"
t.string "description"
t.string "image"
t.decimal "price"
t.datetime "created_at"
t.datetime "updated_at"
t.string "url"
end
end
Seems that you have description field in table tops as 'varchar' or string, however you are trying to store array in it.
You need to change datatype of description field to text and then serialize the value before trying to store it.
Generate new migration file and run it, On your terminal:
rails g migration change_desc_in_my_tops
As you are using Rails 4, add following code in your migration file:
class ChangeDescInTops < ActiveRecord::Migration
def up
change_column :tops, :description, :text
end
def down
change_column :tops, :description, :string
end
end
Now run migration:
rake db:migrate
Update your tops model as:
class Tops < ActiveModel::Base
serialize :description, Array
...
...
end
Now try to run your rake task. Hope, it will help you.
NOTE: You should use singular model names. Your Tops model could be Top. It avoids confusion while using associations and it follows convention.
You quite confusing have set price to be an array (rather than calling it prices) which was possibly a contributing factor in your typo below
price.each do |prices|
Tops.create(description: price)
end
You are assigning the array you are iterating over, rather than the individual element that is being yielded.
Can't seem to find a solution to this one. I have a relational table, BlabsUser, from which I'm trying to find and destroy a record. I'm doing this:
BlabsUser.find_by_user_id_and_blab_id(1,29).destroy
And getting this lovely error:
BlabsUser Load (0.2ms) SELECT "blabs_users".* FROM "blabs_users" WHERE "blabs_users"."user_id" = 1 AND "blabs_users"."blab_id" = 29 LIMIT 1
Could not log "sql.active_record" event. NoMethodError: undefined method `name' for nil:NilClass
SQLite3::SQLException: no such column: blabs_users.: DELETE FROM "blabs_users" WHERE "blabs_users"."" = ?
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: blabs_users.: DELETE FROM "blabs_users" WHERE "blabs_users"."" = ?
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in `initialize'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in `new'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/sqlite3-1.3.5/lib/sqlite3/database.rb:91:in `prepare'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:234:in `block in exec_query'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract_adapter.rb:244:in `block in log'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.3/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract_adapter.rb:239:in `log'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:223:in `exec_query'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/sqlite_adapter.rb:249:in `exec_delete'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract/database_statements.rb:101:in `delete'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `delete'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/relation.rb:351:in `delete_all'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/persistence.rb:94:in `destroy'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/locking/optimistic.rb:119:in `destroy'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/callbacks.rb:254:in `block in destroy'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.3/lib/active_support/callbacks.rb:390:in `_run_destroy_callbacks'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.1.3/lib/active_support/callbacks.rb:81:in `run_callbacks'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/callbacks.rb:254:in `destroy'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/transactions.rb:236:in `block in destroy'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/transactions.rb:208:in `transaction'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.1.3/lib/active_record/transactions.rb:236:in `destroy'
from (irb):1
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.3/lib/rails/commands/console.rb:45:in `start'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.3/lib/rails/commands/console.rb:8:in `start'
from /Users/dylandrop/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.3/lib/rails/commands.rb:40:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Why is it looking for a column called blabs_users? Why isn't it just looking for a record in my blabs_users table? Also, more importantly, how do I fix this?
Edit:
And I've also tried this with the same problem:
BlabsUser.destroy_all(:blab_id => 29, :user_id => 1)
Edit 2, as per request:
My model is just
class BlabsUser < ActiveRecord::Base
end
Migration is just
class BlabsUsers < ActiveRecord::Migration
def self.up
create_table :blabs_users, :id => false, :force => true do |t|
t.integer :user_id
t.integer :blab_id
t.timestamps
end
end
def self.down
drop_table :blabs_users
end
end
ActiveRecord depends pretty heavily on having a unique key to work with (usually the primary key of the table) Since you explicitly don't have one defined (:id => false), I strongly suspect that your problem is related to that.
destroy() is also documented as Destroy an object (or multiple objects) that has the given id which strongly suggests it needs that unique id to work with.