Forum: Ruby on Rails Whats the best way to do this?

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.
Lance S. (Guest)
on 2006-04-20 19:16
I have an archive that can have 0 or more extra files associated with
it.

I would like to be able to edit the associated files info on the same
page as the archive info.

Listing the extra files info to the edit form is simple enough, but How
do I form the text input fields for easy (or automatic) pick-up in the
update?

Or am I barking up the wrong tree here?
Kelly F. (Guest)
on 2006-04-20 20:03
(Received via mailing list)
First, you may want to check

http://www.catb.org/~esr/faqs/smart-questions.html...

I think you are asking how to display/update a collection of items. When
you
talk about files are you talking about a table that contains information
about files? Do you have a file model (File.rb)? Do you have something
associated with these files, perhaps an archive model (Archive.rb)?

In any case you will likely have a loop in your view to display the 0 or
more files and a loop in your controller to capture the updates.

Please include additional information to get more specific help. Also
you
may want to post code fragments.

-Kelly
Lance S. (Guest)
on 2006-04-20 20:57
Ok, Sorry about the non specific subject title.

Tables are 'archives' and 'extra_files'

Related models:
---------------
class Archive < ActiveRecord::Base
	belongs_to :category
	has_many :extra_file
end

class ExtraFile < ActiveRecord::Base
	belongs_to :archive
end


Archive Controller currently looks like this:
---------------------------------------------
class ArchiveController < ApplicationController
	scaffold :archive

	def list
		@header = "Test List"
		@subheader = "Everything in the database. Using Adam's layout"
		#@programs = Archive.find_all
		@program_pages, @programs = paginate :archive
	end

	def edit
		@program = Archive.find(@params["id"])
		@categories = Category.find_all
	end
end

Now here is the part(s) where I'm at a loss. Below is the edit.rhtml.
I've re-edited the text-input fields so many times, I don't know what I
haven't done yet...

Originaly the text-input fields were named by hand, and mostly didn't
render at all without errors.

You probably don't need the entire edit.rhtml, but I included it all so
you know about where I started from. The relivent part is near the
bottom, near 'Extra Files'

Thanks

edit.rhtml
	<html>
 <head>
  <title>Edit Program Listing</title>
 </head>
 <body>
 <h1>Edit Program Listing</h1>

 <form action="../update/<%= @program.id %>" method="POST"">
  <input id="archive_id" name="archive[id]" size="30"
         type="hidden" value="<%= @program.id %>" />
  <p><b>Title</b><br>
  <input id="program_name" name="archive[program_name]" size="30"
         type="text" value="<%= @program.program_name %>" />
  </p>
  <p><b>Author</b><br>
  <input id="program_author" name="archive[author]"
         size="30" type="text"
         value="<%= @program.author %>" />
  </p>
  <p><b>Format</b><br>
  <input id="program_format" name="archive[format]"
         size="30" type="text"
         value="<%= @program.format %>" />
  </p>
  <p><b>Reference</b><br>
  <input id="program_reference" name="archive[reference]"
         size="30" type="text"
         value="<%= @program.reference %>" />
  </p>
  <p><b>Release Date</b><br>
  <input id="program_release_date" name="archive[release_date]"
         size="30" type="text"
         value="<%= @program.release_date %>" />
  </p>
  <p><b>Description<b><br>
  <textarea id="program_description" name="archive[description]"
         cols="40" rows="20" wrap="virtual"
><%= @program.description %></textarea>
  </p>
  <p><b>Misc (extended Description)</b><br>
  <textarea id="program_misc" name="archive[misc]"
         cols="40" rows="20" wrap="virtual"
><%= @program.misc %></textarea>
  </p>
  <p><b>Baud</b><br>
  <select id="program_baud" name="archive[baud]">
  <% ['2000','300','2000 BlueRam'].each do |baud| -%>
  <option <%= 'selected' if @program.baud == baud %>><%= baud
%></option>
  <% end -%>
  </select>
  </p>
  <p><b>Archival Status</b><br>
  <input id="program_arc_status" name="archive[arc_status]"
         size="30" type="text"
         value="<%= @program.arc_status %>" />
  </p>
  <p><b>File Location<b><br>
  <input id="program_file_location" name="archive[file_location]"
         size="30" type="text"
         value="<%= @program.file_location %>" />
  </p>
  <p><b>Extra Ram</b><br>
  Yes <input name="archive[ext_ram]"
         type="radio" value="1"
         <%= 'checked' if @program.ext_ram == 1 %> />
  No <input name="archive[ext_ram]"
        type="radio" value="0"
        <%= 'checked' if @program.ext_ram == 0 %> />
  </p>

  <p><b>Category:</b><br>

  <select name="archive[category_id]">
   <% @categories.each do |category| -%>
       <option value="<%= category.id %>" <%= 'selected' if category.id
== @program.category_id %>><%= category.name %></option>
   <% end -%>
  </select></p>

  <p><b>Extra Files</b><br>

  <% @program.extra_file.each do |file| -%>
  Name: <%= text_field "extra_file", "name", "index" => file.id,
"value"=> file.name %>
  Location: <%= text_field "extra_file", "location", "index" => file.id,
"value"=> file.location %>
  <br>

  <% end -%>

<input type="submit" value="Update" />
 </form>

 <a href="/program_downloads/Archive/archive/show/<%= @program.id %>">
