Ruby on Rails: How to store form data - ruby-on-rails

I have a state field that stores the value as 2 characters. For example, Alabama is saved as AL, Alaska is saved as AK, Arizona is saved as AZ, etc. In the show.html.erb, how do I display the long name for the state such as Alabama instead of just showing AL? Is this possible or should I just store the long name in the database such as Alabama, Alaska, Arizona, etc?

Write a method that would output long name of a stateand call it in show.html.erb
some_model.rb:
SomeModel < ActiveRecord::Base
STATE_CODES = {
"AL": "Alabama", "AK": "Alaska",
# add remaining 50
}
def state_human_name
STATE_CODES[self.state]
end
show.html.erb:
<%= record.state_human_name %>
EDIT: It does not help to store full names of states in your database -- you'll need short forms at least somewhere and therefore would need to add mapping between short and long forms anyway.

Is there a reason for using the 2 letter codes (e.g. a legacy database)? If not I would stick to the usual ActiveRecord idiom and have a separate "states" table linked by id. If you need the 2 letter code for display purposes, printing address labels or whatever then add add a 'state_code' attribute to the states table but don't use it as a primary key.

I put this in a comment, but I've decided it's sufficiently different that it warrants an answer.
When you're deciding where to keep your state map, consider whether you'll ever need to ship things to Canada, or further afield. If so, it's worth the effort to set up a states table, linked to a countries table.
And anyway, if your data rarely changes, it's less issue-prone to put it in the database, because code changes far more often. More frequent changes = more opportunities to mess it up. Plus, it's then trivial to sort as you like.
class State < ActiveRecord::Base
def self.get_states
##states || State.find(:all,
:include => :country,
:order => 'countries.name, long_name')
end
end

Tilendor, I notice that if I use STATE_CODES.invert, the drop-down menu selection would get out of order. For example, the first five lines of my option list is shown below:
New Hampshire
Ohio
Colorado
Minnesota
Alabama
...
In my STATES_CODES hash, I have the following listed in the order below:
"AL" => "Alabama",
"AK" => "Alaska",
"AZ" => "Arizona",
"AR" => "Arkansas",
"CA" => "California",
...
Is there a way to have the options listed in the form in the same order as the STATES_CODES? Maybe sort them alphabetically?

Related

Modeling Item Size in Rails App

I have an Item model, that can be clothing, shoes, or bags (category).
I also have the Size model, that represents the Size of the Item.
The issue is:
For clothing, size can be: XS, S, M, L, XL
For shoes, size can be: 9, 9.5, 10, 10.5
Also, the shoe size depends if it is UK or US or European, so a UK 6 is a US 7 and European 40.
How should I model this?
Everything as a single Size model?
Should I have child models?
Or should I have many different models (ShoeSize, ClothingSize)?
Thanks in advance.
Is there any reason you require an 'Item' catch-all model?
The two ways I might do this are:
1) I would either have separate models for clothes, shoes and bags. Each model would have it's own individual size attribute.
I would also do their size attributes as a collection with "US 6" etc as separate options.
or
2) If you want to keep them all under one 'Item' model . Make their type (i.e. shoes, clothes, bags) an enumeration (Example included below). Then I would make a different column in my table for each type of size for example: Item would have an attribute that is :clothes_size that is a collection with your S,M,L,XL and then a :shoes_size with it's own selection etc.Then you can just display the field that is necessary for that item.
Enumerations look like this:
class Item < ActiveRecord::Base
enum type: [:shoes, :clothing, :bags]
end
What the enumeration will do is make it so you have an attribute to put them into categories; mapping each one to an integer in the db. (0=shoes, 1=clothing, 2=bags)
Then you will need to run a migration.
rails g migration AddTypeToItem type:integer
It will also auto generate a bunch of super cool built in methods for you to sort and find your objects by type, such as
#item.shoes? etc. Read more about them in the Rails API.
You could put the item category as an enumeration as #ChiefRockaChris suggested, then I would do this:
make the size attribute an integer and map these integers to a different set of strings according to item category. I would come up with a standard measurement unit for shoe size (like mm) then have another function that maps that measurement to UK, US or European.
This code would go in your Item class
def self.sizes
{
clothing: {1: 'XS', 2: 'S', 3: 'M', 4: 'L', 5: 'XL'},
shoe: {1: '35mm', 2: '40mm', 3: '45mm'}
}
end
def self.shoes_size_type
{
UK: {'35mm' => '6', '40mm' => '7', '45mm' => '8'},
US: {'35mm' => '7', '40mm' => '8', '45mm' => '9'},
Europe: {'35mm' => '35', '40mm' => '40', '45mm' => '45'}
}
end
def self.size_parsed
sizes[category][size]
end
def self.shoe_size(country)
shoe_size_type[country][size_parsed] or size_parsed
end

Bakery Inventory Calculations

