At the Forge - Fixtures and Factories
Listing 1. Model Files, with Associations and Validations
class Person < ActiveRecord::Base
has_many :meeting_people
has_many :meetings, :through => :meeting_people
validates_presence_of :first_name, :last_name, :email
validates_uniqueness_of :email
def fullname
"#{first_name} #{last_name}"
end
end
class Meeting < ActiveRecord::Base
has_many :meeting_people
has_many :people, :through => :meeting_people
validates_presence_of :starting_at, :ending_at, :location
def validate
if starting_at > ending_at
errors.add_to_base("Starting time is later than ending time!")
end
if self.people.empty?
errors.add_to_base("You must meet with at least one person!")
end
end
def people_as_sentence
return self.people.map { |p| p.fullname}.to_sentence
end
end
class MeetingPerson < ActiveRecord::Base
belongs_to :person
belongs_to :meeting
end
Listing 2. views/meetings/new.html.erb, Modified from the Default Scaffold to Allow the User to Enter One or More People
<h1>New meeting</h1>
<% form_for(@meeting) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :starting_at %><br />
<%= f.datetime_select :starting_at %>
</p>
<p>
<%= f.label :ending_at %><br />
<%= f.datetime_select :ending_at %>
</p>
<p>
<%= f.label :location %><br />
<%= f.text_area :location %>
</p>
<p>With:
<%= select("person",
"person_id",
Person.all.collect { |p| [p.fullname, p.id] },
{},
{:multiple => true}) %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', meetings_path %>
I also created a convenience function that returns an array of names with whom the appointment will be:
def people_as_sentence
return self.people.map {|p| p.fullname}.to_sentence
end
This validation, which is run whenever I try to save an instance of Meeting, checks to make sure that the starting time is earlier than the ending time. If this is not the case, the validation fails, and the data is not stored. (The fact that I can treat times as full-fledged objects, with access to the > and < operators, is one of my favorite parts of both Ruby and SQL.)
Finally, I'm going to enhance this application by modifying the existing scaffolded controller actions to be more useful. First, I modify the new and create actions, such that they will allow someone to create an appointment, simultaneously indicating the person or people with whom the appointment will take place. Then, I modify the index action, so that the user will get a list of all upcoming appointments.
Now that I've created a simple application, the time has come to test it. As I wrote above, testing the application requires that I have some sample data with which to test it. By default, the generators for Rails models create basic fixtures, which have long been the standard way to import data into Rails tests. By basic, I mean that they contain some very, very basic data—too basic, actually, for any real testing I might want to do. For example, here is the automatically generated fixture for people:
one: first_name: MyString last_name: MyString email: MyString two: first_name: MyString last_name: MyString email: MyString
Even if you are new to reading YAML, let alone fixture files, the format should be easy enough to understand. YAML consists of name-value pairs within a hierarchy, and indentation indicates where in the hierarchy a particular name-value pair exists. (You also can associate a list of values with the key, by separating values with commas.) Thus, there are two people defined in the fixture, one and two, and each has three name-value pairs.
However, these name-value pairs are close to useless. They might contain valid data, or they might contain data that fails to adhere to the standards laid out in my model validations. If I had defined a validator for the email field, ensuring that the field always would contain a valid e-mail address, the tests would fail right away, before they even ran. Rails would load the fixtures into ActiveRecord, the database would reject them as being invalid and I'd be left scratching my head.
Things get even hairier when you start to make fixtures that depend on associations. I obviously want my meeting_people fixtures to point to valid people and meetings, but using the numeric IDs can get confusing very quickly. Fortunately, recent versions of Rails allow me to name the fixture to which an object is associated, rather than its numeric ID. Thus, although the default fixtures for meeting_people is this:
one: person_id: 1 meeting_id: 1 two: person_id: 1 meeting_id: 1
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- Swap Your Laptop for an iPad + Linode
- Building an Open-Source House
- An Automated Reliable Backup Solution
- Tech Tip: Really Simple HTTP Server with Python
- Stupid tar Tricks
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Acquia Founder, Drupal Project Creator Dries Buytaert Named a Young Global Leader by the World Economic Forum
- Getting Rid of Spam
- QuickStart: Replication & Recovery 1.2
- 1998 Atlanta Linux Showcase
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




3 hours 42 min ago
6 hours 14 min ago
7 hours 32 min ago
8 hours 7 min ago
8 hours 29 min ago
13 hours 18 min ago
14 hours 4 min ago
15 hours 38 min ago
17 hours 15 min ago
19 hours 13 min ago