Forum: Ruby on Rails populating model attribute from one of many lists

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.
A1abbce3456c884c4d827a0b8dc12021?d=identicon&s=25 JP (Guest)
on 2006-05-03 18:56
(Received via mailing list)
I have a model named Project which contains a name attribute, and I
have a second model named Booking which has, among other things, a
date and a Project. (has_many :bookings, belongs_to :project).

When a user creates a new Booking, they have the option of using an
existing Project or creating a new Project. As an added complexity,
when choosing from existing Projects, they can either choose from a
list of all Projects or they can choose from a list of "recent"
projects (Projects associated with Bookings dated within the past N
days). I settled upon the following as a way to present the different
lists of projects:

I added three attributes to the Booking model:

   attr_accessor :recent_project, :all_project, :new_project

The view for creating new Bookings is provided two lists of Projects
(@projects and @recent_projects) which are used to create
corresponding select lists, essentially:

   <%= select :booking, :recent_project, @recent_projects,
:include_blank => true %>
   <%= select :booking, :all_project, @projects, :include_blank => true
%>
   <%= text_field :booking, :new_project %>

There's some validation going on to make sure one of the auxiliary
Projects is set, and finally, the booking model uses a before_save
hook to set the project_id attribute based on these auxiliary
attributes (simplified version below):

   def before_save
      if not self.recent_project.nil?
         self.project = Project.find(self.recent_project)
      elsif not self.all_project.nil?
         self.project = Project.find(self.all_project)
      else
         self.project = Project.find_or_create_by_name(self.new_project)
      end
   end

To make matter trickier, I mangle Project.name before saving new
Projects. In order to make them easier to sort I move leading articles
to the end of the name, e.g., "The Widget" becomes "Widget, The". This
is accomplished using a before_validation hook in the Project model.
(You may have spotted the bug here: if a user enters a new Project
title which happens to already exist and which starts with an article
find_or_create_by_name() gets fooled since the pre-validation mangling
kicks in after the find() but before the create().)

Now I have two questions:

1. Is there a better or standard way of using one of multiple inputs
to populate an attribute of an ActiveRecord model?

2. What would be a smart way to fix the bug described at the end? I
haven't tried overwriting Project.find_or_create_by_name() yet, and
I'm guessing I can just do that, but I thought I'd ask while I'm here.

Thanks for any advice.

-J
This topic is locked and can not be replied to.