Forum: Ruby on Rails habtm and date_select problem

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
1b6ed15a6126e1d5ef4d7d15550f30bb?d=identicon&s=25 François Montel (zerohalo)
on 2005-12-14 00:12
I have an habtm problem, which I just can't figure out for the life of
me. This is a continuation of another problem I had (on this thread:
http://www.ruby-forum.com/topic/44286#9200), which someone was kind
enough to help me with.)

To recap, I have tables Projects and Stages, with a habtm relationship.
I have a table  Projects_Stages contains project_id, stages_id and an
additional date_done field (containing the date the stage of the project
was completed).

In addition to letting the user select the next stage of the project, I
want them to be able to select the date that stage was completed, so I
need a date select field on the page.

My models:

class Stages < AR
has_and_belongs_to_many :projects
end

class Projects < AR
has_and_belongs_to_many :stages
attr_accessor :newly_completed_stage_id
attr_accessor :stage_date_done

def before_save
	stages.push_with_attributes(Stage.find(newly_completed_stage_id.to_i),
:date_done => stage_date_done) unless newly_completed_stage_id.blank?
end

end

My edit.rhtml page contains (as part of the form_tag):

<%= collection_select(:project, :newly_completed_stage_id,
Step.find(:all) - @project.stages, :id, :description, {:include_blank =>
true}) %>

<%= date_select (:project, :stage_date_done, :order => [:day, :month,
:year]) %>


The collection_select works just fine on its own. However, adding the
date_select to the edit.rhtml page as shown above, returns the following
error:

undefined method `klass' for nil:NilClass


Trace shows parameters are being passed (some data omitted):

Parameters: {"commit"=>"Save", "id"=>"1",
"project"=>{"stage_date_done(3i)"=>"13", "newly_completed_step_id"=>"5",
"stage_date_done(1i)"=>"2005", "stage_date_done(2i)"=>"12"}}

If I omit the date_select command in edit.rhtml and change my
before_save method to ":date_done => Date.today", then everything works
properly. So the problem is with the date_select command or the
stage_date_done attribute. But I can't find anything wrong with it, and
I can't find any information on what the 'klass' method is. So I'm
stuck! Is this just an habtm limitation or am I missing something?

The only thing I can think of is that date_select returns an array (as
evidenced by the parameters passed), and that maybe I need to somehow
define stage_date_done as an array using attr_accessor? However, I can't
find any way to do this (I have both the Programming Ruby and Agile
books).

Thanks!
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2005-12-14 02:58
(Received via mailing list)
zero halo wrote:
> undefined method `klass' for nil:NilClass
> ...
>
> The only thing I can think of is that date_select returns an array (as
> evidenced by the parameters passed), and that maybe I need to somehow
> define stage_date_done as an array using attr_accessor? However, I can't
> find any way to do this (I have both the Programming Ruby and Agile
> books).

There is no way for Rails to know that stage_date_done is of class Date,
so multi-parameter assignments from posted parameters only work with
database columns where the type can be determined.

Possible solutions:

1. Extract the parameters manually, perhaps making use of AR's
    extract_callstack_for_multiparameter_attributes method.
2. Somehow instantiate stage_date_done as a column in a way that
    Rails knows it's not database-backed.
3. Instantiate stage_date_done as Date.new, and patch Rails around
    http://dev.rubyonrails.org/browser/trunk/activerec...
    to look for the class of non-column attributes.

--
We develop, watch us RoR, in numbers too big to ignore.
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2005-12-14 03:41
(Received via mailing list)
Mark Reginald James wrote:

> 1. Extract the parameters manually, perhaps making use of AR's
>    extract_callstack_for_multiparameter_attributes method.

Best way to do this would probably be to use select_year,
select_month, and select_day, use their field_name options,
and three attr_accessors.


--
We develop, watch us RoR, in numbers too big to ignore.
1b6ed15a6126e1d5ef4d7d15550f30bb?d=identicon&s=25 François Montel (zerohalo)
on 2005-12-14 06:59
Mark Reginald James wrote:
> Best way to do this would probably be to use select_year,
> select_month, and select_day, use their field_name options,
> and three attr_accessors.
>

Yep, tried that and it worked! I set each select_xxx with
:prefix=>:project, :field_name=>:stage_xxx
then created attr_accessor :stage_day, :stage_month, :stage_year

and finally changes before_save to:

def before_save
        stagedate = (stage_year + stage_month + stage_day).to_date
	stages.push_with_attributes(Stage.find(newly_completed_stage_id.to_i),
:date_done => (stagedate)) unless newly_completed_stage_id.blank?
end

Interesting is that :date_done => stagedate returns a strange error
('unknown method < in Nil'). Only :date_done => (stagedate) works.

Sure would be nice though if habtm had a way of verifying the attribute
type in this sort of situation. Maybe Rails could be patched so that
attr_accessor would accept a variable type?

Thanks a lot, Mark, for your help. It's almost taken me a long to try to
solve this one little problem as to write my whole app!
C64e63b70be7dfed8b0742540b8b27e5?d=identicon&s=25 Mark Reginald James (Guest)
on 2005-12-14 07:49
(Received via mailing list)
zero halo wrote:

> def before_save
>         stagedate = (stage_year + stage_month + stage_day).to_date
> 	stages.push_with_attributes(Stage.find(newly_completed_stage_id.to_i),
> :date_done => (stagedate)) unless newly_completed_stage_id.blank?
> end
>
> Interesting is that :date_done => stagedate returns a strange error
> ('unknown method < in Nil'). Only :date_done => (stagedate) works.

stagedate = Date.new( stage_year, stage_month, stage_day ) would be
better.


> Sure would be nice though if habtm had a way of verifying the attribute
> type in this sort of situation. Maybe Rails could be patched so that
> attr_accessor would accept a variable type?

Yes, I think Rails should allow models to define both DB-backed
and non-DB-backed columns, so that both types can make use of
validations and multi-parameter assignments.

--
We develop, watch us RoR, in numbers too big to ignore.
This topic is locked and can not be replied to.