Assignment 3, Milestone III
25-Nov-2008: See note on datetime_select here: http://e168f08.plugh.org/uncategorized/datetime_select-used-in-assignment-3/
A version of this doc is in the download’s README file, but this version is official; any tweaks or changes will be given in dated updates at the top.
Assignment 3, Milestone III: Controllers and Views
Due date: Sunday, Dec. 7
In Assignment 3, Milestone III, you will modify MetricMine, adding controllers and views.
There are some small changes between this version and the prior version: 20081111021247_add_current_observation_set_id_to_user.rb adds a column to user “current_observation_set_id” - whenever you view an observation set, the id is saved here so that when you log in from a cookie, you can be redirected to that set: This makes it especially easy to enter a new observation for whatever set you were last looking at. There are also some extra validations on the models; these changes required some tweaks to the tests (we didn’t add tests for the additional validations, but we did need to change our existing tests). We added a default value of ” for the notes field on observations. We also added a “dependent” option for ObservationKind so that when it is deleted, the foreign key will be set to null on any ObservationSets that belong to it. Finally, there is an additional data migration so that the “john” user has two relatively detailed observation sets (for weight and savings).
About nomenclature:
In the UI, an observation set is called a metric, and an observation kind is called a “kind of metric” or a “metric kind.” It seemed to us that for the end user this language is easier that observation/observation set.
Now, what are you supposed to do?
You need to flesh out the controllers and views that manage certain models for basic CRUD operations.
Any time you like, you may play with a “reference implementation” here:
We will re-run the migrations periodically to clear out the database.
Also note that you can fire up your server (ruby script/server), browse to http://localhost:3000, and quite a bit of MetricsMine will run. You will see some missing data because your controllers aren’t finished, or some static data that doesn’t apply to your user, because the views aren’t all dynamic. In a number of cases, we have marked out views that need to be made dynamic; in some cases, we give you some static rendered HTML that is the result of the reference view code. All of this is to alert you to what must be done.
Regarding the static HTML: Remember that almost all of this is generated dynamically! E.g., if the action on a form is to “/observation_sets/create_observation” that is probably generated with something like this:
<% form_for :observation, :url => { :action => :create_observation } do |form| %>
In other words, USE YOUR VIEW HELPERS! We don’t want to see “raw” HTML links, form actions, etc., etc. Such things will count against you.
For controllers, make sure that you choose redirect or render properly; we will mention this occasionally below, but the behavior should be like the reference MetricsMine application. When this assignment is graded, we will spot-check for this. In the views, there are a number of little details you need to get right: The page title; the error display (both summary and per-fiend); setting the focus on the first element for a field; etc. Again, graders will spot-check, so you need to get this right everywhere.
NOTE: On occasion, you may see an error message claiming that there is no template for the “create” (or another) action. Remember that in Rails, we typically redirect after create, or use the view template for another action; in other words, these error messages may be spurious, depending on where you are with the assignment. When in doubt, review the reference implementation.
This download includes a fully-migrated version of the database. If you want to get the database back to its original condition, do
rake db:migrate VERSION=02 rake db:migrate
During development, you may also find that you need to delete any permanent cookies in your browser for the app associated with the “localhost” server. You would want to do this if the saved user id is forcing you to an action + view you haven’t implemented yet.
Let’s go through the actions, roughly by controller:
(1) The easy cases: Administrative functions. Remember that you have to log in as “admin” to see these. You should be able to finish these swiftly; within 4 hours, maximum.
Controllers:
MeasurementsController
ObservationKindsController
UnitsController
These are roughly the same as the CRUD operations in LinkWizz, CCC, and LinkWizz’s ResearchTopicsController. Remember that a Unit belongs to a Measurement (same for ObservationKind), so for edit and new you will need to set up a @measurements instance variable that holds the options for the drop-down.
Notice that you CAN delete an ObservationKind.
Views:
For each of these controllers, there are views for edit, index, and new - there is no “show” because the relevant data is shown in the list. A pattern you may see is to implement a “list” action, and have the “index” action utilize it; in MetricsMine we’ve simply implemented index.
We have included STATIC stubs for the views for ObservationKinds to give you a feel for what the rendered dynamic view should look like (you can do “view source” on the reference implementation to see the same sort of thing). Notice the fancy JavaScript for the “(delete)” link. The view helper link_to’s :action => ‘destroy’ option will do all of this for you.
For the others, we have just included a message asking you to implement the view.
(2) Managing an Observation Set and its Observations
This will be more difficult. There are a lot of little details here. Try to get as far as you can; we will give you hints on the discussion board, particularly if it is clear that you are making headway.
Controller: ObservationSetsController
Notice that this controller manages updates of BOTH ObservationSet and Observation. This is not an unusual pattern. Since Observation is almost completely a “slave” of ObservationSet, it is convenient to manage both Models in the same controller. When we get to REST, we will talk about changing this.
Actions
new and create: The new and create paired actions are for creating a new ObservationSet. Notice that you cannot edit/update the name and kind of a user’s ObservationSet!
NOTE: When an ObservationSet is created, don’t forget to (a) set the @observation_set’s user_id to that of the current user, and (b) also set the @observation_set’s preferred unit to the first unit of the selected ObservationKind’s Measurement!! These two items (a) and (b) are each easily expressed in a single statement.
show: This shows all of the observations for the observation set, AND it sets up a form for adding a single observation! When an observation set is displayed or edited, the current observation set id is copied to the current user’s attribute current_observation_set_id. You must do this as well. This allows the filter on the application controller to bring the user back to the last observation set edited, for easy addition of new data.
create_observation: This is the action to which “show” posts when you want to create a single observation. Let me repeat: *NEW* sets up the form for an observation_set that posts back to *CREATE* to create an observation_set. But *SHOW* shows all the observations, AND sets up a form for an observation; that form posts back to *CREATE_OBSERVATION*. In the reference implementation, the id of the newly-created observation is put into the flash, so that when the list of observations is re-displayed, we can change the background color of the row. You need to do this, too; to get it to happen you will want to dynamically change the style element on the correct <tr> tag. E.g., it would look like:
<tr>
when the row shouldn’t be emphasized; and
<tr style=”background-color: #E0FFFF”>
when it should be emphasized. This is the sort of thing you can glean from view/source for the reference implementation.
edit and update: These are for setting up the edit view with the checkboxes, so that you can delete specific observations. Notice that after update deletes the appropriate observations, it creates a “flash” message that summarizes how many observations were deleted. Notice that the title of this page has the name for the observation set, so you will need to establish the proper @observation_set as well as @observations. It is possible to implement this so that the view works off of @observation_set only, but I think it will be easier if populate instance variables for both @observation_set and @observations.
Views:
edit.html.erb - There should be a table around the form; checkboxes are on each row. (Big) HINT: The easiest way to make this work is for the form to be on the observation_set, and to use the checkbox_tag: check_box_tag “observation_ids[]“, “#{obs.id}” %>
new.html.erb - Standard.
show.html.erb - The interesting part is defining the form to create an observation. It will look like this:
<% form_for :observation, :url => { :action => :create_observation } do |form| %>
Now, read closely: An observation is for a particular observation_set, right? Therefore, this form must have in it a field that designates the observation_set for which this observation is destined. We are accustomed to putting all of the new data for a model into form fields — but do we want the user to be able to edit the observation_set_id? I don’t think so. Therefore, the way to implement this is with a hidden field. Inside that form you are going to need to define:
<%= form.hidden_field :observation_set_id %>
Otherwise, how would the observation_set_id get back into the params hash so that the new @observation is set up correctly . . . ?
That’s all we have to say for show.html.erb. Try and get as much of it working as you can; if you have issues, post them to the discussion board.
QUESTIONS AND ANSWERS
Q1. Can I replace the stylesheet or change the HTML?
A1. No.
Q2: Can I add additional information that is “latent” in the model? I.e., can I change what is shown in the tables?
A2: No.
Q3: Is there any extra credit?
A3: Yes. We will give a SMALL number of points (2 or 3) for an implementation of the “compare” function. Compare is a multi-stage process. First a list of links should be displayed where the user picks an observation set (you could also implement this on the index view for observation_sets), so that the user can pick which observation set needs a comparison. That should take the user to a page that would show a list of observation sets owned by other users of the same measurement kind. The UI could present a list of links or a drop-down. Once the other observation set is picked, you should show a view that compares the data. My advice is to KEEP IT SIMPLE. For example, simplying show the first and last observations for each observation set, along with the dates for those observations, would be fine. The learning process here is in the addition of controllers and views to facilitate the comparison. If you want to go nuts, you could try to rollup the data in similar fashion, and then create a Google Chart that charts both data sets — to do this will require a lot of scrounging around to figure out Google Charts. I think this would be a waste of time at this point, but I mention it for the ambitious.
Add New Comment
Viewing 183 Comments
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
In several posts since the beginning of the course, I have said: Remove that file.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
I thought I was done.. Logged back in to do a final wrap up, and now I'm confused. Do we need to submit migrations? The Paragraph at the top regarding logging in from a cookie, redirecting to measurements page, makes it sound like we might need to change our migrations. I did them for Milestone 1 but haven't touched them and have been using the provided migrations from this site.
Am i right? Were we supposed to do a version 3 of the migrations?
Thank you.
Do you already have an account? Log in and claim this comment.
There are no required changes to the migrations as long as you use the ones we handed out after Milestone 1.
Regarding using the cookie to login and to to the last observation set: That is all handled by the filter in the application.rb we originally handed out.
The only thing you have to do his this: "When an observation set is displayed or edited, the current observation set id is copied to the current user’s attribute current_observation_set_id. You must do this as well. This allows the filter on the application controller to bring the user back to the last observation set edited, for easy addition of new data." See above. This has always been in the requirements.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
After I run
rake db:migrate VERSION=02
rake db:migrate
and I received the following error message. I am not sure why? What do I need to do?
ActiveRecord::RecordNotFound in WelcomeController#welcome
Couldn't find User with ID=7
RAILS_ROOT: C:/Ruzh/Harvard/CSCI E-168/Assignment3
Application Trace | Framework Trace | Full Trace
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:1383:in `find_one'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:1366:in `find_from_ids'
C:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/base.rb:541:in `find'
app/controllers/application.rb:31:in `authorize'
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
http://metricsmine.plugh.org/observation_sets
We're sorry, but something went wrong.
We've been notified about this issue and we'll take a look at it shortly.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Also, when an observation is created, the unit should be the same as the preferred unit as the observation set for which it is created. This is specified in the assignment: "An Observation has a Unit. In the initial implementation, all Observations in a particular Observation Set use the Observation Set’s preferred unit. (E.g., if the Observation Set’s preferred unit is Pound, then all Observations are also in Pounds.)" (http://e168f08.plugh.org/assignments/assignment...).
Eventually, it would be nice if one observation could be recorded in pounds, and then later in kilograms, with automatic conversions between units of the same measurement kind.
Also, at present, when you create an observation set, you never pick the unit. You only pick the KIND, and, by specification, "also set the @observation_set’s preferred unit to the first unit of the selected ObservationKind’s Measurement!!" (http://e168f08.plugh.org/assignments/assignment...). Notice that we have not defined here what "first" really means; as long as you set the observation_set's unit to SOME unit that has been associated with the measurement of the picked observation kind, you'll satisfy the requirement. I probably should have said "first in order of create time." In any case, lacking an ability to convert between units of the same measurement, it makes no sense to allow a lot of flexibility with units.
Do you already have an account? Log in and claim this comment.
My tests complained that a new ObservationKind was created without a :measurement_id value. My ObservationKind model file includes "validates_presence_of :measurement_id".
First, it looks like the validation isn't working. Wha?
Second, I started a new migration, adding ":null => false" as an option to change_column:
change_column :observation_kinds, :measurement_id, :null => false
but the migration failed with the message, -- change_column(:observation_kinds, :measurement_id, {:null=>false})
rake aborted!
undefined method `to_sym' for {:null=>false}:Hash
WHA???
this seems nuts! any suggestions? thanks.
Do you already have an account? Log in and claim this comment.
The reason your call to change_column is failing is because you left out the type: See the doc;
change_column(table_name, column_name, type, options = {})
http://api.rubyonrails.org/classes/ActiveRecord...
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Thanks!
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
<form action="/observation_sets/create_observation" method="post">
<input class="text large" id="observation_notes" name="observation[notes]" size="30" type="text" />
<select id="observation_date_1i" name="observation[date(1i)]">
... and all the other (2i), (3i)... fields
</form>
I can grab the "observation[notes]" field (shown above) just fine, but for some reason just keep getting nil values when trying to work with the "observation[date(1i)]" fields.
params[:observation][:notes]
grabs the notes, but
params[:observation][:date]
won't grab any dates... and
params[:observation][:date(3i)]
throws an error.
Played around with
convert_date
to no avail.
This has got to be simpler than I am making it. Probably a one-liner...?
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
params[:observation][:observed_at]
as well as
Observation.new(params[:observation][:observed_at])
(ie. the "date" field is renamed in this application to "observed_at")
and it just does not work.
I just keep gettting an error
"Couldn't find rollup for observation at "
The date is not being received at all.
In the error message there is a "Request Parameters" section that shows clearly that the parameters are getting sent across correctly as follows:
{"observation"=>{"observation_set_id"=>"2",
"observed_at(4i)"=>"04",
"observed_at(5i)"=>"31",
"observed_at(6i)"=>"45",
"notes"=>"abc",
"amount"=>"123",
"observed_at(1i)"=>"2008",
"observed_at(2i)"=>"12",
"observed_at(3i)"=>"7"},
"commit"=>"Add"}
I think there may be something wrong with my system's helpers when they are catching and reconstituting the date fragments.
I will send my code to Keith right now.
Do you already have an account? Log in and claim this comment.
observation = Observation.new()
observation.observed_at = Time.new(params[:observation][:observed_at])
but why go to the trouble of addressing this level of detail when creating your observation?
You have everything you need in params[:observation] -- the observation_set_id, notes, amount, and all of the pieces of observed_at.
Just invoke Observation.new(params[:observation]), and trust Rails to unpack everything properly for you.
Do you already have an account? Log in and claim this comment.
As I said, generally, you want to build your forms so you can do as you described, and mess with parameters only on rare occasions.
Do you already have an account? Log in and claim this comment.
Naturally, I've been watching this discussion of datetime_select with some interest.
My main comment for students struggling with datetime_select is to look at example code:
In the ChildCare Co-Op app, app/views/playdates/list.html.erb . . . and app/controllers/playdates_controller.rb (see the "create" action).
As you see there, datetime_select does all of the heavy leifting -- you don't have to dig into the key of the instance object, nor its pieces.
The one additional piece here is that there is an option :include_seconds which is documented for other tags; despite its omission from the docs for datetime_select, it does exist. I sent around an e-mail on this topic awhile back.
Do you already have an account? Log in and claim this comment.
But: to figure out what's happening with parameters, in general, I've found it very useful, when I get totally confused, to stick the line
puts params.inspect
into a controller action, and then go look at the output from my server, to see exactly what it is that the controller is seeing after the user posts the form.
Do you already have an account? Log in and claim this comment.
In general you want to construct your forms so you rarely, if ever, need to futz with the parameters, especially in basic CRUD actions.
I'm getting a lot of questions from people having trouble with params. Outputting it with params.inspect, tailing your development log, whatever -- it is important to know what is being passed to your action, and what the structure of the hash looks like, in order to debug effectively.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Incidentally, at work we have noticed that there are problems with datetime_select on Rails 2.2.2, so I hope you haven't inadvertently updated your Rails version!
If you continue to have problems, post.
Do you already have an account? Log in and claim this comment.
c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_view/helpers/form_options_helper.rb:214:in `options_from_collection_for_select'
c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_view/helpers/form_options_helper.rb:398:in `to_collection_select_tag'
c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_view/helpers/form_options_helper.rb:133:in `collection_select'
c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_view/helpers/form_options_helper.rb:445:in `collection_select'
app/views/observation_kinds/new.html.erb:11:in `_run_erb_47app47views47observation_kinds47new46html46erb'
app/views/observation_kinds/new.html.erb:5:in `_run_erb_47app47views47observation_kinds47new46html46erb'
app/controllers/observation_kinds_controller.rb:33:in `create'
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
How does this line work? :observation_ids[] isn't something I have seen in my code. Is this meant to gather the observation.id into an array? I gather that the obs.id will send the obs.id to the update method so that an observation can be deleted.
Do you already have an account? Log in and claim this comment.
The checkbox technique is also used in ChildCare Co-Op. Please review those materials.
Do you already have an account? Log in and claim this comment.
Thanks!
Do you already have an account? Log in and claim this comment.
The short answer is that when you put [] after an attribute name, Rails will magically take each check and assign "true" to the array element for the check id.
It's totally non-obvious, which is why I discussed it in lecture, and recommended that people look at the ChildCare Co-Op code.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
One thing you want to watch for is this:
-- If in your own implementation you add an observation at 5:00 PM, it should show up as 5:00 PM in the list.
What is going on here is that times are stored in the database in UTC (universal time). If you made the mistake of entering dates in, say, local time, you could get a discrepancy.
it is unlikely that this is happening to you.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
For an observation kind I can say something like observation_kind.measurement.name because all the methods are made available to the observation_kind through the measurement relationship.
Should I also be able to use the same relationship with units? For example unit.measurement.name? When I do this from the unit's index view the measurement is nil.
Do you already have an account? Log in and claim this comment.
ruby script/console
Unit.find(:all).first.measurement.name
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
You should be able to do:
Unit.find(:all).each { |u| puts u.measurement.name }
I.e., iterate through all of your units, and see if any break on the following of the measurement association.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
The submission is like so:
0. Before submitting, verify that the migrations work! I.e., delete (or rename) db/development.sqlite3 and do "rake db:migrate". Check out your app! It can happen that you are relying on bad data being in the database, so exercise your app with a clean slate.
1. There should be a small readme text file in the root of the project with your name, e-mail address, and the name of the project -- this is simply so that if we change the name of your project we can still figure out whose it is!
2. If you are doing anything "unusual" or have bugs that require special discussion, include that discussion in the readme. There is NOT a requirement for a "writeup" for this assignment, because the assignment is essentially about fulfilling a fairly narrow set of requirements. Do include judicious code comments for anything that is unusual, weird, especially superb, etc.
3. You may have a file bin/PKZIPC.exe - remove it. Your ZIP won't go through some e-mail agents with it included.
4. ZIP your project with
rake package
It is possible that this will fail on systems that do not have a working ZIP program -- we have a ZIP in Ruby included, but it can sometimes break on Windows.
If rake package doesn't work, ZIP up your project with any ZIP program. If you have to manually ZIP, remove the files from tmp/ and log/ . INCLUDE YOUR NAME in the name of the ZIP archive.
E-mail it to your TA.
Do you already have an account? Log in and claim this comment.
Also, you say we should delete our database and rake db:migrate. Do you want us to package our submission with our test data in the database, or just a clean database, or none at all? Or does this even matter?
Do you already have an account? Log in and claim this comment.
The safest thing would be to rename your "good" database. So that way if it turns out that your migrations fail, we can still do some forensics to figure out what's going on.
I need to double-check the Rakefile 'cos it may do something funny with db/
John
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
But, generally, you want to store time/date data in UTC.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Also: It is easy to create UTC times . . . you might have noticed in models/rollup.rb, db/migrate/data_add_rollups.rb and elsewhere.
In other words: If you stick to UTC, you don't have to do any conversions.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Couldn't find rollup for observation at
Application Trace | Framework Trace | Full Trace
app/models/observation.rb:36:in `before_validation'
app/controllers/observation_sets_controller.rb:53:in `create_observation'
I could not figure out why? Could you guide me?
Do you already have an account? Log in and claim this comment.
If "observed_at" is bad, then no row will be found, and that code will fail.
Therefore, double-check that you are setting observed_at is being set properly.
There are only rollups for dates between 2008 and 2010 -- so there could be an issue if you add an observation farther in the future. If you look at the rollups migration, you should be able to figure out how to create more rollup data for more years in the future.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
For the final project: A great thing to do is to try to manage URLs so that they aren't sequential numbers. Even if you check the user who supposedly owns a given resource/item, it can be good to not even reveal the fact that something exists at a certain id. To do this, you would add a column and you would set it to some String version of a Hash of unique info for that record; then look up by that added id, rather than by the primary key.
Do you already have an account? Log in and claim this comment.
Is there a way to print debug info out to the console or something? I want to see some errors at least, or find out where my mistake is.
Do you already have an account? Log in and claim this comment.
You say that you created a CREATE "function" (I assume you mean method?) in a helper object. Action methods should be on the CONTROLLER, not on any helper objects.
So, the upshot is:
(1) In the observation_set.rb file, which defines ObservationSetController, you should define a "create" method. This is the method that allows you to create a set of observations. It will look something like this:
def create
# you add your code here
end
(2) When a specific observation is added, that is handled by a method called create_observation. So in that same file you will need:
def create_observation
# you add your code here
end
In both of these methods, you may find it helpful to add calls to the "puts" method to dump whatever debug code you want to the console.
One last thing: Everything I've said here I said in the assignment description above in the section that starts: "Controller: ObservationSetsController
Notice that this controller manages updates of BOTH ObservationSet and Observation. This is not an unusual pattern. Since Observation is almost completely a “slave” of ObservationSet, it is convenient to manage both Models in the same controller. When we get to REST, we will talk about changing this."
And then I went on to define exactly the methods you need to define. I am not sure what you mean in your post about writing a "dummy function" (there are no functions per se in Ruby) or "the helper object" (since you really shouldn't need to do anything with helpers).
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
"You have a nil object when you didn't expect it!
The error occurred while evaluating nil.has_key?"
I have gone through the book many times, through your Lecture 9 slides, reviewed the "CRUD" application code (which all runs just fine on my machine).
To try and fix this issue, I am working with the admin's Measurements "New Measurement" form, which is the simplest.
The HTML produced on my form is identical to that on metricsmine.plugh.org. So there must be a problem on the "measurement.rb" or "measurements_controller.rb".
The error is being thrown by the following line in the "def Create":
@measurement = Measurement.new(params[:measurement])
If I remove the code that does the create / insert, and just pass the #{params[:measurement]} to the "flash" message on the index page, then the results of that printed variable are:
nameasd
(where I typed "asd" into the name field).
For the above I had not initialized any variables in the "def new" with any variables. If I add
def new
@measurement = Measurement.new
end
to the controller, then I can't even get to the "New Measurement" form at all. Clicking on the "New Measurement" link gives me the error:
wrong number of arguments (0 for 1)
Otherwise, I am progressing, but I've been picking at this one crucial issue for too long now. Please assist. Thank you.
Do you already have an account? Log in and claim this comment.
(1) In views/measurements/new.html.erb: What does your "form_for" line look like?
(2)
Double-check that your Measurement model, defined in measurement.rb, looks like this (this is what we handed out with the "solution" for the associations and validations milestone):
class Measurement < ActiveRecord::Base
has_many :units # 7b
has_many :observation_kinds # 6b
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :name, :maximum => 30
end
(3) Remove your file db/development.sqlite3 and re-run your migrations from scratch. Important: you should be using the model definitions (with its associations and validations) and migrations from the solution download.
Do you already have an account? Log in and claim this comment.
2) HOWEVER, I found the following in my measurement.rb. Once I removed it, then everything worked fine.
def initialize(measurement)
@measurement = measurement
@name = name
end
I must have added this when in my "I'll try anything" stage.
3)...
Thank you!
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
In the reference implementation, the id of the newly-created observation is put into the flash [did you do this?], so that when the list of observations is re-displayed, we can change the background color of the row [Have you figured out how to do this?]. You need to do this, too; to get it to happen you will want to dynamically change the style element on the correct <tr> tag [do you have a way to determine the correct <tr> tag?]. E.g., it would look like:
<tr>
when the row shouldn’t be emphasized; and
<tr style=”background-color: #E0FFFF”>
when it should be emphasized. This is the sort of thing you can glean from view/source for the reference implementation.
---------------------
So this means that when you display the <tr> element for the row, you are going to have some code more or less like this:
<tr <%= if SOMETHING then '' else 'style="background-color: #E0FFFF"' end %>>
The part after the "then" is when the condition holds -- i.e., when it's an ordinary row; the part after the "else" is for when the condition doesn't hold, which would be the case when you want to "decorate" the row. There are other ways to get the effect: You could create an actual style and then select it with the "class" attribute on the tr element.
The "EOFFFF" is from inspecting the rendered HTML of the the reference implementation (after adding an observation).
You have to figure out SOMETHING. It is an expression based on the whatever you put in the flash that indicates the item number of the most-recently-added observation.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
-- If there are errors, render. Why? Because you use the instance variables to trigger to the error display.
-- If there are no errors, then you want to redirect so that the user gets a fresh page and a page reload won't re-submit the form.
Other frameworks will redirect for error display, too; the reason Rails doesn't is presumably because it means using the session too much.
Do you already have an account? Log in and claim this comment.
We are supposed to save the observation set id into the user table. We save off the last observation set the user chooses.
However, I don't see how we use this information.
When I log on, I get to the dashboard, which allows me to:
- logout
- Get a list of metrics (i.e. observation sets)
- Create a new observation set
- Compare
So, I don't see how and where we direct a user to a page with the most recently used observation set.
The assignment reads:
"There are some small changes between this version and the prior version: 20081111021247_add_current_observation_set_id_to_user.rb adds a column to user “current_observation_set_id” - whenever you view an observation set, the id is saved here so that when you log in from a cookie, you can be redirected to that set: This makes it especially easy to enter a new observation for whatever set you were last looking at. "
So, when I log on, assuming that there's a cookie, do we not go to the dashboard, and instead go straight to the page where we can add new observation s?
Thanks
Do you already have an account? Log in and claim this comment.
(1) Log in.
(2) close your browser without logging out.
(3) Go back to the application. See where you end up?
If this doesn't work for you, let us know.
Reason for this behavior: There is ONE activity that the user wants to do every day: Post data. If you have ever tracked your weight, you will do anything to avoid this behavior. Therefore, the application makes it as easy as possible.
Do you already have an account? Log in and claim this comment.
It takes me to the dashboard.
BTW, why do you need o save the information in the database as well as in the cookie ?
I thought that if you save it in the database, then once you look on, you will get the observation set information from the database.
If you save it in the cookie, then you get it from the cookie. Why do we need both ?
Thanks
Do you already have an account? Log in and claim this comment.
When you say: "why do you need o save the information in the database as well as in the cookie ?", what do you mean by "the information"?
Do you already have an account? Log in and claim this comment.
It delete multiples rows for each delete key I hit.
I hope that you can reproduce this. Perhaps my problem with ObservationKind delete is related or similar.
Do you already have an account? Log in and claim this comment.
If you are deleting observations (metrics), you would use the checkbox and then click "delete checked." There is only one button here, so I don't know what you mean by "each delete key I hit."
If you are deleting observation kinds -- "kinds of metrics" in the UI -- you would be clicking the delete link.
Note that when an observation kind is deleted, then the display of the KIND at the top of the "show" page for the observation set can no longer display the kind. So it is blank. There is an instruction regarding this in the static page for the "show" template.
Do you already have an account? Log in and claim this comment.
Also, "the information" is the observation_set id.
I thought we're supposed to save off the last used observation_set id somewhere, so that when the user log on again, he gets send to the page whereby he can add a new observation for the observation set he last used.
Now as an admin
I also noticed that in the reference implementation, the delete also seem to have rows (observationKinds) automatically disappearing.
Also, when I hit destroy for some of the ObservationKind, I to an error page.
Do you already have an account? Log in and claim this comment.
I cannot reproduce the "automatic" disappearance of observation kinds, or any error page. If you delete all of the observation kinds (PLEASE DON'T!) you will find that you can't create a new observation set (I think). This was discussed earlier, and we said: "An admin would never delete all of the observation kinds, so we will consider this a feature, not a bug."
I have just reset the database. If you can identify a set of seps that will produce this behavior, from login to the error, e-mail the steps to me.
Do you already have an account? Log in and claim this comment.
This will require me to modify my browser settings to accept persistent cookies, won't it?
(But shouldn't it work equally well to leave the browser open and simply close the tab or window that's connected to the metrics mine, and then go back to the application?)
Do you already have an account? Log in and claim this comment.
I am not 100% about this, but I think if you close all tabs to a site, and then re-open a tab, your prior session cookie will still be used (which makes sense from many typical end-user cases -- if you accidentally close a tab, you don't want to have to re-log in).
Also, it is worth nothing that Internet Explorer and Firefox work differently with temporary cookies (not your question, but related). You can block a temp cookie on IE, but not, to my knowledge, on FF (though doubtless there is a browser plugin for FF that will do it). Also, if you're a security zealot, IE implements P3P, which is pretty great, though few sites implement it server side (one that does is my old company, h3.com - https://www.h3.com).
Do you already have an account? Log in and claim this comment.
Why would we want to limit this convenience feature to people auto-logging-in with a persistent cookie? Isn't the redirection to the current observation set equally (or more) useful to someone who logs in daily from their public library or school's lab, or someone travelling around the world tracking their latitude in Internet cafes? The way I use my own computer, taking me from the home page to the desired observation set is of almost no use at all, first because my browser discards persistent cookies on exit for privacy reasons, and second because for sites that I visit frequently, my bookmarks generally take me not to the home page of a site, but directly to the page I'm interested in (and if those pages require login, most well-designed sites will redirect me to a login page and then from the login send me directly to the page I was trying to get to).
Do you already have an account? Log in and claim this comment.
If you logged in at school on a computer where you didn't have a cookie, do you want someone looking over your shoulder to know right away that you've blown your diet?
It is definitely the kind of thing that would get tuned based on user response.
Do you already have an account? Log in and claim this comment.
and if you do not check any box (for observations), then, there will be a page telling me that something went wrong.
Do you already have an account? Log in and claim this comment.