ActiveSupport::Notifications.subscribe('sql.active_record') do |_, _, _, _, details|
if details[:sql] =~ /UPDATE "answers" SET position =/
puts '*' * 50
puts caller.join("\n")
puts '*' * 50
end
end
And then looked at the call stack to see where it was coming from. I could have output to the logger too. And I would not recommend doing this on Production.
Showing posts with label Rails. Show all posts
Showing posts with label Rails. Show all posts
Thursday, July 16, 2015
How to discover what is generating an SQL statement in your Rails log
Just spreading a really cool tip I came across. Ryan Bigg has this blog post showing how you can find out what is creating an SQL statement in your log. I was having a devil of a time figuring out where a particular callback was coming from and discovered his great post.
Essentially you hook into ActiveSupport::Notifications and then put in logic in the regex piece to describe the query you are looking for. In this case I did this in development.rb:
Wednesday, May 7, 2014
Testing a Rails/Ember app with Teaspoon & QUnit and watching the tests run
Recently I have had to start working with an Ember application. It is certainly a challenge. For Unit testing we decided to look at QUnit for our front end pieces. Being used to:
save_and_open_page
and looking at tests running visually I was a bit stymied until I realized you could use the `-d` flag to override the phantom.js we set up in the config. So:
teaspoon -d selenium
will run the tests with Firefox & Selenium (normal version issues apply)
Wednesday, February 26, 2014
Using table_for with HTML elements in Active Admin
Ah yes another foray into ActiveAdmin. Recently I needed to use the table_for feature on a show page and add some html options to it. This required looking into the code itself as the documentation was not exactly clear in either ActiveAdmin or Arbre.
Essentially you need to do something like this:
table_for agent.quotes, {:id => 'agent_quotes'} do
column 'Quote Number' do |quote|
quote.slug
end
column 'Business' do |quote|
quote.business.name
end
column 'Status' do |quote|
quote.state
end
column '' do |quote|
link_to 'View Quote', admin_quote_path(quote.id)
end
end
It was as simple as adding a hash with the needed items after the collection for the table_for:
table_for collection, {:id => 'html_id', :class => 'html_class'}
Tuesday, July 9, 2013
Uploading CSV files to a Rails Application using ActiveAdmin
Recently I had try and upload CSV files to a rails application via Active Admin. I had the inkling that maybe I was not the first to have done this. A short google search later and I was lead to this answer on Stack Overflow
I loved it except for the processing class listed under csv_db. It seemed too limiting in that it requires EVERY column to be there whether data is present or not. I recalled a Railscast that offered up a much more flexible solution and created this:
If you replace the code from the Stackoverflow post in csv_db with this you should be able to load any number of columns you wish. As soon as I figure out the updating of existing records I will post a follow-up.
I loved it except for the processing class listed under csv_db. It seemed too limiting in that it requires EVERY column to be there whether data is present or not. I recalled a Railscast that offered up a much more flexible solution and created this:
require 'csv'
class CsvDb
class << self
def convert_save(model_name, csv_data)
begin
target_model = model_name.classify.constantize
CSV.foreach(csv_data.path, :headers => true) do |row|
target_model.create(row.to_hash)
end
rescue Exception => e
Rails.logger.error e.message
Rails.logger.error e.backtrace.join("\n")
end
end
end
end
If you replace the code from the Stackoverflow post in csv_db with this you should be able to load any number of columns you wish. As soon as I figure out the updating of existing records I will post a follow-up.
Sunday, April 28, 2013
Flay, a gem to help improve the maintainability of your code
Recently I read a post where the author listed the must have gems for rails development. Being an avid watcher of Railscasts I knew many of them however one, flay, caught my attention. It comes out of the Seattle Ruby group which also brought us flog.
Flay is along the same lines as Flog; it analyzes your code looking for issues. Rather than looking for tortured code though it is looking for similar or duplicate code blocks. You install with `gem install flay` and then run it against your files, e.g.:
flay ./app/models/*.rb
A report is generated of the suspect areas like this:
macscott:test-project scottshea$ flay ./app/models/*.rb
Total score (lower is better) = 1666
1) Similar code found in :call (mass = 170)
./app/models/level.rb:8
./app/models/level.rb:9
./app/models/level.rb:10
./app/models/level.rb:11
./app/models/level.rb:15
./app/models/level.rb:17
./app/models/level.rb:19
./app/models/level.rb:20
./app/models/level.rb:22
./app/models/level.rb:23
2) Similar code found in :defs (mass = 154)
./app/models/item_step.rb:260
./app/models/response.rb:195
3) Similar code found in :defs (mass = 138)
./app/models/feedback.rb:62
./app/models/hint.rb:54
./app/models/subtitle.rb:51
4) Similar code found in :call (mass = 136)
./app/models/level.rb:12
./app/models/level.rb:13
./app/models/level.rb:14
./app/models/level.rb:16
./app/models/level.rb:18
./app/models/level.rb:21
./app/models/level.rb:24
./app/models/level.rb:25
5) IDENTICAL code found in :defn (mass*2 = 128)
./app/models/report_generator.rb:7
./app/models/summary_report_generator.rb:7
6) IDENTICAL code found in :defn (mass*2 = 120)
./app/models/image.rb:17
./app/models/sharded_image.rb:23
[truncated]
The total app score of 1666 can be viewed in its individual components showing areas that provide the most bang for the buck. For experienced developers operating on their own or in a small team Flay may be unnecessary. However, on larger projects (as the one I ran it on) or those with beginner or intermediate programmers it can help increase the maintainability of your codebase.
I am not sure where the 1666 would rank on the overall chart (is that really bad? representative?) but the 'lower is better' advice holds true. This Stackoverflow question offers some interpretation of the score but really the best advice is "don't let it get higher!"
Saturday, April 20, 2013
Using Sidekiq with Faye to notify client web pages and applications of updates
Recently I was given a small coding challenge of how I would update sites & client applicaitons with notifications of content being released. My mind immediately flew to the faye gem. However, this would be a serious block if my app had to halt everything to send out the notification to a bunch of browsers.
So, I added in Sidekiq. In the Content Model I put this to call out to Sidekiq:
/config/initializers/faye_configuration.rb):
def self.release_next
ContentWorker.perform_async
end
The ContentWorker then looks like this:
class ContentWorker
include Sidekiq::Worker
sidekiq_options queue: "content"
def perform
next_release = Content.next_release(Content.last_release)
# puts the data into JSON format; for actual content it could encode a url that is then loaded
vars = ["title" => next_release.title,
"site" => next_release.site,
"released_at" => next_release.released_at.strftime("%l:%M:%S %p %m-%d-%Y")].to_json
message = {:channel => "/releases", :data => vars, :ext => {:auth_token => FAYE_TOKEN}}
uri = URI.parse(FAYE_SUBSCRIPTION_PATH)
Net::HTTP.post_form(uri, :message => message.to_json)
next_release.update_attribute(:released_at, DateTime.now)
end
end
I created a designated queue in Sidekiq for the messages and then made the Faye channel creation configurable via an environment variable from an initializer file (FAYE_SUBSCRIPTION_PATH = "http://localhost:9292/faye"
The client then just listens in on the Faye channel and acts upon a message coming through. Here is the Javascript I wrote for listening to the Channel and adding the new release to the top of the view table just below the headers:
$(function() {
var faye = new Faye.Client("http://192.168.0.12:9292/faye");
faye.subscribe("/releases", function(data) {
add_to_table(data);
});
});
function add_to_table(data){
var json_obj = jQuery.parseJSON(data);
var $content_table = $('#content_table');
if ($content_table.find('tr').length >= 10 ) {
$content_table.find("tr:last").remove();
}
$("#header").after("<tr><td>" + json_obj[0].title+ "</td><td>" + json_obj[0].site + "</td><td>" + json_obj[0].released_at + "</td></tr>");
}
All in all a nice little challenge. I have not had a chance to try it out beyond my home network yet so I am not sure how performant the solution would be.
Railscasts used for this:
Faye
Sidekiq
Thursday, March 14, 2013
Errors building Nokogiri on Lion/Mountain Lion
I kept getting an odd error with Nokogiri on my new Macbook:
WARNING: Nokogiri was built against LibXML version 2.9.0, but has dynamically loaded 2.7.8
With help from this post I was able to resolve the issue. It seems that "This happens because the Lion system default libxml2 (loaded at bootstrap) is used, regardless of which libxml2 Nokogiri was built against". No real original work on my part here other than a Google search. However I wanted to spread the effort of Michele Gerarduzzi a litte further and give credit where credit is due.
The relevant post: Get rid of Nokogiri LibXML warning on OSX Lion
WARNING: Nokogiri was built against LibXML version 2.9.0, but has dynamically loaded 2.7.8
With help from this post I was able to resolve the issue. It seems that "This happens because the Lion system default libxml2 (loaded at bootstrap) is used, regardless of which libxml2 Nokogiri was built against". No real original work on my part here other than a Google search. However I wanted to spread the effort of Michele Gerarduzzi a litte further and give credit where credit is due.
The relevant post: Get rid of Nokogiri LibXML warning on OSX Lion
Thursday, February 14, 2013
Heroku with Unicorn backlog settings and performance
In light of this post from Rap Genius and subsequent blow up on Hacker News I decided to share what we did to play with the request queue on Unicorn & Heroku.
In the app/config/unicorn.rb we changed the backlog line to this:
And then we can alter the backlog as necessary via:
We found 25 to be a sweet spot for two Unicorn Workers but it may be different with four (which we are experimenting with now). Again this is also relative to the app so your results may (and probably will) be different.
Update:
I neglected to mention that you have to move the port declaration from config.ru and put it in the unicorn.rb too. The full line should be something like this:
In the app/config/unicorn.rb we changed the backlog line to this:
:backlog => Integer(ENV['UNICORN_BACKLOG'] || 200)
And then we can alter the backlog as necessary via:
heroku config:set UNICORN_BACKLOG=25 -a <app_name>
We found 25 to be a sweet spot for two Unicorn Workers but it may be different with four (which we are experimenting with now). Again this is also relative to the app so your results may (and probably will) be different.
Update:
I neglected to mention that you have to move the port declaration from config.ru and put it in the unicorn.rb too. The full line should be something like this:
listen ENV['PORT'], :backlog => Integer(ENV['UNICORN_BACKLOG'] || 200)
Tuesday, June 19, 2012
Current Rails Project
Currently I am working with a company that is upgrading their Rails 1.2.3 app to Rails 3.0.13. We decided not to tackle the asset pipeline in this go around.
In production their app resides on a Windows server hosted inside the clients walls and operates off of MS-SQL. I have it up and running on my Windows box at home while I work on an Ubuntu laptop. I am trying to make it as agnostic as possible so that should a client want the Rails app on a Linux server there is little to change. Who knows how successful this will be.
In production their app resides on a Windows server hosted inside the clients walls and operates off of MS-SQL. I have it up and running on my Windows box at home while I work on an Ubuntu laptop. I am trying to make it as agnostic as possible so that should a client want the Rails app on a Linux server there is little to change. Who knows how successful this will be.
Customary Introduction Post
The title of my blog comes from the fact that I have a cat who will sit on my lap staring at the screen while I try to write code. I am taking the stance that he wants to learn what I am doing rather than he is really saying "Srsly? You should read a best practices book."
I am a mid-range Ruby/Rails developer at this stage. Proficient in some areas, woefully lacking in others. Also, because I have only had one 'longish' term assignment I have had to hop around from Windows to Linux to Mac and from Rails 1.2.3 to 2.3.n to 3.n.
I find myself learning a lot of things... sometimes repeatedly... so I decided to start blogging about it as a way to take notes and possibly help someone else-- hopefully more than just providing a "don't do this!" example.
I am a mid-range Ruby/Rails developer at this stage. Proficient in some areas, woefully lacking in others. Also, because I have only had one 'longish' term assignment I have had to hop around from Windows to Linux to Mac and from Rails 1.2.3 to 2.3.n to 3.n.
I find myself learning a lot of things... sometimes repeatedly... so I decided to start blogging about it as a way to take notes and possibly help someone else-- hopefully more than just providing a "don't do this!" example.
Subscribe to:
Posts (Atom)