Show </a> |
  <%= link_to "Back", :action => "list" %>
<!--  <a href="/program_downloads/Archive/archive/list">
  Back
 </a> -->

 </body>
</html>
Kelly F. (Guest)
on 2006-04-20 21:21
(Received via mailing list)
>Tables are 'archives' and 'extra_files'
>
>Related models:
>---------------
>class Archive < ActiveRecord::Base
>       belongs_to :category
>       has_many :extra_file
>end

Do model operations work properly for you in script/console?
This should probable be:

       has_many :extra_files

(note the pluralization)

>class ExtraFile < ActiveRecord::Base
>       belongs_to :archive
>end

>Archive Controller currently looks like this:
>---------------------------------------------
>class ArchiveController < ApplicationController
>       scaffold :archive
>
>       def list
>               @header = "Test List"
>               @subheader = "Everything in the database. Using Adam's
layout"
>               #@programs = Archive.find_all
>               @program_pages, @programs = paginate :archive
>       end
>
>       def edit
>               @program = Archive.find(@params["id"])
>               @categories = Category.find_all
>       end
>end

I haven't used the scaffold function. I've always generated the
scaffolds.

I guess you are using the update action that comes with the scaffold
function. This is not likely to work, but I can't be sure since I
haven't
done it. It is not likely to work because the scaffold logic does not
handle
relationships to other models. You will need to put your own update
action
in place. In fact, I think you will need to replace all of the scaffold
generated actions with your own versions. You can get a jump start on
this
by using "script/generate scaffold..."

I don't think there is much point discussing the rest until you get an
update action.

-Kelly
Lance S. (Guest)
on 2006-04-20 21:57
Kelly F. wrote:
>>Related models:
>>---------------
>>class Archive < ActiveRecord::Base
>>       belongs_to :category
>>       has_many :extra_file
>>end
>
> Do model operations work properly for you in script/console?
> This should probable be:
>
>        has_many :extra_files
>
> (note the pluralization)
>

Seems to be working fine. Lists properly in both the list and edit
pages.
Will try changing though.....

Changing it caused errors in my listings. Would have to change them too.


<snip>
> I don't think there is much point discussing the rest until you get an
> update action.
>

Generated update function:
--------------------------
  def update
    @archive = Archive.find(params[:id])
    if @archive.update_attributes(params[:archive])
      flash[:notice] = 'Archive was successfully updated.'
      redirect_to :action => 'show', :id => @archive
    else
      render :action => 'edit'
    end
  end
Kelly F. (Guest)
on 2006-04-20 22:41
(Received via mailing list)
Now, your view needs to iterate over the associated items. Here is an
example:
<p>Members:<br/>
<% for login in ordered_members(@group) %>
<%= select_tag('people[]',
options_for_select(user_list_for_select(@group),
login)) %> <br />
<% end %>
<% new_user_select_tag = select_tag('people[]',
options_for_select(user_list_for_select(@group)))
   5.times do %>
<%= new_user_select_tag %> <br />
<% end %>
</p>
This is a ui for adding/removing people from a group.

Note the 'people[]'. These people ids will be delivered to the
controller as
an array.

Here's the update action:

  def update
    @group = Group.find(params[:id])
    Group.transaction(@group) do
      @group.group_members = group_members_from_params(@group)
      if @group.errors.empty? and
@group.update_attributes(params[:group])
        flash[:notice] = 'Group was successfully updated.'
        redirect_to :action => 'list', :id=>@group.period
      else
        render :action => 'edit'
      end
    end
  end


Oh, and here's a related function

 def group_members_from_params(group)
    group_members = []
    unless params[:people].blank?
      params[:people].each do |login|
        unless login.blank?
          gm = (GroupMember.find_by_login_and_period_id(login,
group.period_id) ||
            GroupMember.new(:group => group, :login => login))
          if gm.group_id != group.id
            group.errors.add_to_base(login + ' is assigned to another
group')
          else
            group_members << gm
          end
        end
      end
    end
    group_members
  end


This may be too complicated to use as an example, but I don't have time
to
make it more succinct.

-Kelly
Kelly F. (Guest)
on 2006-04-20 22:50
(Received via mailing list)
Seems to be working fine. Lists properly in both the list and edit
pages.
Will try changing though.....

Changing it caused errors in my listings. Would have to change them too.


Hmmm. Rails has conventions on names so I surprised this works.
Normally:


   - ModelName.rb will access a database table called model_names.
   - Association _collections_ are pluralized, such as has_many :members
   - Non collection associations are singular, such as belongs_to :group


Of course, changing a model association will break other code. I
surprised
the model works. I've been caught a few times with associations defined
backwards, and rails doesn't help you by throwing an exception - it
simply
fails to work. In other words, I used a belongs_to when I should have
used
has_many, or vice versa.
Kelly F. (Guest)
on 2006-04-20 22:53
(Received via mailing list)
I surprised = I'm surprised

(sometime fingers type what they want)
Lance S. (Guest)
on 2006-04-20 23:25
Kelly F. wrote:
> Now, your view needs to iterate over the associated items. Here is an
> example:

Unfortunatly, you were right. Too complex for me to pickout the relivent
information, re: my set-up.

Sorry.

As for the extra_file. I wasn't sure how to name it. It worked that way,
so I left it.

I'm still not sure the input fields on the edit page are named
properly...

Lance
This topic is locked and can not be replied to.