Skip to main content
Posts by:

Tim Booher

Render CSV in Rails

First I read the docs at: rubydoc.info to understand how FasterCSV is now in the ruby standard library.

Then, I set up the following code:

https://gist.github.com/tbbooher/1700200

This gives me a pretty flexible solution to render csv, but I’m really interested to see if this is a good way to go. Your comments are appreciated.

By 0 Comments

Radar parameter estimation

[mathjax]

Here we tackle what a Radar needs to accurately measure a target’s position, size and motion. (This is nothing new, just a placeholder for some of my notes.)

First of all, everything depends on $SNR$, and the parameter estimation happens in the main computer of a Radar. The theoretical rms error of a measurement is of the form:

<br /> \delta M = \frac{k M}{\sqrt{SNR}}<br />

where \(k\) is a constant between 0.5 and 1.

h3. Range

First, let’s tackle range. They key metric for range is bandwidth, the higher the bandwidth the better the resolution.

Estimation of the range of a target is based upon using A/D sampled measurements of the round trip time to and the target

<br /> R = \frac{c T_R}{2}<br />

For time delay measurements , such as range, the value of the constant depends on the shape of the radar pulse’s spectrum and the pulse’s rise time and for a rectangular pulse, whose width is, (T):

<br /> \delta T = \frac{T}{2 \sqrt{SNR}}<br />

or equivalently,

<br /> \delta R = \frac{c T}{2 \sqrt{SNR}}<br />

However, pulses always move in trains or if $T_D$ is the dwell time:

<br /> \delta R = \frac{c , T}{2, \sqrt{SNR\, \text{PRF} \, T_D}}<br />

from Barton and Ward.

So Range depends on \(SNR\), pulse shape and width, effective bandwidth, number of pulses that can be coherently integrated.

This is explained well by a diagram in the lincoln presentation:

h3. Angle

