Rails 4 model is valid, but won't save? - ruby-on-rails

I have the following models:
notification
class Notification < ActiveRecord::Base
belongs_to :notification_path
before_save :set_default
def set_default
self.resolved = false unless self.resolved
end
end
notification_path
class NotificationPath < ActiveRecord::Base
has_many :notifications
end
Then this code:
notification = Notification.new({"area"=>"test", "severity"=>"10", "message"=>"Test", "notification_path_id" => 3})
<Notification id: nil, area: "test", severity:
10, message: "Test", created_at: nil, updated_at: nil,
notification_path_id: 3, resolved: nil>
notification.valid?
true
notification.errors.full_messages
[]
So, as you can see - notification is valid and has no errors. There are zero validations on the notification model. But then, when I save the model:
notification.save
false
It won't save. What is causing this? It may be worth noting that set_default does run successfully, and even though the model isn't saving the resolved attribute is being set to false when it tries to save.
EDIT
Full error trace below, when following the above in IRB:
notification.save! ActiveRecord::RecordNotSaved: ActiveRecord::RecordNotSaved from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/persistence.rb:125:in
save!' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/validations.rb:57:in
save!' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/attribute_methods/dirty.rb:29:in
save!' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:273:in
block in save!' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:329:in
block in with_transaction_returning_status' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in
block in transaction' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/connection_adapters/abstract/database_statements.rb:219:in
within_new_transaction' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in
transaction' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:208:in
transaction' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:326:in
with_transaction_returning_status' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activerecord-4.1.0.rc1/lib/active_record/transactions.rb:273:in
save!' from (irb):23 from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/railties-4.1.0.rc1/lib/rails/commands/console.rb:90:in
start' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/railties-4.1.0.rc1/lib/rails/commands/console.rb:9:in
start' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/railties-4.1.0.rc1/lib/rails/commands/commands_tasks.rb:69:in
console' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/railties-4.1.0.rc1/lib/rails/commands/commands_tasks.rb:40:in
run_command!' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/railties-4.1.0.rc1/lib/rails/commands.rb:17:in' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:247:in
require' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:247:in
block in require' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:232:in
load_dependency' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:247:in
require' from /Users/Jonathan/steel_notify/bin/rails:8:in <top
(required)>' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:241:in
load' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:241:in
block in load' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:232:in
load_dependency' from
/Users/Jonathan/.rvm/gems/ruby-2.1.1#steel_notify/gems/activesupport-4.1.0.rc1/lib/active_support/dependencies.rb:241:in
load' from
/Users/Jonathan/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in
require' from
/Users/Jonathan/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in
require' from -e:1:in'

In Ruby, assignments return the value being assigned. In your case you are setting self.resolved to false. When you return exactly false from a before_* callback, it will cancel the save operation. You need to return something that is not false after you make your assignment.

Related

`object.message if object.respond_to? :message` works, but is proving difficult to test

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

PgSearch 1.0.0 throws ModelNotMultisearchable error when trying to rebuild from console

