I'm using a json field for storing some additional parameters in one of my models.
It works great except for the fact that it doesn't detect changes I make when accessing the data using square brackets:
2.1.1 :002 > p = Payments.last
=> {...}
2.1.1 :003 > p.params.keys
=> ["receipt_data"]
2.1.1 :004 > p.params['verification_data'] = 'test'
=> "test"
2.1.1 :005 > p.params.keys
=> ["receipt_data", "verification_data"]
2.1.1 :006 > p.params_changed?
=> false
2.1.1 :007 > p.save
(0.2ms) BEGIN
(0.2ms) COMMIT
=> true
2.1.1 :008 > Payment.last.params.keys
Payment Load (0.5ms) SELECT "payments".* FROM "payments" ORDER BY "payments"."id" DESC LIMIT 1
=> ["receipt_data"]
How do I force it to save the changes?
to force, before any update. you can say:
p = Payments.last
p.params_will_change!
p.params['verification_data'] = 'test'
p.save
Btw, ActiveRecord is supposed to handle dirty tracking automatically. so, if you can push an app on github which reproduces this issue, I can try to help.
Related
I have a Rails model class with a function to be executed at a later time, which is managed by Delayed::Job. Here is the function (simplified):
def fn_with_dj_delay
puts "puts output here"
do_somethting_else
end
handle_asynchronously :fn_with_dj_delay, :run_at => Proc.new { 24.hours.from_now }, :queue => 'my_queue'
When the function is called in my Rails test environment however, the delaying is being skipped. Is it possible for this to perform the same in both environments?
In rails c test the function fires immediately. Here is a slightly simplified and truncated console log:
2.3.1 :004 > x = MyClass.new
2.3.1 :005 > x.save!
2.3.1 :006 > x.fn_with_dj_delay
puts output here
=> #<Delayed::Backend::ActiveRecord::Job id: nil, priority: 0, attempts: 0 # ...
2.3.1 :007 > Delayed::Job.last
Delayed::Backend::ActiveRecord::Job Load (0.3ms) SELECT `delayed_jobs`.* # ...
=> nil
In rails c the function is automatically delayed as instructed. Again, a slightly simplified and truncated console log:
2.3.1 :004 > x = MyClass.new
2.3.1 :005 > x.save!
2.3.1 :006 > x.fn_with_dj_delay
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO `delayed_jobs` (`handler`, `run_at`, # ...
(0.5ms) COMMIT
=> true
2.3.1 :007 > Delayed::Job.last
Delayed::Backend::ActiveRecord::Job Load (2.2ms) SELECT `delayed_jobs`.* # ...
=> #<Delayed::Backend::ActiveRecord::Job id: 1, priority: 0, attempts: 0 # ...
The only clue I can see is the returned, uninstantiated Delayed::Backend::ActiveRecord::Job object in the test console when the function finishes. If there is something invalid about the object, I could understand this failure, though I would expect an error to be raised. Regardless, this is not at issue:
2.3.1 :004 > res = p.check_for_similar_web_data
puts output here
=> #<Delayed::Backend::ActiveRecord::Job id: nil, priority: 0, attempts: 0 # ...
2.3.1 :005 > res.valid?
=> true
2.3.1 :006 > res.save!
(0.1ms) BEGIN
SQL (0.4ms) INSERT INTO `delayed_jobs` (`handler`, `run_at` # ...
(0.5ms) COMMIT
=> true
This is so simple, I'm surprised and embarrassed I didn't find it before writing this up. I guess the default is false in the test environment?
2.3.1 :003 > Delayed::Worker.delay_jobs = true
2.3.1 :004 > x = MyClass.new
2.3.1 :005 > x.save!
2.3.1 :006 > x.fn_with_dj_delay
(0.2ms) BEGIN
SQL (0.4ms) INSERT INTO `delayed_jobs` (`handler`, `run_at`, # ...
(0.5ms) COMMIT
=> true
2.3.1 :007 > Delayed::Job.last
Delayed::Backend::ActiveRecord::Job Load (2.2ms) SELECT `delayed_jobs`.* # ...
=> #<Delayed::Backend::ActiveRecord::Job id: 1, priority: 0, attempts: 0 # ..
As seen (in reverse) here.
I try to convert Hash to JSON before viewing it on page, but can`t convert type of variable. Example in console (rails c):
2.1.5 :001 > #item = Item.find(2)
Item Load (1.6ms) SELECT "items".* FROM "items" WHERE "items"."id" = $1 LIMIT 1 [["id", 2]]
=> #<Item id: 2, nested_params: {"123"=>"123", "456"=>"456"}>
2.1.5 :003 > #item.nested_params.class
=> Hash
2.1.5 :004 > #item.nested_params = #item.nested_params.to_json
=> "{\"123\":\"123\",\"456\":\"456\"}"
2.1.5 :005 > #item.nested_params.class
=> Hash
2.1.5 :006 > #item.nested_params
=> {}
You can visit below link
http://www.rexfeng.com/blog/2012/12/convert-a-ruby-hash-into-valid-json/
I think you have to write require 'json'
When I open the console of an existing application and type in :
2.1.1 :001 > User.first
User Load (17.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
=> #<User id: xxxx .... >
typing the query next time :
2.1.1 :002 > User.first
User Load (0.8ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
=> #<User id: xxxx .... >
You can see the difference between the time taken by rails to query the database. Is something like caching available in console. How does this behave in running applications. Does it more time or even it is cached, where exactly does it do it.
The database server caches queries in the query cache.
See here for documentation on the mysql database query cache: https://dev.mysql.com/doc/refman/5.1/en/query-cache.html
ActiveRecord also performs query caching:
http://edgeguides.rubyonrails.org/caching_with_rails.html
Both of these may be happening depending on your system configuration.
If you're using rails 4, the database connection is not established straight away, until you make a query so:
2.1.1 :001 > User
=> User(no database connection)
2.1.1 :002 > User.first
User Load (28.8ms)
2.1.1 :003 > User.first
User Load (1.9ms)
2.1.1 :004 > User.last
User Load (2.8ms)
So the initial query is establishing a database connection. Those after are then using the cache (as mentioned in other answer) and already established connection.
I have a model called Content, with a column called dependencies, serialized as Hash:
class Content < ActiveRecord::Base
attr_accessible :dependencies
serialize :dependencies, Hash
end
This really killed my nerves for the last few hours. I'll appreciate any help/hint.
Questions:
What should be the default (empty) value in migration?
What should be the default (empty) value in FactoryGirl?
Most important - how to query in order to find empty values?
Thanks in advance!
What should be the default (empty) value in migration?
What should be the default (empty) value in FactoryGirl?
In both cases, the empty hash {}
Most important - how to query in order to find empty values?
Since serialized values are stored using YAML, you need to search as follows:
Content.where('dependencies = ?', {}.to_yaml)
Here's an irb transcription for my test of the above:
MacbookAir1:so1 palfvin$ rails c
Loading development environment (Rails 4.0.0)
2.0.0-p247 :001 > u = User.new(role: {})
=> #<User id: nil, role: {}, role2: nil>
2.0.0-p247 :002 > u.save
(0.3ms) begin transaction
SQL (3.3ms) INSERT INTO "users" ("role", "role2") VALUES (?, ?) [["role", "--- {}\n"], ["role2", nil]]
(1.1ms) commit transaction
=> true
2.0.0-p247 :003 > u.role
=> {}
2.0.0-p247 :004 > {}.to_yaml
=> "--- {}\n"
2.0.0-p247 :005 > u
=> #<User id: 4, role: {}, role2: nil>
2.0.0-p247 :006 > User.where(role: {}.to_yaml)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."role" = '--- {}
'
=> #<ActiveRecord::Relation [#<User id: 3, role: {}, role2: nil>, #<User id: 4, role: {}, role2: nil>]>
2.0.0-p247 :007 >
(Note: I had created a User instance (#3) prior to posting the first version of this answer, which is why that shows up in my where as well).
And here's my user.rb file:
class User < ActiveRecord::Base
has_many :who_rated_comment_rels, foreign_key: "user_id", dependent: :destroy
serialize :role, Hash
serialize :role2
end
You can ignore the stuff not-relevant to your case (i.e. anything other than role). I hack on this project for various StackOverflow purposes.
In $ rails console I noticed that multiple queries are being run when I save a record:
ruby-1.9.2-p180 :001 > ActiveRecord::Base.logger = Logger.new(STDOUT)
=> #<...>
ruby-1.9.2-p180 :002 > p = Project.first
Project Load (0.3ms) SELECT `projects`.* FROM `projects` LIMIT 1
=> #<Project id: 1, category_id: 1, qualified_at: "2011-12-14 15:06:29", ...>
ruby-1.9.2-p180 :003 > p.qualified_at = Time.now
=> 2011-12-14 10:11:42 -0500
ruby-1.9.2-p180 :004 > p.save
SQL (0.2ms) BEGIN
SQL (1.5ms) SHOW TABLES
AREL (0.3ms) UPDATE `projects` SET `qualified_at` = '2011-12-14 15:11:42', `updated_at` = '2011-12-14 15:11:47' WHERE `projects`.`id` = 1
Category Load (0.3ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 1 ORDER BY name LIMIT 1
ProjectPerson Load (0.4ms) SELECT `project_people`.* FROM `project_people` WHERE (`project_people`.project_id = 1 AND (project_people.is_client = 1)) LIMIT 1
Person Load (0.3ms) SELECT `people`.* FROM `people` WHERE (`people`.`id` = 2)
ProjectTag Load (0.4ms) SELECT DISTINCT `project_tags`.tag_id FROM `project_tags` WHERE (`project_tags`.project_id = 1)
SQL (0.5ms) COMMIT
=> true
I don't have before or after filters in my Project model, and I'm not using an Observer. Obviously these queries relate to associations of the Project model, but why are the queries being run? Not sure what else to consider. Thanks.
I just figured it out... I'm using the sunspot_rails gem and it was updating the index for that record :) These were associations that were referenced in my index definition.
I'll keep the question in case anyone else happens to come across a similar problem.