Now, let’s tackle angle. Angle accuracy depends on antenna size. Simple detection provides coarse location in angle by isolating a target’s location within beamwidth of antenna (and beamwidth is just \(\lambda / D \), where \(D\) is the aperture diameter and \(\lambda \) is the wavelength. But this is very coarse, 1° beam at 100 km extends across 1,745 meters. In order to provide more accurate angle estimation, you have to measure at different beam positions to improve accuracy. You can do this through sequential lobing, conical scan tracking, or monopulse angle estimation.

h4. Conical Scanning

Conical scanning is a technique to keep the beam pointed at the target to improve angle accuracy. It is based on the principle that the radar receiver will get maximum returned signal strength when the target is in the beam centre, so if the beam is pointed directly at the target, when the target moves it will move out of the beam center and the received signal strength will fall. Circuitry designed to monitor any fall off in received signal strength controls a servo motor that steers the aerial to follow the target motion.

Wikipedia has a nice drawing that explains this technique:

!https://upload.wikimedia.org/wikipedia/commons/3/32/Conical_scan.jpg!

h4. Sequential lobing

While conical scan tracking uses the phase of modulation to get the angle error and amplitude modulation to get the beam displacement, sequential lobing uses two slightly separated antenna elements to send the beam slightly to either side of the midline of the antenna, switching between the two to find which one gave the stronger return, thereby indicating which direction the antenna should be moved in order to point directly at the target.

Here, wikipedia provides another good diagram:

!https://upload.wikimedia.org/wikipedia/commons/b/b6/Monopulseprinzip2.gif!

h4. Monopulse

Monopulse radars are similar in general construction to conical scanning systems, but add one more feature. Instead of broadcasting the signal out of the antenna “as is”, they split the beam into parts and then send the two signals out of the antenna in slightly different directions. When the reflected signals are received they are amplified separately and compared to each other, indicating which direction has a stronger return, and thus the general direction of the target relative to the boresight. While monopulse, requires a separate receiver for each channel, it improves performance over conical scan and sequential lobing whose performance degrade with time varying radar returns.

All angle errors are summed up well by the following:

and

SNR, type of measurement technique, antenna illumination distribution, antenna size, and frequency.

h3. Doppler

Lastly, let’s look at Doppler accuracy. Doppler accuracy depends on coherent integration time \(\Delta t \):

Doppler frequency is calculated as:

<br /> f_d = \frac{2 v_r}{\lambda}<br />

To accurately measure Doppler, use two closely spaced frequency filters offset from the center frequency of the Doppler filter containing the detection

<br /> \text{Doppler measurement accuracy} \propto \frac{\lambda}{\Delta t} \frac{1}{\sqrt{SNR}}<br />

Doppler accuracy depends on SNR, pulse shape, integration time.

h3. Real world limitations

h4. Receiver noise

# Adds variance to estimates

h4. Radar calibration

# Poor calibration leads to poor estimation

h4. Amplitude fluctuations

# Small effect on monopulse and array solutions

h4. Angle noise (angle scintillations, or target glint)

# Complex target return biases angle estimate

h4. Multipath (low angle tracking)

# Reflection off earth’s surface combines with direct path return

# Can cause biases in angle estimates for all technique

h4. Good References

“Parameter Estimation”:http://www.ll.mit.edu/workshops/education/videocourses/introradar/lecture9/lecture.pdf

“Basic Fundamentals”:http://faculty.nps.edu/jenn/Seminars/RadarFundamentals.pdf

“Parameter Estimation and Tracking”:http://aess.cs.unh.edu/Radar{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}202010{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}20PDFs/Radar{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}202009{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}20A_15{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}20Parameter{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}20Estimation{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}20and{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}20Tracking{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}20Part{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}201.pdf

By 0 Comments

Wind speed calculation

I want to know the impact of wind on endurance.

So we have something like this:

This gives us 8 cases of wind direction:

From this we can infer that going to the center from one of the 8 directions.

So an overall flight path would look like this:

If each grid cell is a distance (s) in size, each time a diagonal transition is made the distance would be (sqrt{2} s). As an aircraft enters each cell, they encounter the wind-star as shown above with the expected value of the wind facing one of the eight possible directions. In general, if (W) is the wind velocity in direction (alpha), from grid direction (g in [1,8]) we have to find the expected value for the wind in direction (cos(alpha_{g,w})), by integrating over all values of (w).

[
V_{g,w} = sum_{1..12} cos(alpha_{g,w_{i}}) dot P_i
]

With these bins:

h3. Wind Directions ( w_{i} )
|Wind Direction|Angle|
|1|0|
|2|30|
|3|60|
|4|90|
|5|120|
|6|150|
|7|180|
|8|210|
|9|240|
|10|270|
|11|300|
|12|330|

h3. Grid Direction (g)
|Grid Direction||
|1|315|
|2|270|
|3|225|
|4|0|
|5|180|
|6|45|
|7|90|
|8|135|

By 0 Comments

Buyback military years

h2. Should I even buy the years? what if we use the 13K for something really special? the cashflow is way out there.

1 36 7836.4409
2 37 8692.4214
3 38 9592.7079
4 39 10539.1884
5 40 11533.8243
6 41 12578.6531
7 42 13675.7911
8 43 14827.4367
9 44 16035.8728
10 45 17303.4704
11 46 18632.6915
12 47 20026.0928
13 48 21486.3287
14 49 23016.1553
15 50 24618.4338
16 51 26296.1345
17 52 28052.3406
18 53 29890.2526
19 54 31813.1921
20 55 33824.6069
21 56 35928.0746
22 57 38127.3083
23 58 40426.1607
24 59 42828.6297
25 60 45338.8632
26 61 47961.165
27 62 50700
28 63 53560
29 64 56545.97
30 65 59662.89

If you’ve spent time in on active duty with an honorable discharge (i.e. you have a DD-214) and you then join the civil service, it is possible to pay for your military years and receive credit for FERS.

Questions:
* What are the various deadlines?

There is a two-year interest free period that begins on your date of hire. However, since the interest is added on an annual basis, if the deposit amount is paid in full prior to three years of your hire date the deposit is interest.

* Can I collect my civilian and reserve retirements? (Retirement: You must waive your military retired pay in order to receive credit for military service in a civilian annuity, unless your military retirement is based on)
*

employee. The deposit can be made in one single payment, multiple payments, or through payroll deductions, normally for as little as $25-$50

There are two reasons to do this:
* You could retire sooner, or
* Your can increase your retirement annuity

Here are the rules:
* The deposit must be paid in full while you are a federal employee
* that you must have at least five years of creditable civilian service and be covered under the CSRS or FERS retirement system on the date of retirement

All the details are here: “http://www.opm.gov/retire/pre/fers/servicecredit.asp”:http://www.opm.gov/retire/pre/fers/servicecredit.asp

Here is the math. The deposit amount is 3{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4} of military base pay for FERS employees.

There are three steps to make this happen:

Obtain your total estimated military earnings by sending form RI20-97 and a copy of your DD214 to your respective military pay representative. The military payroll office will send you a short letter or form indicating your total estimated earnings during your military service.

Complete a SF-3108 or SF-2803 This form requires a statement on the form concerning military deposits, which is not available on the on-line version. Obtain the edited form from your HR office. HR will forward the documents to your civilian payroll office. Your payroll office will bill you directly.

Make the deposit to your civilian payroll office. You can pay the deposit in one lump sum, a series of payments, or sign up for payroll deductions, normally for as little as $50 per pay period. The deposit must be paid in full while you are employed and cannot be made after you retire.
Step 4: When the deposit is complete, your payroll office will send you a letter that the deposit is paid in full. Keep this document for your permanent retirement records and send a copy to your HR office. Payroll will not usually notify your HR office of the deposit, so it is very important that you retain a copy of this letter until you

classdef PaymentPlanner  0
               obj.year_of_departure = 2011 + years_from_now;
            end
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           how many years are we looking at total?
            obj.n                       = PaymentPlanner.years_out+1;
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           which years are we looking at?
            obj.years                   = (2011:(2011+PaymentPlanner.years_out))';
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           what are the years of the experiment?
            obj.tv_each_year            = obj.years;
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           what age are you each year?
            obj.tv_age                  = obj.years-(ones(obj.n,1)*1976);
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           what is your age when you leave service?
            obj.year_of_62              = obj.years(obj.tv_age == 62);
            obj.age_at_departure        = obj.year_of_departure-obj.birthday(1);
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           what is the inflation-adjusted salary in each year?
            obj.tv_salary               = obj.increase_with_inflation(obj.starting_salary)';
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           what is the inflation-adjusted salary at exit
            obj.departing_salary_TY     = obj.tv_salary(obj.years == obj.year_of_departure);
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           how much cash on hand each year?
            obj.tv_cash_on_hand_TY      = obj.increase_with_inflation(obj.amt_years_buyback)';
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           how many years in federal service?
            obj.total_time_in_service   = obj.year_of_departure - PaymentPlanner.year_started_service;
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           how much cash would the government return?
            obj.payout                  = calculate_payout(obj);
{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}           what is the yearly payment available in 2011 dollars?
            obj.yearly_payment_BY       = obj.present_value(obj.get_retirement_BY, obj.year_of_62 - obj.year_of_departure);
        end

        function compare_30_year_coa(obj)
           for i = 1:30
               obj.year_of_departure = 2011 + i;
               obj.age_at_departure  = obj.year_of_departure-obj.birthday(1);
               obj.total_time_in_service   = obj.year_of_departure - PaymentPlanner.year_started_service;
               obj.yearly_payment_BY       = obj.present_value(obj.get_retirement_BY, obj.year_of_62 - obj.year_of_departure);
               disp([num2str(i) '|' num2str(obj.age_at_departure) '|' num2str(obj.yearly_payment_BY)]);
               A(i) = obj.yearly_payment_BY;
           end
           plot(1:30,A);
        end

        function out = present_value(obj, x, years)
            out = x/((1+obj.inflation_rate)^years);
        end

        function out = increase_with_inflation(obj,x)
            out = x*((1+obj.inflation_rate).^(1:obj.n));
        end

        function display_output(obj)
            disp(['At age ' num2str(obj.age_at_departure) ' you would depart with a base year salary of ' num2str(obj.starting_salary) ]);
            disp(['You would get ' num2str(obj.yearly_payment_BY) ' (BY11) going forward at age 62.']);
        end

        function payout = calculate_payout(obj)
            idx                         = find(obj.tv_age == 62);
            count_to_the_top            = length(obj.tv_payout_TY(idx:end));
            retirement_starting_salary  = obj.get_retirement_TY;
            obj.tv_payout_TY(idx:end)   = retirement_starting_salary*(1+obj.inflation_rate).^(1:count_to_the_top);
            payout                      = sum(obj.tv_payout_TY);
        end

        function yearly_payment = get_retirement_TY(obj)
            yearly_payment      = (obj.total_time_in_service/100)*obj.departing_salary_TY;
        end

        function yearly_payment = get_retirement_BY(obj)
            yearly_payment      = (obj.total_time_in_service/100)*obj.starting_salary;
        end

        function obj = value_at_age_62(obj)

        end
    end

end

h2. What are the steps?

Do I fall under: Uniformed Services Employment and Reemployment Rights Act (USERRA)?
No because no civilian service was interrupted.
How much do I pay?
For periods of service performed during 1999 the deposit equals 3.25{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}; and during 2000 the deposit equals 3.40{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}. After 31 Dec 00 the deposit returns to 3{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4} of your military base pay.
For periods of service performed during 1999 the deposit equals 3.25{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}; and during 2000 the deposit equals 3.40{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4}. After 31 Dec 00 the deposit returns to 3{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4} of your military base pay.
So, for example, I joined in 07/04/1999 and departed in 08/05/2009
What is the process

By 0 Comments

Resource Allocation with Approximate Dynamic Programming

[
E = frac{eta}{c}left( frac{C_L^{3/2}}{C_D} right) sqrt{2 rho S} left( frac{1}{W_f} – frac{1}{W_i} right)
]

Where (eta) is the propeller efficiency, (c) is the minimum power specific fuel consumption rate, maximum density of air, ( rho ).

By 0 Comments

Winds around the world

Goal: characterize the winds available around the world.

First we need to construct our grid:

The horizontal, latitude-longitude grid ranges from +70 to -70 deg in latitude and from 0 to 357.5E deg in longitude, producing a grid that has dimensions of 57 x 144 points.

In matlab, this is:

[cells/degree northern_latitude_limit western_longitude_limit]
zerom(

These data were produced from the “NCEP/NCAR Reanalysis”:http://www.esrl.noaa.gov/psd/data/reanalysis/reanalysis.shtml are available at six-hour intervals, from January 1, 1948 to the present, and it is this 6-hour data that was used as the basis for this work.

Spatially, the delivered data values are given at points in a three-dimensional, global system using a 2.5 x 2.5 deg grid of latitude-longitude and altitudes that are specified by atmospheric pressure.

Above each point in this grid, horizontal wind information is delivered at 4 pressure levels: 50 mb, 70 mb, 100 mb, and 150 mb. If we assume a standard day, this corresponds to: 67,726 60,504 53,083 44,647 feet. At each grid point and pressure altitude, the horizontal wind vectors have been sorted into 12 directional bins.

Cells per degree = 2.5
Degrees per cell = 0.4

– how linear is the wind change with altitude?
– where are winds high?

By 0 Comments

How do you deploy an application.yml based config to heroku

In one of my applications, I have the following config files that are excluded from git:

* config/mongoid.yml
* config/application.yml
* config/mailserver_setting.rb
* config/omniauth_settings.rb

For deploying to a regular server, I just add tasks to my capistrano deployment file to create sym-links to a shared directory. In this case I have to modify my application to use local ENV files and consequently the ENV hash in my rails app.

In my configuration.rb (boots at initialization):

config_file =  File.expand_path('../../config/application.yml', __FILE__)
if File.exist?(config_file)
  APPLICATION_CONFIG=YAML.load_file(config_file)[Rails.env]['application']
  CONSTANTS=YAML.load_file(config_file)[Rails.env]['constants']
  APPLICATION_CONFIG.each{|k,v| ENV["APPLICATION_CONFIG_#{k}"] = v.to_s }
  CONSTANTS.each{|k,v| ENV["CONSTANTS_#{k}"] = v.to_s}
end

So using the following custom thor task, I can load heroku’s env files based on some code from Les Hill:

This works well.

By 0 Comments

Attic

If you walk up our attic steps, you will be surrounded by this:

The problem is that it takes forever to find and store things, so we don’t store them there or we buy duplicates of things we already have. I am often prevented from getting things done because I want them done perfectly. However, this problem is sufficiently annoying and I have sufficiently small time that I am ready to fix this without custom carpentry and custom angled storage bins on castors and wheels to provide easy access to everything — on top of a full database of our home inventory. Ah, someday.

So our attic and our stuff in general is not serving us. Yes, we need to get rid of the stuff we don’t need, made easy(ier) by the fact that our kid production line is closed. If we put something up there then it is not down here because we need it seasonally (think Christmas tree) or occasional (think my mitre saw). Given the nature of what will be up there, our effort is guided by the following principles (by priority):

  • Cheap and Easy (we want absolute minimal time and energy spent on this, roughly three diaper change intervals is all we can spare — yes, that has a huge standard dev)
  • Speed, Easy access to everything (so we don’t have to move more than one box to see what we are looking for)
  • Transparency, we can get to what we need easily (so we will have a map of where things go)
  • Center Isle Clear, no items in the “hallway” (that is our downfall now, items in the central area block us from finding things)
  • Flexibility (when we get in hurry, we have to put things up quickly, so we don’t want to over-optimize)
  • Minimalism (Let’s not put it up there if we don’t have 90{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4} chance of using it in a year, can’t buy it, or have a long term vision for it)

Regarding the last principal, we’ve developed a proviso for sentimental stuff. We have one bin for each of us and call it our sentimental warehouse, everything else has to have a non-sentimental purpose. With these principles understood, we have every incentive to put stuff up there because we have a smaller house for 6 folks (200 ft^2 per person) so we have to use our space wisely. We have a small garage that serves as a mud, play and sports room, so I put as much of our tools, paint, etc up in the attic and this has to be easy to access. We also believe in a bare bones accesible toy inventory, so we rotate toys up there frequently, aside from the fact that one kid is always graduating to a new set of toys.

Despite the fact that I have to get my taxes done this weekend (slacker! or is it workaholic?), the colder weather reminded me the small window of attic access is coming. Plus, we need to move things around up there for some upcoming electrical work. So I took some measurements, and played around in Sketchup and found that the key issue was how to make the sides useful and easily accessible. For example, the entire floor width was approximately 29 feet, but only 18 feet had a usable floor, meaning that I was ignoring roughly 40{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4} of the total floor space. This 40{aaa01f1184b23bc5204459599a780c2efd1a71f819cd2b338cab4b7a2f8e97d4} was the most important to use for storage since it is out of the center aisle. If I just incorporate this area, I calculated that I would gain roughly 25 ft^2 of surface area, multipled by the linear feet available which is 80 feet — meaning we would have 75 cubic yards, exactly half of a semi truck’s transportation volume — that is a lot of space, if I could only harness it inline with our principles.

With two hours, I did some SketchUp, looked around online at some ideas, my results are below. Now, back to taxes. Can I be greedy, and hope wiser friends can give me some feedback on this plan?

All feedback is welcome, but here are the things I want to do, but can’t:

  • Full inventory of everything up there, location tag everything and put on our intranet
  • Custom drawers and storage containers
  • Analysis on how supported my shelving needs to be (I have a degree in structures, I would love to use it someday.)
  • Optimization of where things are placed

Particular things I don’t know:
* Where to get storage containers as cost efficient as possible
* Attic ventilation constraints (building science considerations)
* Whether it makes sense to use the 10 inches in the joists. I don’t think so, because of the height of any box will prevent using that area.
* Any systems that are inexpensive, but will save me lots of time
* If installing lighting back there makes sense

Links
* “rubbermaid”:http://www.rubbermaid.com/Category/Pages/ProductDetail.aspx?CatName=Storage&SubcatId=CleverStore&Prod_ID=RP091401
* “wheeled idea”:http://www.curbly.com/lgsal/posts/1562-how-to-safely-store-things-in-the-attic
* “what i really want to do”:http://img2.timeinc.net/toh/i/g/09/interiors/06-before-after/06-attic.jpg
* “good idea”:http://www.betterimprovement.com/wp-content/uploads/2007/11/the-infinite-attic-storage-system.jpg

h3. Conclusion

and eventually:

I couldn’t resist the cheap and easy method to buy ready-made shelves and just put them up there. For roughly $200, I got everything off the floor. It was an excellent suggestion. Thanks Matt Markel for the shelving idea. Spirit, thank you for the organization idea. I’ve fully incorporated your ideas.

At some point in life, I have to choose simplicity over fun. That point arrives when four kids arrive.

By 0 Comments

Mongoid counter_cache with has_and_belongs_to_many

If I have two Mongoid models joined by a has_and_belongs_to_many relationship, Users and Groups. I need to quickly and efficiently sort by the most popular groups which really should be done with a counter_cache. However, counter_caches are implemented in rails by setting a callback to update the counter cache every time a child model is created/destroyed. But, Mongoid does not present callbacks for HABTM, and there are no real records that are getting created anyway. Additionally, you can add a whole collection of associations at once which would not be compatible with the efficient Mongoid inc operator. There is a mongoid_counter_cache gem that I played with for awhile, but for these reasons, I couldn’t get it to work with my existing schema, so I had to roll my own solution to this.

To complicate things, a user can follow a group or join a group. Following a group just keeps them informed on what the group is doing, joining allows them to participate. To make all this work, I have the following associations defined:

bc.
include Mongoid::Document
field :name, :type => String
field :type, :type => Symbol, :default => :custom
field :description, :type => String
index :name
index :type
field :follower_count
field :member_count

belongs_to :owner, :class_name => “User”, :inverse_of => :custom_groups

has_and_belongs_to_many :members, :class_name => “User”, :inverse_of => :joined_groups
has_and_belongs_to_many :followers, :class_name => “User”, :inverse_of => :followed_groups

And for the user:

bc.
has_and_belongs_to_many :joined_groups, :class_name => “PolcoGroup”, :inverse_of => :members
has_and_belongs_to_many :followed_groups, :class_name => “PolcoGroup”, :inverse_of => :followers

I’m sticking with the _count naming convention in case, I get some performance boost when calling parent.children.size which will read the cached value instead of actually querying the database. The column type is integer and we also pass a :default => 0.

Since I can’t use Mongoid’s atomic update here, I’m going to go through the database and update the relevant field with the current count.

bq.
after_save :update_categories_counter_cache
def update_categories_counter_cache
self.categories.each { |c| c.update_count(self) } unless self.categories.empty?
end

What does all this mean? We are adding an after_save callback method called update_categories_counter_cache. This metod is triggered after the record is saved, and it loops through all categories (if self.categories array is not empty, that is) and calls update_count method for each of them. The update_count is defined in Category model file (well, not yet, but you will define it now). The reason for the loop is that you might have multiple assignments on one save, so we make sure all categories that the post belongs to are updated.

Let’s define the update_count method for the Category model. Open category.rb and add the follwing:

def update_count
update_attribute(:posts_count, self.posts.length)
end

By 0 Comments

Official Modes of Travel for the US Department of Defense

This one should be simple, but it is not. I just wanted to know what to put on an Air Force form 938 for “MODE OF TRAVEL”. This wasn’t easy.

In the JFTR, https://www.defensetravel.dod.mil/Docs/Training/DTA_App_C.pdf

Appendix K,
Table K-3 associates each travel mode with its description, expense category,
and single threshold.

TRAVEL MODES AND OTHER TRANSPORTATION TYPES

OTHER TRANSPORTATION TYPE MODE DESCRIPTION EXPENSE CATE SINGLE THRESH
Comm Bus CB Bus Fare COM. CARR.-I 500
CTO Fee (Central Bill) CF-C CTO FEE (GOVCC-C) COM. CARR.-C 150
CTO Fee (Indiv Bill) CF CTO FEE (GOVCC-I) COM. CARR.-I 150
Comm Air (Indiv Bill) CP Air Fare (GOVCC-I) COM. CARR.-I 1500
Comm Air (Central Bill) CP-C Air Fare (GOVCC-C) COM. CARR.-C 1500
Comm Rail (Indiv Bill) CR Train Fare (GOVCC-I) COM. CARR.-I 300
Comm Rail (Central Bill) CR-C Train Fare (GOVCC-C) COM. CARR.-C 300
CV Ship Fare COM. CARR.-C 300
DGV POC Use-Gov Vehicle Available MILEAGE 0
GA Government Auto TRANSPORT 0
GB Government Bus TRANSPORT 0
GP Government Plane COM. CARR.-G 0
GV Government Vessel TRANSPORT 0
GVA POC Use-Dedi-cated Gov Vehicle MILEAGE 0
PA Pvt Auto-TDY/TAD MILEAGE 500
PAL Pvt Auto-Local MILEAGE 200
PAS Passenger (No Claim) TRANSPORT 0
PAT Pvt Auto-Terminal MILEAGE 50
PM Private Motorcycle MILEAGE 500
PP Private Plane MILEAGE 500
PV Private Vessel TRANSPORT 500
TB Prepaid Bus COM. CARR.-T 0
TP Prepaid Plane COM. CARR.-T 0
TR Prepaid Rail COM. CARR.-T 0
TV Prepaid Vessel COM. CARR.-T 0
CA Commercial Auto RENTAL CAR 500
By 0 Comments