I've got an app with 4 different models which are multisearchable, however they were originally set up with a pg_search_scope; ie:
class Episode < ActiveRecord::Base
include PgSearch
# multisearchable :against => [:title, :description]
pg_search_scope :search_text,
:against => [:title, :description],
:using => {
:tsearch => {:prefix => true}
}
As you can see at one point I tried setting this up the multiserachable way.
Of late there are items we know should be returning that are NOT in the search results, and I thought I'd have to rebuild the pg_search_documents; however that's throwing an error:
irb(main):004:0> PgSearch::Multisearch.rebuild(Show)
PgSearch::Multisearch::ModelNotMultisearchable: PgSearch::Multisearch::ModelNotMultisearchable
from /app/vendor/bundle/ruby/2.0.0/gems/pg_search-0.7.3/lib/pg_search/multisearch/rebuilder.rb:6:in `initialize'
from /app/vendor/bundle/ruby/2.0.0/gems/pg_search-0.7.3/lib/pg_search/multisearch.rb:10:in `new'
from /app/vendor/bundle/ruby/2.0.0/gems/pg_search-0.7.3/lib/pg_search/multisearch.rb:10:in `block in rebuild'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.0.2/lib/active_record/transactions.rb:209:in `transaction'
from /app/vendor/bundle/ruby/2.0.0/gems/pg_search-0.7.3/lib/pg_search/multisearch.rb:8:in `rebuild'
from (irb):4
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.0.2/lib/rails/commands/console.rb:90:in `start'
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.0.2/lib/rails/commands/console.rb:9:in `start'
from /app/vendor/bundle/ruby/2.0.0/gems/railties-4.0.2/lib/rails/commands.rb:62:in `<top (required)>'
from /app/bin/rails:4:in `require'
from /app/bin/rails:4:in `<main>'
irb(main):005:0>
I thought that it might be because of the setup as a pg_search_scope, so I set one class as above with the multisearch:multisearchable :against => [:title, :description] -- but even then I get rebuild problems.
I tried the manual way of deleting from the pg_search table and rebuilding but even THAT's throwing an error:
2.1.0 :010 > Show.find_each{ |record| record.update_pg_search_document }
Show Load (4.8ms) SELECT "shows".* FROM "shows" ORDER BY "shows"."id" ASC LIMIT 1000
NoMethodError: undefined method `update_pg_search_document' for #<Show:0x007fd945a92358>
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activemodel-4.0.2/lib/active_model/attribute_methods.rb:439:in `method_missing'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.2/lib/active_record/attribute_methods.rb:155:in `method_missing'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/acts_as_follower-0.2.1/lib/acts_as_follower/followable.rb:54:in `method_missing'
from (irb):10:in `block in irb_binding'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.2/lib/active_record/relation/batches.rb:26:in `block (2 levels) in find_each'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.2/lib/active_record/relation/batches.rb:26:in `each'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.2/lib/active_record/relation/batches.rb:26:in `block in find_each'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.2/lib/active_record/relation/batches.rb:75:in `find_in_batches'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-deprecated_finders-1.0.3/lib/active_record/deprecated_finders/relation.rb:70:in `find_in_batches'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.2/lib/active_record/relation/batches.rb:25:in `find_each'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/activerecord-4.0.2/lib/active_record/querying.rb:8:in `find_each'
from (irb):10
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/railties-4.0.2/lib/rails/commands/console.rb:90:in `start'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/railties-4.0.2/lib/rails/commands/console.rb:9:in `start'
from /Users/grimm/.rvm/gems/ruby-2.1.0/gems/railties-4.0.2/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4
I've been getting the same error while trying to rebuild (for the first time, installing) via the Rails command line with PgSearch::Multisearch.rebuild(Professor). What's worked for me is instead rebuilding from the command line using the alternative approach recommended on the Github:
rake pg_search:multisearch:rebuild[Professor]
This seems to work for me -- it doesn't throw an error, and when I go to the Rails console after and run PgSearch.multisearch("query") it's returning a result, whereas before it was returning an error.
I know this isn't a fix, but it's a solution to the immediate problem. I hope it helps -- posting an issue on their Github might lead to a fuller fix.

Rails monkey patch only on certain columns

