# Habtm and date\_select problem

**URL:** <https://www.ruby-forum.com/t/habtm-and-date-select-problem/50182>\
**Category:** Rails\
**Created:** [December 14, 2005, 12:12am UTC](https://www.ruby-forum.com/t/habtm-and-date-select-problem/50182 "2005-12-14T00:12:54Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [December 14, 2005, 12:12am UTC](https://www.ruby-forum.com/t/habtm-and-date-select-problem/50182/1 "2005-12-14T00:12:54Z")

</div>

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:  
[Habtm and collection\_select question - Rails - Ruby-Forum](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!

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [December 14, 2005, 2:58am UTC](https://www.ruby-forum.com/t/habtm-and-date-select-problem/50182/2 "2005-12-14T02:58:54Z")

</div>

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/activerecord/lib/active\_record/base.rb#L1690](http://dev.rubyonrails.org/browser/trunk/activerecord/lib/active_record/base.rb#L1690)  
to look for the class of non-column attributes.

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [December 14, 2005, 3:41am UTC](https://www.ruby-forum.com/t/habtm-and-date-select-problem/50182/3 "2005-12-14T03:41:08Z")

</div>

Mark Reginald J. 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.

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [December 14, 2005, 6:59am UTC](https://www.ruby-forum.com/t/habtm-and-date-select-problem/50182/4 "2005-12-14T06:59:14Z")

</div>

Mark Reginald J. 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!

---

<div class="post-metadata">

**Author:** ![zerohalo](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/z/5fc32e/32.png) [@zerohalo](https://www.ruby-forum.com/u/zerohalo)\
**Post date:** [December 14, 2005, 7:49am UTC](https://www.ruby-forum.com/t/habtm-and-date-select-problem/50182/5 "2005-12-14T07:49:46Z")

</div>

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.
