Came across and interesting problem. We decode a base64 string that is received as a parameter and decode it to work out where to build a new path. The problem here is that the extra characters \xDB\x9D\x00 shouldn’t be there and cause YAML to blow up
2.2.2 :017 > Base64.decode64('LS0tCi0gOnBvbHltb3JwaGljX3BhdGgKLSAhcnVieS9BY3RpdmVSZWNvcmQ6%250AUHJvamVjdAogIGF0dHJpYnV0ZXM6CiAgICBpZDogODAyNQo=%250A')
=> "---\n- :polymorphic_path\n- !ruby/ActiveRecord:\xDB\x9D\x00Project\n attributes:\n id: 8025\n"
2.2.2 :023 > YAML.load("---\n- :polymorphic_path\n- !ruby/ActiveRecord:\xDB\x9D\x00Project\n attributes:\n id: 8025\n")
Psych::SyntaxError: (<unknown>): control characters are not allowed at line 1 column 1
Somehow control characters are appearing in our Base64 string and we need to strip them. It just doesn’t seem as simple as
That’s much better and now YAML can decode this successfully.
It is at this stage I notice…. %250A in the Base64 string and at the end of the string. This represents a carriage return, that can happen in parameters easily enough, so I am decoding a carriage return and then stripping it from the string. I should just strip the carriage returns in the first place.
rails@snarf:/var/www/mini-epic/current$ sudo -u postgres createuser --interactive
Enter name of role to add: rails
Shall the new role be a superuser? (y/n) y
rails@snarf:/var/www/mini-epic/current$ RAILS_ENV=staging rake db:create
rails@snarf:/var/www/mini-epic/current$ psql epic_invite_staging < /tmp/mini-epic.pgsql
Interesting problem requiring us to remove the where values on an ActiveRecord::Relation. The original heavy handed method seems to play havoc with chained where calls and the id of the original proxy_association.owner would get used in a later where. Here we can see that our for_me method seems to cause the else_id to be the same as our recipient_id
[5] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_7::Nested_1>)> user.somethings.where(else_id: something.else_id).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`user_id` = 20323 AND `somethings`.`else_id` = 6465 ORDER BY id DESC"
[6] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_7::Nested_1>)> user.somethings.for_me.where(else_id: something.else_id).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`recipient_id` = 20323 AND `somethings`.`else_id` = 20323 ORDER BY id DESC
when in doubt read the Rails source
# remove user_id = proxy_association.owner.id from scope
# so it can be reapplied by to_me or for_me
def global_scope
- s = respond_to?(:scoped) ? scoped : all
- s.where_values = []
- s
+ unscope(where: :user_id)
end
which is the way that rewhere reassigns values in where rather than chaining again
2.2.2 :006 > Something.where(user_id: 1).where(user_id: 2).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`user_id` = 1 AND `somethings`.`user_id` = 2"
2.2.2 :007 > Something.where(user_id: 1).rewhere(user_id: 2).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`user_id` = 2"