First let me say I've really enjoyed reading my daughter's blog this year (even if she rolls her eyes any time she sees me on her blog). I haven't posted nearly as many times as I'd hoped. Writing is hard!!
Memorial Day morning was a perfect runner's morning. Except, I haven't run in four years so I had to walk it. Ever since I shredded the tendons on my ankle and had surgery I've been limited to a jog at best. Extremely frustrating. About a mile into my walk I was bored; and, so annoyed with my body.
Later that morning I picked up my son from his grandparents. Their community was covered in American flags. Made my remember that I'm so lucky to be living in a country where freedom is the norm because so many men and women now, previously, and in the future put their lives on the line for our country. Makes my bad ankle seem like a bug bite.
Nothing I write could ever convey my appreciation and debt of their (and their families) sacrifice(s). One of our countries weaknesses is that financial rewards often go to those who benefit most from our freedom and safety and yet contribute the least to maintaining those aspects of our lives. In fact, many go out of their way to try and contribute as little as possible despite their own success and comfort.
I'm financially conservative; but, as election year rolls around I always cringe at candidates who ask for lower taxes. Yes, there is a lot of government waste; but, we as a country need to pay down our debt, lower the financial burden for future generations, and make good on the sacrifices for those who put their lives on the line. Dropping the tax rate for the wealthy (and I don't just mean the super wealthy) seems like a short sited, self centered path to a weaker country.
Saturday, June 4, 2016
Wednesday, February 10, 2016
Dynamic Rails Model
When writing a rails application do you find yourself writing model after model; and then controller after controller; and then views after, well you get the idea. I ran into one scenario where I was able to have the models created dynamically and then leverage the same controller and views.
The Scenario
An existing database driven solution needed an admin interface to make maintenance easier and more efficient.
Within the current database the admin team would create the same set of tables for each of their customers. Part of why they did this was that customers would only have access to their tables. For this post we will pretend their customer table's simply consisted of two tables called problems and solutions. Therefore Customer ABC would get tables abc_problems and abc_solutions and Customer XYZ would get tables xyz_problems and xyz solutions.
It was decided that a Ruby on Rails application could be spun up to point to the database tables and provide the new admin interface. The proposed UI would allow the admins to select a customer and then be able to manage the data for that customer. If the admin selected Customer ABC he would be able to create new entries in abc_problems and abc_solutions, and edit or delete entries in those tables as well.
First Pass
The project team realized that to show a list of all customers they needed a new table for all the customers (customers).
They started by also creating models for a single customer (AbcProblem and AbcSolution) and for customers as a whole (Customer).
They created a generic controller for each of their customer models (problems_controller and solutions_controller) and built views to support the standard actions. They just wired the controllers and views to use the AbcProblem and AbcSolution models regardless of what was selected in the customer dropdown.
The Call for Help
But at this point they realized they were going to need to create new models for every single customer (and for future customers). And, somehow modify the controllers and views to handle each one or have to create controllers and views for each customer as well.
With the limited amount of time before the code freeze we needed to get it working.
From the Rails perspective everything would have become greatly simplified if the database structure could have been changed from tables for each customer to common tables that had a customer column. But that was not an option here since 1) the tables were already supporting live customers in there current format and 2) access to the data was user account and table driven.
Our first step was to make the models dynamic so the Rails application would not need to be updated every time a new customer was added. To do this we took the Abc models they had created and moved their code into abstract models and within an eval statement. Then we created a factory that would load/create the model based on prefix.
For example, the initial AbcProblem may have looked like this:
class AbcProblem < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
validates :severity, numericality: { greater_than: 0, less_than: 11}
has_many :abc_solutions
end
From that we created a ProblemFactory that would create a new ActiveRecord class if it didn't already exist.
class ProblemFactory
@@problem_classes = {}
def self.problem_class(prefix)
if @@problem_classes[prefix].nil?
@@problem_classes[prefix] = build_problem_class(prefix)
end
@@problem_classes[prefix]
end
def self.build_problem_class(prefix) problem_def = "class #{prefix.capitalize}Problem < ActiveRecord::Base;"+
" self.table_name = '#{prefix}_problems';"+
" validates :title, presence: true;"+
" validates :description, presence: true;"+
" validates :severity, numericality: { greater_than: 0, less_than: 11};"+
" has_many :#{prefix}_solutions;"+
"end"
eval(problem_def)
eval("#{prefix.capitalize}Problem")
end
end
That isn't quite enough since there isn't yet a model yet for AbcSolutions. So we added that as well within build_problem_class (refactored to be build_problem_classes)
def self.build_problem_classes(prefix)
#create the solution class as well
solution_def = "class #{prefix.capitalize}Solution < ActiveRecord::Base;"+
" self.table_name = '#{prefix}_solutions';"+
" validates :explanation, presence: true;"+
" include AbstractSolution;"+
"end"
eval(solution_def)
#etc...
The initial references in the controllers to the models were something like:
def index
@problems = AbcProblem.all
end
def new
@problem = AbcProblem.new
end
def create
@problem = AbcProblem.new(problem_params)
render (@problem.save ? :show : :new)
end
Those were changed to dynamically retrieve the class based on which customer was selected:
def index
@problems = problem_class.all
end
def new
@problem = problem_class.new
end
def create
@problem = problem_class.new(problem_params)
render (@problem.save ? :show : :new)
end def problem_class
ProblemFactory.problem_class(@customer.prefix)
end
def load_customer
@customer = Customer.find(params[:customer_id])
end
The Stuff Works
The positives from this approach were
1 - It works
2 - It was completed easily within the deadline for the demo
3- It supports additional customers. When the admin database is updated with new customer tables, the rails application doesn't need to be rebuilt. Just add a customer from within the UI.
The main negative from this approach is that future developers on the project will have a learning curve to figure out this solution. Not only are models created inside a factory using the eval statement; but, a few places with rails generated code had to be changed.
Routes needed some massaging since the three controllers (customers, problems, and solutions) where not all using a specific rails model.
Since the views were displaying AbcProduct or DefSolution the form helpers on the views needed to be changed from using form_for(@model) and f.text_field :attr because there is was no route for an AbcProduct . Instead we used the 'classic' helpers form_tag and and text_field_tag.
You can check out all the gory details from git hub: https://github.com/gwinklosky/dynamic_model
The Scenario
An existing database driven solution needed an admin interface to make maintenance easier and more efficient.
Within the current database the admin team would create the same set of tables for each of their customers. Part of why they did this was that customers would only have access to their tables. For this post we will pretend their customer table's simply consisted of two tables called problems and solutions. Therefore Customer ABC would get tables abc_problems and abc_solutions and Customer XYZ would get tables xyz_problems and xyz solutions.
It was decided that a Ruby on Rails application could be spun up to point to the database tables and provide the new admin interface. The proposed UI would allow the admins to select a customer and then be able to manage the data for that customer. If the admin selected Customer ABC he would be able to create new entries in abc_problems and abc_solutions, and edit or delete entries in those tables as well.
The project team realized that to show a list of all customers they needed a new table for all the customers (customers).
They started by also creating models for a single customer (AbcProblem and AbcSolution) and for customers as a whole (Customer).
They created a generic controller for each of their customer models (problems_controller and solutions_controller) and built views to support the standard actions. They just wired the controllers and views to use the AbcProblem and AbcSolution models regardless of what was selected in the customer dropdown.
The Call for Help
But at this point they realized they were going to need to create new models for every single customer (and for future customers). And, somehow modify the controllers and views to handle each one or have to create controllers and views for each customer as well.
With the limited amount of time before the code freeze we needed to get it working.
From the Rails perspective everything would have become greatly simplified if the database structure could have been changed from tables for each customer to common tables that had a customer column. But that was not an option here since 1) the tables were already supporting live customers in there current format and 2) access to the data was user account and table driven.
Our first step was to make the models dynamic so the Rails application would not need to be updated every time a new customer was added. To do this we took the Abc models they had created and moved their code into abstract models and within an eval statement. Then we created a factory that would load/create the model based on prefix.
For example, the initial AbcProblem may have looked like this:
class AbcProblem < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
validates :severity, numericality: { greater_than: 0, less_than: 11}
has_many :abc_solutions
end
From that we created a ProblemFactory that would create a new ActiveRecord class if it didn't already exist.
class ProblemFactory
@@problem_classes = {}
def self.problem_class(prefix)
if @@problem_classes[prefix].nil?
@@problem_classes[prefix] = build_problem_class(prefix)
end
@@problem_classes[prefix]
end
def self.build_problem_class(prefix) problem_def = "class #{prefix.capitalize}Problem < ActiveRecord::Base;"+
" self.table_name = '#{prefix}_problems';"+
" validates :title, presence: true;"+
" validates :description, presence: true;"+
" validates :severity, numericality: { greater_than: 0, less_than: 11};"+
" has_many :#{prefix}_solutions;"+
"end"
eval(problem_def)
eval("#{prefix.capitalize}Problem")
end
end
That isn't quite enough since there isn't yet a model yet for AbcSolutions. So we added that as well within build_problem_class (refactored to be build_problem_classes)
def self.build_problem_classes(prefix)
#create the solution class as well
solution_def = "class #{prefix.capitalize}Solution < ActiveRecord::Base;"+
" self.table_name = '#{prefix}_solutions';"+
" validates :explanation, presence: true;"+
" include AbstractSolution;"+
"end"
eval(solution_def)
#etc...
The initial references in the controllers to the models were something like:
def index
@problems = AbcProblem.all
end
def new
@problem = AbcProblem.new
end
def create
@problem = AbcProblem.new(problem_params)
render (@problem.save ? :show : :new)
end
Those were changed to dynamically retrieve the class based on which customer was selected:
def index
@problems = problem_class.all
end
def new
@problem = problem_class.new
end
def create
@problem = problem_class.new(problem_params)
render (@problem.save ? :show : :new)
end def problem_class
ProblemFactory.problem_class(@customer.prefix)
end
def load_customer
@customer = Customer.find(params[:customer_id])
end
The Stuff Works
The positives from this approach were
1 - It works
2 - It was completed easily within the deadline for the demo
3- It supports additional customers. When the admin database is updated with new customer tables, the rails application doesn't need to be rebuilt. Just add a customer from within the UI.
The main negative from this approach is that future developers on the project will have a learning curve to figure out this solution. Not only are models created inside a factory using the eval statement; but, a few places with rails generated code had to be changed.
Routes needed some massaging since the three controllers (customers, problems, and solutions) where not all using a specific rails model.
Since the views were displaying AbcProduct or DefSolution the form helpers on the views needed to be changed from using form_for(@model) and f.text_field :attr because there is was no route for an AbcProduct . Instead we used the 'classic' helpers form_tag and and text_field_tag.
You can check out all the gory details from git hub: https://github.com/gwinklosky/dynamic_model
Wednesday, January 20, 2016
Snow Day Checklist
With a threat of snow this weekend, I thought I'd dust off this family classic.
Things you can do to encourage a larger snowfall.
Things you can do to encourage a larger snowfall.
- Do Your Homework - Powerful magic here. Like washing your car (or watering your lawn) and causing it to rain.
- Wear PJs Inside Out - A break from the normal...just like a snow day. Mix and matching a top and bottom can also be effective.
- Do the "Snow Dance" - The more energy expended and released into the atmosphere the better!
- Read Snow Books - There are some fun ones out there. "Snow Dance" by Leslie Evans, "The Biggest Snowman Ever" by Steven Kroll, "Snow Day" by Betsy Maestro, "The Missing Mitten Mystery" by Steven Kellogg, "Rhinos Who Snowboard" by Julie Mammano to name a handful.
- Put 3 Ice Cubes in the Toilet - There is real science behind this; but, too complicated to explain here. But, do not flush, because wasting water will reduce the snowfall.
- Put a Sock on Your Door - A snow sock is best; but, only as long as you can still do #7.
- Wear Snow Socks to Bed and Sleep with a Stuffed Animal - Obviously, polar bears, penguins, and other cold area animals are best; but, any will work as long as you keep them warm through the night.
- Put a Spoon Under Your Pillow - Believe it! Doubting at this point could destroy all that you've worked for so far.
Want to see for yourself? Click the link to see the Snow Day Kit video on YouTube. While there was already a bit of snow out, the snow we got overnight was just unbelievable! Great job kids!!
Sunday, January 17, 2016
iBook for Nana
Want to make your child’s grandparents day AND encourage your child’s creative writing? Then turn one of their writing assignments into an eBook. All you need to start is a writing project from school (or home). With that you can create some digital images and then assemble it all within an eBook.
To add a cover for the eBook, select “Tool” and “Add Cover”. When presented with the popup window, select the image that was intended to be your cover art. The cover file created is cover.xhtml and appears under the Text folder.
The eBook also needs some publishing information which you add by first selecting “Tool” and “Metadata Editor”. This opens a window where you can add the title for the book and the author’s name.
Now click “File” and “Save”. A folder prompt appear for you to select where the epub file will go and what to name it. Note the location where you are saving the file, give it a name, (ie, “ocean”) and click “Save”. The epub file (ie, “ocean.epub”) will be created. Then you can exit Sigil with “File” and “Quit”.
At this point you have an epub file on your computer which is basically an eBook.
If she has a recent mac she also will likely have iBooks on it and could open an epub attachment.
Writing project from school
While in first grade and kindergarten my son came home with many class papers which consisted of a drawing and some writing. This is a perfect start for an eBook. Below is an example of my son’s work that was the basis for our first eBook.
With that as a starting point I decided we should do a book with one picture for every sentence or two on each page of the book. So we had enough writing; but, would need more pictures.
If your child’s writing is a bit different that’s ok, you can adapt. The more advanced the writing the less pictures you'll need per sentence. A picture per paragraph may be the right ratio for your iBook.
At this point, you should have a plan for each page (text and image) in the book.
A way to make digital images of your child’s art
So you could just take a photo with your phone (or pad) of your child's drawing; but, I don’t think they look as nice once included within the eBook. There are lots of scratch pad type apps available from which your child could draw the pictures.
I installed Zoodle on my son's mini-iPad (https://itunes.apple.com/us/app/zoodle-pad-sketching-drawing/id439412351?mt=8).
He recreated the original drawing and then created new ones for the remaining sentences. Lastly, he create one more image to be the cover art for the book.
For each image you will need to Save it to the "camera" by selecting the disk icon and then selecting "camera". Once all the images are in your camera roll you can email them to yourself or share them in some manner to eventually download them to your computer.
At this point you should have the digital images that are to go on the pages and an image for the cover.
He recreated the original drawing and then created new ones for the remaining sentences. Lastly, he create one more image to be the cover art for the book.
For each image you will need to Save it to the "camera" by selecting the disk icon and then selecting "camera". Once all the images are in your camera roll you can email them to yourself or share them in some manner to eventually download them to your computer.
At this point you should have the digital images that are to go on the pages and an image for the cover.
Note: Zoodle is free to download; but, since we first downloaded it, over a year ago, it now has an ad banner.
A way to build the epub file
Again there are multiple tools; however, the details that follow are based on Sigil. A free publishing application you can download for a Windows or Mac computer (https://github.com/Sigil-Ebook/Sigil/releases/tag/0.9.2).
Once Sigil is installed, open it and an empty project will apear:
An epub file is a structured collection of files. The image files will go in the Images folder, and your main pages will end up in the Text folder. Your first page has already been created ("Section0001.xhtml") and has been opened up for you. For more advanced books you could include audio and/or video files. While not covered here; adding them to a page (and the project) would be similar to the steps for adding an image file.
Before working on the first page we will add the images to the project. From the top menu select “File”, then select “Add” and finally select “Existing Files…”
This will open a prompt for you to search your computer for the image files. Find a file and click “Open”. The image file will automatically be placed under the Images folder of the eBook project. You can eliminate a few clicks by just right clicking over the Images folder and select “Add existing files”. Repeat steps for each of your images. You can double click the image in the left pane and it will open in the larger pane. Once done adding the images (and having selected an image) your screen would look something like this.
Next we want to write our first page. Click the tab for Section0001.xhtml. Type in the text you want on the first page (this is not the cover). Then to add an image to the page you click “Insert” from the top menu, then “File”. (Note: the options under Insert have icons that you can also find and use in the action bar for convenience) This opens a window that displays all the image you have added to the project, you then select the image that you want on the page and hit "OK".
To add a second page, select “File”, then “Add”, and then “Blank HTML File”. This will create Section0002.xhtml. Alternatively, you can right click the Text folder and click “Add blank HTML file”. Fill in the text and image for this page using the same steps used for the first page. And, for all the subsequent pages you need.
Slight technical detour here. By default the pages shown appear as “Book View”, as in, how it will likely appear on the screen of a device. However, each page is actually just an HTML file. From the main menu select “View” and then “Code View”. If you are familiar with HTML (and css) you are free to edit in this view instead. Should you ever to take text from Word, you might find in this view that you brought over a lot more than just text (ie, styles and classes on paragraphs).
To go back to “Book View”, select “View” and then “Book View”.
To add a cover for the eBook, select “Tool” and “Add Cover”. When presented with the popup window, select the image that was intended to be your cover art. The cover file created is cover.xhtml and appears under the Text folder.
The eBook also needs some publishing information which you add by first selecting “Tool” and “Metadata Editor”. This opens a window where you can add the title for the book and the author’s name.
Now click “File” and “Save”. A folder prompt appear for you to select where the epub file will go and what to name it. Note the location where you are saving the file, give it a name, (ie, “ocean”) and click “Save”. The epub file (ie, “ocean.epub”) will be created. Then you can exit Sigil with “File” and “Quit”.
At this point you have an epub file on your computer which is basically an eBook.
Sharing the book with Nana
Of course, this will of depend on Nana. Both my son's grandparents have iPhones and iPads so we emailed them the epub file (ie, ocean.epub) as an attachment. When she reads her email on her phone; the attachment can be opened and read in iBooks (which should be on her device already).
If she has a recent mac she also will likely have iBooks on it and could open an epub attachment.
For other electronic readers or phones I would still suggest trying to email the file as an attachment. I’m not sure how the devices will react to the attachment; but, they will likely recognize the .epub extension. The format of the epub file is a universal standard, not specific to iBooks or Apple products.
If you have success opening on an Android based phone please leave a comment below and share any issues you may have had to overcome.
You can try viewing an earlier version of this post that I packaged as an eBook:
Nana.epub
If you have success opening on an Android based phone please leave a comment below and share any issues you may have had to overcome.
You can try viewing an earlier version of this post that I packaged as an eBook:
Nana.epub
Subscribe to:
Comments (Atom)