I am trying to include a module only if the subclass has a certain column,
and I am doing this in an initializer:
class ActiveRecord::Base
def self.inherited(subclass)
subclass.include(MultiTenancy) if subclass.new.respond_to?(:tenant_id)
end
end
I keep getting this error:
NoMethodError: undefined method `[]' for nil:NilClass
Here is the module that I am importing:
module MultiTenancy
class TenantNotSetError < StandardError ; end
def self.included(model)
model.class_eval do
belongs_to :tenant
validates :tenant_id, presence: true
default_scope -> {
raise TenantNotSetError.new unless Tenant.current_tenant
where(tenant_id: Tenant.current_tenant.id)
}
def multi_tenanted?
true
end
end
end
end
What am I doing wrong. I can include the module on any subclass separate eg. Klass.include(MultiTenancy) successfully, so the problem is with the initializer.
Below is the stack trace:
from -e:1:in `<main>'2.1.1 :002 > Klass.all
NoMethodError: undefined method `[]' for nil:NilClass
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/relation/delegation.rb:9:in `relation_delegate_class'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/relation/delegation.rb:112:in `relation_class_for'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/relation/delegation.rb:106:in `create'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activerecord-4.1.4/lib/active_record/model_schema.rb:133:in `table_name='
from /home/lee/Code/mobifit/app/models/klass.rb:25:in `<class:Klass>'
from /home/lee/Code/mobifit/app/models/klass.rb:22:in `<top (required)>'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:443:in `load'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:443:in `block in load_file'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:633:in `new_constants_in'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:442:in `load_file'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:342:in `require_or_load'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:480:in `load_missing_constant'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:180:in `const_missing'
from (irb):2
from /home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/console.rb:90:in `start'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/console.rb:9:in `start'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/commands_tasks.rb:69:in `console'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/railties-4.1.4/lib/rails/commands.rb:17:in `<top (required)>'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `require'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `block in require'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:232:in `load_dependency'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `require'
from /home/lee/Code/mobifit/bin/rails:8:in `<top (required)>'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:241:in `load'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:241:in `block in load'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:232:in `load_dependency'
from /home/lee/.rvm/gems/ruby-2.1.1/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:241:in `load'
from /home/lee/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /home/lee/.rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from -e:1:in `<main>'2.1.1 :003 >
If you follow the stack trace back a bit, you can see that the thing that's nil that isn't supposed to be is is the class's #relation_delegate_cache. Looking at the source, you can see that this normally gets initialized in the initialize_relation_delegate_cache method, which is called in the inherited hook for ActiveRecord::Delegation::DelegateCache.
ActiveRecord::Base extends this module, so normally a class that inherits from ActiveRecord::Base would call this inherited hook. So the problem with your code is that you're monkey-patching inherited on ActiveRecord::Base, which means that the hook in ActiveRecord::Delegation::DelegateCache is no longer being called.
Two comments:
This is why it's a bad idea to monkey-patch, especially something as fundamental and complex as active record. Is it possible to do what you want to do in a more straightforward way?
If it's not, you should take some notes on how ActiveRecord::Delegation::DelegateCache works and rewrite your monkey patch to mix in a module of your own, rather than just over-writing ActiveRecord::Base's inherited method.
The suggestion in (2) would look something like this:
module MultitenancyConcern
def self.inherited(subclass)
subclass.include(MultiTenancy) if subclass.column_names.include?("tenant_id")
super #this is critical for avoiding the error you're getting
end
end
then your monkey-patch becomes just
ActiveRecord::Base.extend(MultitenancyConcern)

Rails : gem "dynamoid" list_tables error

I'm not new to DynamoDB, but I'm new to DynamoID gem.
I can't achieve to make it work since I get the following error :
/aws-sdk-1.28.1/lib/aws/core/client.rb:366:in `return_or_raise': The action or operation requested is invalid. Verify that the action is typed correctly. (AWS::DynamoDB::Errors::InvalidAction)
/aws-sdk-1.28.1/lib/aws/core/client.rb:467:in `client_request'
(eval):3:in `list_tables'
/aws-sdk-1.28.1/lib/aws/dynamo_db/table_collection.rb:121:in `_each_item'
/aws-sdk-1.28.1/lib/aws/core/collection/with_limit_and_next_token.rb:54:in `_each_batch'
/aws-sdk-1.28.1/lib/aws/core/collection.rb:80:in `each_batch'
/aws-sdk-1.28.1/lib/aws/core/collection.rb:47:in `each'
/dynamoid-0.7.1/lib/dynamoid/adapter/aws_sdk.rb:185:in `collect'
/dynamoid-0.7.1/lib/dynamoid/adapter/aws_sdk.rb:185:in `list_tables'
/dynamoid-0.7.1/lib/dynamoid/adapter.rb:146:in `block (3 levels) in <module:Adapter>'
/dynamoid-0.7.1/lib/dynamoid/adapter.rb:39:in `benchmark'
/dynamoid-0.7.1/lib/dynamoid/adapter.rb:146:in `block (2 levels) in <module:Adapter>'
/dynamoid-0.7.1/lib/dynamoid/adapter.rb:25:in `block in reconnect!'
/dynamoid-0.7.1/lib/dynamoid/adapter.rb:39:in `benchmark'
/dynamoid-0.7.1/lib/dynamoid/adapter.rb:25:in `reconnect!'
/dynamoid-0.7.1/lib/dynamoid.rb:35:in `configure'
app/config/initializers/dynamoid.rb:1:in `<top (required)>'
It seems that list_tables doesn't exist, but it's a method of the AWS Ruby SDK
My model is very simple :
class Interaction
include Dynamoid::Document
table :name => :interactions, :key => :from, :read_capacity => 1, :write_capacity => 1
end
Could anybody help?
Cheers,
Emmanuel

undefined method `yaml' for nil:NilClass when trying to save duplicated object

I have an Active Record model object called Event, which has many event_things. I want to be able to duplicate the event, so that it gets a new id. I'm using Rails 3.2 and in rails console am able to successfully call
event_copy = event.dup
event_copy.save
However, I also want to duplicate each of the Event's event_things.
copy = event_thing.dup
copy.event_id = event_copy.id
copy.save
But that gives me this error stack:
NoMethodError: undefined method `yaml' for nil:NilClass
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych.rb:204:in `dump_stream'
from /Users/Ed/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/psych/core_ext.rb:35:in `psych_y'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:143:in `attribute_change'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `block in changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `map'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.6/lib/active_model/dirty.rb:117:in `changes'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/attribute_methods/dirty.rb:23:in `save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block (2 levels) in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:295:in `block in with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/connection_adapters/abstract/database_statements.rb:192:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:208:in `transaction'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:241:in `block in save'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:252:in `rollback_active_record_state!'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.6/lib/active_record/transactions.rb:240:in `save'
from (irb):18
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from /Users/Ed/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
I ran into the same issue as this. It turns out that there's a Kernel.y extension method that is getting in your way, based on this article. Here is what I did to fix my problem:
class Event < ActiveRecord::Base
# alias the attributes
alias_attribute :x_pos, :x
alias_attribute :y_pos, :y
after_initialize :init
# after_initialize will still work, with the aliases
def init
self.x_pos ||= 0
self.y_pos ||= 0
end
# override Kernel.y
def y; end
# override self.y_pos to read out of the :attributes, since we blew away :y
def y_pos
attribute['y']
end
end
After doing this, I was finally able to use my model without having to rename the y database column.
While I normally don't advocate using gems liberally, if you have a lot of relations that need to be preserved in the duplication, or find yourself doing these manual duplications a lot, take a look at deep_clonable.
As for your specific error, try surrounding each line of code with a nil check (one line at a time). I'm sure there's just some case where you're ending up with a nil object that you're overlooking.

Resources