need to pass parameter from controller to .html.erb file - ruby-on-rails

My controller code:
def description
product = #products.find(params(:id))
end
This is in the controller and I have to pass the product variable to description.html.erb. How can I do this?
It is giving me an ArgumentError in StoreController#description.

In general the way variables from the controller get passed to the views is by assigning them as an instance variable, which are variables defined with an # before it, e.g #products. If you want the product variable to be passed along, it has to be set as #product, like so:
#product = #products.find ...
In this particular case, you are getting an error raised before your view even is called. The only line in your controller action is throwing this.
Make sure that #products is actually being set. It's not being set in the #description method, so is it being set in a before_filter here? Is #products able to call #find? In Rails we often only see a model calling this method, e.g Product.find(params[:id]).
Further more, I see that you're accessing your params hash with regular brackets instead of square brackets. In Ruby you use square brackets. This alone may be what's causing the error. Try changing that to:
#product = #products.find(params[:id])

You can pass variables from controller to views using #
example in controller :
#my_var = 'toto'
in view
<%= #my_var %>

Related

Rails Controller Confusion

this is my first post.
I'm brand new to Rails and I'm attempting to learn how to use it. To be clear, I have a brushing familiarity with Ruby. I'm pretty sure I get the MVC structure, but I'm having trouble understanding certain behaviors I'm experiencing.
Just in case anyone learned from the same source, I'm watching Derek Banas explain it. He explains the thing I'm having trouble with around 16:20. https://www.youtube.com/watch?v=GY7Ps8fqGdc
On to specifics- So I placed this line in my routes.rb file:
match':controller(/:action(/:id))', :via => :get
and I created an instance variable in the controller using this:
def sample
#controller_message = "Hello From The Controller"
end
And in a sample view I created, I call on the "controller_message" variable like this:
<%= "#{#controller_message}" %>
And it works on that one view half the time. Now from what I understand, I should see "Hello From The Controller" anywhere that line of code is placed in a view, right? Maybe I just don't understand how this functions, but I made other view files in the same directory in an attempt to see how controllers pass data to views. They load and everything, but I'm not getting the message from the controller. Sometimes, seemingly inconsistently, the controller message won't even display on the first view where it worked originally, especially if I navigate around the site a little. To get it to display that message again, I have to restart my server.
So am I just misunderstanding how MVC works, or is my software glitching (unlikely, I know), or what? I'm so confused.
I've heard so many great things about this community. Thanks in advance to anyone willing to help me. I'm so stressed out.
The #{} in <%= "#{#controller_message}" %>is string interpolation. The usual convention of displaying an instance variable in a view is simply <%= #controller_message %>
The variable #controller_message, declared in the sample method, makes that variable available to the view associated with that method. By default, rails will look for a corresponding view file that has the same name as the controller method, so in this case it will look for a view called sample.html.erb in the app/views/your_controllers_name folder
Well, to clarify things (because your question is a little vague): rails does a lot of stuffs behind the scene, like relating controller's name with view's name. That is why, in most case, you don't invoke a view to be render in controller's method (Rails does that to you based on file's name). So, would make sense the variables declared in a controller method be displayed only in the view with the same name as the controller method called. If you want to display a variable in a view that is not related with the controller method, you should invoke that view with methods like Render and Redirect, and pass the variables as arguments to those methods.
I.g:
other.controller
def edit
render "/another_view_folder/example.html.erb", #variable_to_be_displayed
end
Another thing:
<%= #controller_message %>
This is enough to display the variable. The way you were doing was Interpolation (use to concatenate variable with strings).
I hope I can help you!
Rails will implicitly render a view file if it is found in the view path.
So given:
# config/routes.rb
get 'foos/bar'
# app/controllers/foo_controller.rb
class FoosController < ApplicationController
def bar
#controller_message = 'Hello'
end
end
Rails will attempt to find the file bar.html.erb in app/views/foos when we request /foos/bar. If we want to render another view we need to tell rails to render it explicitly.
class FoosController < ApplicationController
def bar
#controller_message = 'Hello'
render 'some_other_view' # renders app/views/foos/some_other_view.html.erb
# or
render 'some_other_folder/some_other_view' # renders app/views/some_other_folder/some_other_view.html.erb
end
end
Now from what I understand, I should see "Hello From The Controller" anywhere that line of code is placed in a view, right?
No. Lets say you add another controller and view.
# config/routes.rb
get 'people', to: 'people#index'
# app/controllers/people_controller.rb
class PeopleController < ApplicationController
def index
end
end
# app/views/people/index.html.erb
<h1>The message is: <%= #controller_message %></h1>
It will just render The message is:. Since PeopleController does not set the instance variable #controller_message. Ruby will not raise an error if you reference an unassigned instance variable.
The way to reason about this is that the controller in Rails packages all its instance variables and passes them to the view context so that we can use them in the view.
After the controller has finished rendering it sends the rendered template and the program exits*. Instance variables, local variables etc, do not carry over to the next request.

Get controller with a path

At this time i'm trying to get the controller with a path as a parameter
Then what I need is a method that returns the controller, something like
<%= get_controller(users_path) %>
Thanks
Let me introduce you to ActionDispatch's recognize_path:
Rails.application.routes.recognize_path(users_path)[:controller]
=> "users"
Please note that if you are outside a controller or view (such as in a model or in the console, for example), you need to first include Rails.application.routes.url_helpers before passing named helpers to the method. String routes ("/users" in this case) will work in any case.

Helper method with the same name as partial

I have a helper with a method named search_form like this:
module Admin::BaseHelper
def search_form(*args)
# my great code here
end
end
To call this method in my HAML code, I can do this:
= search_form
= search_form()
= search_form(param1: "value1", param2: "value2"...)
My problem is with this first call. When I do this in any HAML file, it renders my helper. Except if my file name is _search_form.html.haml. Is that case, it returns nil.
If I put a raise error in the helper, I notice that my method isn't being called, but I am not able to find what is being called and why.
If I use the syntax on the second and third lines, it works as expected by calling my helper method.
So my question is: is this standard Rails behavior or a bug?
By default, Rails will look for a local variable with the same name as your partial, which may conflict with existing method names.
One way to get around this is to simply redefine the method inside your partial:
<% search_form = self.search_form %>
# Rest of the partial's code

Creating a form Ruby on Rails

I'm trying to create a form on my website but I get this error:
undefined method 'model_name' for NilClass:Class
says the error is on line #33.
On line 33 I've got <%= form_for #try do |f| -%>
A view does not exist in isolation. You need to have your controller set up all the variables that you might need in the view.
So, assuming this is an edit view, you'll need to have code in your controller's edit action, something like this:
def edit
#try = SomeModel.find params[:id]
end
This will set up the #try variable and provide it to the view.
The #try variable must be nil. How is it set? Are you certain it will always contain a valid object?
You need to link your form to a specific model. In your controller, what code is defining #try? Whatever it is seems to be failing to specify a new or current model instance.
If you are using the code in new.html.haml or new.html.erb view file
def new
#try = ModelName.new
end

Passing a model attribute to a Rails view using redirect_to

I'm trying to pass a model attribute to a view, after successfully setting it to a new value from inside an action in my controller. But this variable is always nil by the time it gets to the view, so I can't use it to conditionally display stuff. I should add that this attribute is not a field in the database. What am I missing/doing wrong?
Here is the code in my model:
attr_accessor :mode
#getter
def mode
#mode
end
#setter
def mode=(val)
#mode = val
end
...in the controller:
#report.mode = "t"
redirect_to edit_report_path(#report)
...and in my view:
<%= build_report(#report.mode) %>
...but this helper method never gets the variable I just set in the controller. It is nil. What gives? Clearly I'm missing something basic here because this seems like it should be straightforward. Any insight would be greatly appreciated.
Thanks.
edit_report_path generates a URL with the ID of #report in it.
redirect_to essentially creates a whole new request, and goes to that URL. When it gets to edit, all it has is the ID. Usually that's fine - it looks up the object and keeps going, but of course it's not going to have the non-db field you set.
There are a couple ways to fix this. You can use :render instead to get to the edit page - then #report will have the field set.
#report.mode = "t"
render :action => edit and return
Or, you can make mode a database field.
The problem here is in the redirect_to. When you redirect somewhere else all instance variables are lost. So when you set #report.mode = "t" it sets the attribute. But when you redirect that data is lost.
I am assuming the <%= build_report(#report.mode) %> is in edit_report.html.erb and the code from when you set 'mode' is not in the edit action. If this is the case you may be able to pass the report.mode to the edit action in the url like so:
build_report(#report.mode, :mode => "t")
The problem is the redirect_to; you're returning a response to the client that causes it to redo the request with a different url. In that second request the mode isn't set because you didn't save it before wrapping up the first request.

Resources