views:

5250

answers:

1

Hey Rails People,

I'm somewhat of a Rails newbie. I'm writing a couchrest-rails app, so am not using activerecord for this model. I just figured out that that means that

form_for(@model)

won't work. I'm trying to work out how to use form_tag -- but most of the examples don't involve new & create actions.

This is wrong:

<h1>New article</h1>

<% form_tag new_article_url(@article), :method => :post do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', articles_path %>

Because when I run my Cucumber scenario, I get this:

Scenario: Create Valid Article                            # features/article.feature:16
  Given I have no articles                                # features/step_definitions /article_steps.rb:8
  And I am on the list of articles                        # features/step_definitions/webrat_steps.rb:6
/home/deploy/www/www.trackingplace.com/app/ccc/app/views/articles/new.html.erb:3: warning: multiple values for a block parameter (0 for 1)
from /usr/local/lib/ruby/gems/1.8/gems/actionpack-2.3.3/lib/action_view/helpers/capture_helper.rb:36
When I follow "New Article"                             # features/step_definitions/webrat_steps.rb:18
  You have a nil object when you didn't expect it!
  The error occurred while evaluating nil.error_messages (ActionView::TemplateError)
  features/article.feature:19:in `When I follow "New Article"'

But I don't understand the error, or how to fix it.

+5  A: 

The form_tag method does not use a form builder, so you can't use the "f" variable in the form block. Instead of f.error_messages you have to use error_messages_for, etc.

<% form_tag new_article_url(@article), :method => :post do %>
  <%= error_messages_for :article %>

  <p>
    <%= label :article, :title %><br />
    <%= text_field :article, :title %>
  </p>
  <p>
    <%= submit_tag 'Create' %>
  </p>
<% end %>

That said, you can use form_for with non ActiveRecord objects, they just need to respond to certain methods. Ensure that these methods are implemented in the Article model.

  • id
  • new_record?
  • to_param
  • errors

That's just a guess as to what is needed, there may be others. If these are implemented and behave like ActiveRecord does you should be able to use form_for.

ryanb
Thanks Ryan.If I decide to add support for form_for to my models - any suggestions on how to confirm the complete set of methods needed?
marfarma
I don't know of a way in Rails 2 to determine the "complete" set of necessary methods. If you do some tests and don't get method_missing errors it is probably good. Rails 3 will introduce a documented way to do this and offer an established interface for you to define in the model.
ryanb
Ok -- now I'm too lame to figure out how to access the form values!In my controller I have: def create @article = Article.new(:title => params[:article])But that doesn't work. I get the following when I try to use it internally to initialize the class:And I press "Create" # features/step_definitions/webrat_steps.rb:14 undefined method `downcase' for {"title"=>"Spuds"}:HashWithIndifferentAccess (NoMethodError)Any clue?
marfarma
Does Article.new(params[:article]) work?
ryanb
`downcase' for {"title"=>"Spuds"}:HashWithIndifferentAccessBased on that error, I can only assume that it's storing the value, "Spuds" in the title parameter as type HashWithIndifferentAccess instead of type String.Since it's couchdb model, it's not validating the type before assigning it -- something I suppose I could add to the model. But I'm at a loss right now on how to proceed. I've never heard of HashWithIndifferentAccess before and am just reading about it now.
marfarma
(NoMethodError) ==> that error
marfarma
The parameter is "article"=>{"title"=>"Spuds"} (checking my log, so it seems like it's exactly what I thought -- title is getting the hash {"title"=>"Spuds"} assigned to it, which doesn't have a downcase method.Still searching.
marfarma
Right, params[:article] is a hash of attributes for the model. Did you do "Article.new(params[:article])"?
ryanb
Yes, I did Article.new(params[:article]) -- but my model doesn't already understand how to unpack that hash of attributes -- I have to write that bit -- and I'm failing miserably. Maybe I should find the code that ActiveRecord uses and read it. ....... how to find that bit .......
marfarma
OK -- I finally got it to work.<br><br> @articlehash = params[:article].to_hash @article = Article.new(:title => @articlehash["title"])<br>I'll worry about the 'best' way to do it, once I get the full set of REST actions to work. I only have 'show', 'edit', 'update', and 'destroy' to go.
marfarma