I want to create a Bakery inventory that lists the total amount of ingredients needed for the day by taking in:
Cookie orders from Customers [2 Dozen Sugar Cookies, 1 Dozen Oatmeal Cookies]
Cookie ingredients [Sugar Cookie: 1 cup sugar, etc.]
See a chart here
How would you recommend storing cookie ingredients? My initial thoughts were a hash.
{
flour: 2.75,
sugar: 1,
. . .
}
Why a hash?
You lose the benefits of a relational DB then, e.g, if someone edits the "Sugar" ingredient, your hash is no longer up-to-date. That may be okay, but you'll still have to deserialize and do the math.
Consider instead (pseudo-code):
Recipe => has_many :quantities
Quantity => has_one :ingredient
Order => has_many :recipes # Or whatever; you get the idea
Then you can query for a day's orders' quantities, group by ingredient, and do the math.
If you want to keep the hash you could use ingredient IDs as the key etc.
If you're already using a NoSQL DB then none of the above really applies and you have another set of options to choose from, although in some ways you end up with the same questions.

Rails 4: Ordering Users based on the *last word* in their `name` attribute?

I have a User model with a name attribute. In my PagesController, I want to set an instance variable equal to all of the User objects, but I want to order them based on last name. I know I can do:
#sortedusers = User.order(:name => :asc)
to order the users based on their name attribute, but how do I do it based on last name? (i.e. how do I order the Users based on the last word of their name attributes?
Thanks.
Define a virtual attribute last name in your model
def last_name
name.split(' ').last
end
and then
User.order(:last_name => :asc)
I'd suggest storing the users' last name separately. Barring that, you can use sort_by, like so:
items.sort_by! { |a| a.split(' ') } or something along those lines. Note, this most likely cannot be used straight, it's merely intended to point you in the right direction, as most of my answers are.

Rails 4: Displaying a table of a collection of items, sorted by various item attributes?

So I have a CareerEntry model that has the following attributes: name, job_category, company, group, location, year, full_intern, and it represents the job offers that people have received. full_intern is a string that is either "internship" or "full-time", and represents what the type of the job offer is. All CareerEntries will be created by an Admin interface, so it is essentially acting as a standalone model. This is my question: given a bunch of CareerEntry objects, I want to display a table to display on my careers page (which has an action in a PagesController).
I want the table to be sorted according to multiple attributes. I want each year to be its own section in the table, then within each year, I want the internship entries grouped together and the full-time entries grouped together. Then, within these groupings, I want each job_category to be its own section (job_categories comprise of things like 'Investment Banking,' or 'Technology.')
A very good example of what I'm going for is shown under the "2013" tab in this link.
What is the best way to go about achieving this? I know that in the careers action definition of my PagesController, I could have:
class PagesController < ApplicationController
def careers
#careerentries = CareerEntry.order(:year => :desc, :fullintern => :asc, :job_category => :asc)
end
end
But this would simply return all the entries in the order that I want, and would not allow me to place headers and dividers to separate, say, the job_categories.
Is there any easier way of achieving what I'm looking for?
Perhaps you're looking for .group_by?
Group By
From the link you gave, it looks like you want to group your results by year, like this:
#careerentries = CareerEntry.order(year: :desc, fullintern: :asc, job_category: :asc)
#entries_by_year = #careerentries.group_by { |entry| entry.year }
This gives you all the data, ordered to your specs. You can then sort through it, using the group_by method:
#entries_by_year.each do |entry|
entry.name
end
You could then work this into your table
Good reference Group posts by Year - Rails

See if one person is before another in the alphabet, ruby, rails

I'm doing an app for a membership database.
Each person may have a partner. When it comes to displaying the list, I only want to have one row for each family, so at the moment I'm comparing first names and not displaying the row if the person's name is second. Like this
person.first_name != [person.first_name, person.partner.first_name].sort[0]
This means each family only gets displayed once, not twice - once for each partner.
And I'm doing this in the view.
There must be a better way of doing this, and it'd be really great if I could do it at the database level. I'm using postgresql if that makes a difference.
Edit
Sorry if it was unclear.
Say Person 1 has the first_name "Edward" and Person 2 has the first_name "Fay". Edward and Fay are married.
I only want to show them once in my list - I want a row to look like this
Surname First name Address etc
Mysurname Edward ....
Fay
I don't want to display it again with Fay first because I've got both Fay and Edward in list of people, so I use the ruby in the first part of the question to check if I should display the row - it compares their first names and only does the row if the person has a fist name that's before his/her partner's first name.
Here's the relevant part of my person model
class Person < ActiveRecord::Base
has_one :relationship_link, :foreign_key => :person_id, :dependent => :destroy, :include => :partner
has_one :partner, :through => :relationship_link, :source => :person_b, :class_name => "Person"
I hope that's clearer
You need to use DISTINCT ON or GROUP BY. In postgres you need to be careful to group by everything that you are selecting. If you only need to get the last names you can select("DISTINCT ON(last_name) last_name").pluck("last_name"). You will only get an array of last names though.
Maybe you can get records if you order by every other fields in your table, like this:
select("DISTINCT ON(people.last_name) people.*").order("people.last_name ASC, people.first_name ASC, people.field2 DESC, people.field3 ASC...")
You need to order by every attribute so the result is not ambigious.
For this case, i would create a data structure (a Hash) to store people instances given a specific surname. Something like this:
def build_surnames_hash(people_array)
surnames_hash = {}
people_array.each do |person|
last_name = person.last_name
surnames_hash[last_name] ||= []
surnames_hash[last_name] << person
end
surnames_hash
end
That way, you can iterate over the hash and display people using their surnames stored as hash's keys:
surnames_hash = build_surnames_hash(Person.all)
surnames_hash.each do |surname, person_instances_array|
# display the surname once
# iterate over person_instances_array displaying their properties
end

Resources