How does rails choose which version of an instance variable to render? - ruby-on-rails

I'm fairly new to rails & I'm trying to understand why rails chooses one version of an instance variable over another.
In the controller I have my instance variables defined.
def show
#discussions = Discussion.all.order('created_at desc')
end
def new
#discussion = current_user.discussions.build
end
If I were to call #discussion in one of my views, which version of the variable would it choose?

Each action in the controller (show and new) correspond to and render views with the same name. So, your show method in the controller renders app/views/controller_name/show.html.erb, unless you tell it otherwise by calling render explicitly.
The only instance variables available to show.html.erb are the ones defined in the show action of the controller. The same goes for other actions.

I'm also new to rails, but let me take a crack. I think in both cases, #discussion will be the same thing, the one which it is assigned to. So in your code snippet, if you make a GET call to /controller_route/new it will show you exactly what you intended - current_user.discussions.build.
If you make a GET call to /controller_route, it will be nil, since you haven't defined it. #discussions has no bearing on the evaluation.
But again this is my guess; Would be glad to be educated/corrected on this.

Related

After create, redirect to edit_path instead of show path

Problem is simple (solution is not): I would like to redirect to edit path after X model is created (I'll apply this to multiple models).
Are there any way to do it? I'm digging in source code, trying to find a reference to created instance, but can only find instance variables named after model (like #user, which is harder to make generic).
So far, I found this answer which partially solves my problem: https://stackoverflow.com/a/22486025/312907
I'm still missing a reference to created model object.
The created model object is accessible in the controller method as variable resource.
You can redirect to edit action after creating the object from with in the controller itself
for example
def create
#x = X.new(x_params)
if #x.save
redirect_to edit_x_path(#x)
else
render 'new'
end
end

Ruby on rails, pass an argument from one action to another

I have two actions in my controller:search, show_db.
say, they look like this:
def search
#uploads=current_user.uploads
end
def show_db
end
I need to pass arguments (#uploads) from search-action to show_db-action. (I know I could write #uploads=current_user.uploads in show_db, but I cannot, it is much more complex.)
smt like this:
def search
#uploads=current_user.uploads
show_db(#uploads)
end
def show_db(list)
blablabla
end
Is it possible to do?=)
Many thanks in advance.
If you want to pass the result of one method to another it's pretty simple in Ruby, your second code block should work, you just need to use the list variable from the parameter in your method
def show_db(list)
x = list
list.do_somethings
etc
end
Create a third method that knows how to create #uploads, use it from both actions.
Also, if in your index action you want to render show_db with #uploads variable, you can do this:
def search
#uploads=current_user.uploads
if something
return show_db(#uploads)
end
end
def show_db(list)
blah
render 'show_db'
end
But in this case, show_db is just a method, not a controller action.
You probably want to use a variable across actions. You should know that each time you make a request from browser, you are creating a new instance of controller. Hence, your variables would not work as they should because you will actually be trying to access an instance variable across instances. An impossible task.
I suggest using sessions to store information across multiple requests.
Google up how to use sessions.

Custom Controller variable in application.html

User Story:
Action for Facebook that has open graph object.
For this I need to modify the tag defined in application.html
Problem:
The logic would need to be defined in helpers or the application_controller
From my understanding this is not clean.
Question:
I want to pass variables directly into the application.html view.
Preferably pass those variables from a custom controller into the application.html. This way I can still utilize the rails routing system to only pass those variables when I am on the facebook action.
The common mechanism for passing variables in to the view is to create instance variables in your controller as these are ported over automatically.
This is the standard approach if it is almost certain they will be used. For things that may not be used, create a helper method that will take care of providing them.
This is the difference between doing this:
def show
#facebook_graph = ...
end
And this in a helper:
def facebook_graph
...
end

Trash implementation in rails app

In my app I'm trying to implement trash for some objects, i.e. there will be column "trashed" and it'll set to date, when the object was trashed. Trash also has an index page, where users can restore objects - set "trashed" to nil.
I found examples of models with method trash!, that set trashed to date and it was implemented with Concerns. But I don't really understand how to implement controllers with action to_trash? Is there any way to use Concerns with controllers too or every controller should have it's own action and route for calling it?
Now I implemented it with controller Trash, that have action move_to_trash and every controller use this action, but I have to add get params trashable_id and trashable_type to do this. Is it a good way to do things?
I think the simplest implementation could be to add to your routes.rb file the following:
match ':controller/:id/trash', :action => :trash
This will allow you to use the action trash on every controller. Have a look at the Routing Rails Guide for more examples.
A simple implementation is the following (taking the model Report as example). I don't use Concern here:
class ReportsController < ApplicationController
def trash
#report = Report.find(params[:id])
<Do the trashing of report here, you know that already.>
# Decide what to do after having called #trash
respond_to do |format|
format.html { redirect_to(reports_url) }
end
end
end
If you have only some controllers that should allow the action, it is perhaps easier to add special routes rules for each controller, instead of adding it to every one. And if you want to go a step beyond, you may implement the trash action in a mixin, and mix it in the controller you want to have it in (and no, I don't will implement that, too).

Passing from using '#user' to using 'user' in 'html.erb' files: how and why?

I am using Ruby on Rails 3 and I was advised (#user is a global variable, you can't 'localize' it. I would suggest passing local variables from your controller in the same way.) to use variables like user instead of #user in view files. Why to do that, exactly?.
So, I am considering pass from using #user to using user. That is, (in html.erb file) from using
#user.name
to using
user.name
At this time, for example, in the show method of my controller I have:
def show
#user = Users.find(1)
...
end
What I have to change in the controller to do that works in views?
This is only something you need to worry about when the same partial is called in the views from more than one controller.
Having a partial that is using #user in it (likely set in a users_controller), means that the moment you call that partial in a view from some other controller (for example; accounts_controller) that does not set #users you will get an error. If you reference only local variables in your partial you can set them as needed from any controller with the :locals hash that was described.
That's non sense, only instance_variables are sent from the controller to the view.
Nikita Rybak was not wrong in his answer, he just passed the instance variable contained in his view (#current_user) to a partial where it has a different name (user):
:locals => { :user => #current_user }
he concluded very well:
Local variables are local, so you don't need # to refer them.
Indeed you have two choices when working with a partial:
assume it has access to the instance variable (which is not advised)
pass the instance variable to the partial with a local name which is the Rails' way
Take a look at this Rails Best Practice. Using local variables is preferable way when rendering partials (those view files which start with a _). That's because you'll need review your controller's code to know about instance variable.

Resources