Can't get a simple partial to work !#$@#!$!

class StoreController < ApplicationController
def index
@array = [1, 2, 3]
end

end

index.html.erb

render(:partial => “test”, :object => @array)

_test.html.erb

<% for num in test %>

<%= num %>
<% end %>

When I enter the url:

http://localhost:3000/store

in my browser, this is the output:


NoMethodError in Store#index

Showing app/views/store/_test.html.erb where line #1 raised:

You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

Extracted source (around line #1):

1: <% for num in test %>
2:
<%= num %>

3: <% end %>

The error is saying that test is nil. A ruby program:

array = [1, 2, 3]

for num in array
puts num
end

–output:–
1
2
3

My understanding was that when you write:

render(:partial => “test”, :object => @array)

then inside the file _test.html.erb a local variable called test is
assigned the object @array. But in my application, @array is not
nil–it was assigned the array [1, 2, 3] in the controller. Why won’t
rails relent and loop through the array like I am commanding it to do?

I figured it out. I wasn’t careful about where I was putting render().
I variously tried putting it in index.html.erb and in the layout
(layouts/store.html.erb). I ended up with render() in both files: one
specifying :object and one using :collection.
!#$!@#$!@#$!@#$#!@@#$!!@#!!!

views/store/index.html.erb:

<%= render(:partial => “layouts/test”, :object => @array) %>

views/layouts/_test.html.erb:

<% for num in test %>

<%= num %>
<% end %>

To achieve this I use the syntax

<%= render :partial => ‘cart’, :locals => {:mycart = @cart} %>

Then use the variable mycart in the partial

Colin

2009/5/9 7stud – [email protected]

Rick Lloyd wrote:

views/store/index.html.erb:

<%= render(:partial => “layouts/test”, :object => @array) %>

views/layouts/_test.html.erb:

<% for num in test %>

<%= num %>
<% end %>

Sorry, I don’t know what that means, and I still can’t solve my
original problem, which led to the test code in my op. Here is what I
have now:

class StoreController < ApplicationController
def index
@products = Product.find(:all)
end

def add_to_cart
@cart = [1, 2, 3]
end
end

layouts/store.html.erb

<% @page_title || "Store" %> <%= stylesheet_link_tag 'scaffold', 'store2.css' %>
<%= render(:partial => "cart", :object => @cart) %>

views/store/_cart.html.erb

<% for num in cart -%>

<%= num %>
<% end %>

When I go to http://localhost:3000/store in my browser, I get this:

NoMethodError in Store#index

Showing app/views/store/_cart.html.erb where line #1 raised:

You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

Extracted source (around line #1):

1: <% for num in cart -%>
2:

<%= num %>

3: <% end %>

Trace of template inclusion: app/views/layouts/store.html.erb

Colin L. wrote:

To achieve this I use the syntax

<%= render :partial => ‘cart’, :locals => {:mycart = @cart} %>

I think that is supposed to be:

<%= render :partial => ‘cart’, :locals => {:mycart => @cart} %>

Then use the variable mycart in the partial

and that produces the same error:

NoMethodError in Store#index

Showing app/views/store/_cart.html.erb where line #1 raised:

You have a nil object when you didn’t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

Extracted source (around line #1):

1: <% for num in mycart -%>
2:

<%= num %>

3: <% end %>

Trace of template inclusion: app/views/layouts/store.html.erb

RAILS_ROOT: /Users/autie/2testing/dir1/rails/store2

By the way, my file views/store/add_to_cart.html.erb is blank, although
I don’t think that matters since the layout does not yield.

2009/5/9 7stud – [email protected]

True, this (as corrected) works fine for me on rails 2.2.2. Which
version
are you using?

hi,

try this:

7stud – wrote:

<%= render :partial => ‘cart’, :locals => {:mycart => @cart} %>

<%= render :partial => ‘cart’, :collection => @cart %>

Then use the variable mycart in the partial

views/store/_cart.html.erb

<%= cart %>

tom

===============================================================================
Tomas Meinlschmidt, MS {MCT, MCP+I, MCSE, AER}, NetApp Filer/NetCache

www.meinlschmidt.com www.maxwellrender.cz www.lightgems.cz

On May 9, 6:47 am, 7stud – [email protected] wrote:

@cart = [1, 2, 3]

end
end

if you go to /store that’s just the index action so add_to_cart is
never called and @cart is not set.

Fred

Frederick C. wrote:

On May 9, 6:47�am, 7stud – [email protected] wrote:

� � @cart = [1, 2, 3]
� end
end

if you go to /store that’s just the index action

Yes. I realize that>

so add_to_cart is
never called and @cart is not set.

Ok, but if I go to /store/index why does the add_to_cart view ever come
into play? @ variables in other actions are not set when /store/index
executes, so why doesn’t rails throw errors when their views reference
the @ variables set in their actions?

7stud – wrote:

Frederick C. wrote:

On May 9, 6:47�am, 7stud – [email protected] wrote:

� � @cart = [1, 2, 3]
� end
end

if you go to /store that’s just the index action

Yes. I realize that>

so add_to_cart is
never called and @cart is not set.

Ok, but if I go to /store/index why does the add_to_cart view ever come
into play? @ variables in other actions are not set when /store/index
executes, so why doesn’t rails throw errors when their views reference
the @ variables set in their actions?

Ai yi yi. I’m putting the partial in the store layout so all the
store views use it–including the index view.

Thanks.

When you render a partial you automagically get an object with the
same name available in the partial

For example, render :partial => ‘foo’ passes the instance variable
named @foo to the partial where I can then say: for f in @foo.

In your first post you iterate over ‘test’ but that variable isn’t
created anywhere.

Using: for a in @array might work providing that the partial is part
of that controller though. Or rename @array to @test.

I don’t know how many times I have stopped and looked for the
painfully obvious - like with RESTful resources - the key is to make
that part of the trouble shooting.

Maybe you should send the var through each page, you need to store it
and get it by method.
store it:
:locals => {:var = @a}

get it:
var = local_assigns[:var]

AGoofin wrote:

When you render a partial you automagically get an object with the
same name available in the partial

For example, render :partial => ‘foo’ passes the instance variable
named @foo to the partial where I can then say: for f in @foo.

How do you know that @foo isn’t already available to all the views and
that writing render(:partial => foo) doesn’t have any effect whatsoever
on whether @foo is available in the partial?

In your first post you iterate over ‘test’ but that variable isn’t
created anywhere.

Sure it is. Try it. I’m just a beginner but my Dave Heinemeier H.
book says the variable test gets created by the render() statement, and
my tests confirm that’s the way it works. More generally, when I write

<% render(:partial => “random_name”, :object => @var) %>

and @var was assigned a value in the controller, then I find that the
value of @var gets assigned to the variable “random name”, and
random_name can be accessed in the partial _random_name.html.erb. In
addition, my tests show that @var can be accessed in
_random_name.html.erb as well. I’m not sure why you would want to stuff
the value of @var into another variable when you can just access @var
directly. Switching the names seems confusing to me.

On May 10, 6:35 am, 7stud – [email protected] wrote:

random_name can be accessed in the partial _random_name.html.erb. In
addition, my tests show that @var can be accessed in
_random_name.html.erb as well. I’m not sure why you would want to stuff
the value of @var into another variable when you can just access @var
directly. Switching the names seems confusing to me.

because depending on the state of local variables makes your partial
more dependant on its environment. For example if the random_name
partial always used @var you couldn’t use it to render a collection or
if the thing that you wanted to render was @something.something_else.
Personally I mostly equate this to ‘why use method arguments when you
could just use global variables?’

Fred

Perhaps you should look at the whole of DHH wrote. It is perhaps
something like: render :partial => ‘test’ or has a :test => @var
clause to give the test variable.

The code you posted doesn’t contain any variable named test, otherwise
you wouldn’t get the error in the first place.

If you want the code to work, replace ‘test’ in the index view with
@array

If you don’t want help - why post here?

Variable names are special - they don’t just appear and have to be
created. That’s what your error is telling you.

In all your “testing” did you not realize that test wasn’t there?

Hmmm, it seems that “test” is a reserved word in rails…

22 Oct 07 Rails gotchas (reserved attribute or method name)
Some time ago I’ve got a really strange error message when trying to
access a new method in a controller I have created for a rails
application …
In the log the error message was:
“wrong number of arguments (2 for 0)”
the step by step to reproduce this error is:
rails test
cd test
script/generate controller test process
script/server
point your browser to http://localhost:3000/test/process
What really happened?
ActionController has a method named process, and my controller:
class TestController < ApplicationController

def process
end
end
defined a action with the same name, and it messed up with ActionPack

Hasan had a very similar problem but with a reserved attribute of
ActiveRecord
So, if you are having strange problems like these ones, try looking
for a “reserved” attribute or method …
They are not really reserved, but, you have to pay attention when you
redefine a “rails core” method :smiley:
Even if you do not know that you are redefining the method :smiley:

Frederick C. wrote:

On May 10, 6:35�am, 7stud – [email protected] wrote:

random_name can be accessed in the partial _random_name.html.erb. �In
addition, my tests show that @var can be accessed in
_random_name.html.erb as well. �I’m not sure why you would want to stuff
the value of @var into another variable when you can just access @var
directly. �Switching the names seems confusing to me.

because depending on the state of local variables makes your partial
more dependant on its environment. For example if the random_name
partial always used @var you couldn’t use it to render a collection or
if the thing that you wanted to render was @something.something_else.
Personally I mostly equate this to ‘why use method arguments when you
could just use global variables?’

Ah. I see.

AGoofin wrote:

Perhaps you should look at the whole of DHH wrote. It is perhaps
something like: render :partial => ‘test’ or has a :test => @var
clause to give the test variable.

This is what he wrote:


The :object parameter to render takes an object that is assigned to a
local variable with the same name as the partial. So, in the layout we
could call this:

<%= render(:partial => “cart”, :object => @cart) %>

and in the _cart.html.erb template, we can refer to the cart via the
variable cart.

p. 120, AWDWR(3rd)

My tests show that the :partial name can be anything, e.g.
“forrest_gump”, and then inside the file _forrest_gump.html.erb, a
variable named forrest_gump will be available and it will be assigned
whatever value is specified for :object.

In addition, my tests show that all the @variables that are set in the
controller are available in the partial file no matter what I write in
the render() statement. Therefore, a statement such as this:

For example, render :partial => ‘foo’ passes the instance variable
named @foo to the partial where I can then say: for f in @foo.

does not suddenly make @foo available in the partial. @foo is also
available in the partial already. For instance, if I write:

render :partial => “red”

I can still access @foo in the file _red.html.erb.

The code you posted doesn’t contain any variable named test, otherwise
you wouldn’t get the error in the first place.

I explained why I got the error. It was because I ended up with two
conflicting render statements, one in the layout and one in the index
view:

render(:partial => “some_name”, :object => @var)
render(:partial => “some_name”, :collection => @var)

Apparently, that confused rails. The error had nothing to do with the
fact that ‘test’ wasn’t previously defined somewhere in my code.

If you don’t want help - why post here?

Don’t get offended just because a beginner can’t confirm how you say
rails works. I don’t blindly accept what someone says. I test things
out to see how they work for myself. If my test results don’t confirm
what I’ve been told, then I ask questions.

Variable names are special - they don’t just appear and have to be created.

Is it so hard to believe that rails could create a variable when given a
string, like here:

partial => “forrest_gump”

I can do it:

class A
end

a = A.new
str = “forrest_gump”
val = [1, 2, 3]

a.instance_variable_set(“@#{str}”, val)

eval("
class << a
attr_accessor :#{str}
end")

p a.forrest_gump

–output:–
[1, 2, 3]

I don’t know if things work differently in rails 2.3.2, which is what I
am using.

7stud – wrote:
Corrections/clarification:

I explained why I got the error. It was because I ended up with two
conflicting render statements, one in the layout and one in the index
view:

render(:partial => “test”, :object => @array)
render(:partial => “test”, :collection => @array)

Apparently, that confused rails. The error had nothing to do with the
fact that ‘test’ wasn’t previously defined somewhere in my code.