Reputation: 315
Beginner in Rails here by following tutorial by mackenziechild.me. For example, I have created a PostController with lots of method. However, what confuses me is they seem to have the same variable @post. In this case, how do the program actually knows which correct variable it needs to get? Don't they will get confused when the application is running?
class PostsController < ApplicationController
def index
@posts = Post.all.order('created_at DESC')
end
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post
else
render 'new'
end
end
def show
@post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
Upvotes: 1
Views: 65
Reputation: 48599
I have created a PostController with lots of method. However, what confuses me is they seem to have the same variable @post. In this case, how do the program actually knows which correct variable it needs to get? Don't they will get confused when the application is running?
When your browser requests a page, the request is routed to ONE of the methods you defined. That method executes, and that method sets the value of @post. After the response is sent to the browser, rails destroys all the variables that were created.
but we have Post.new, Post.new(post_params), Post.find(params[:id]) I came from a Java background. so this is quite confusing me. They area all being assigned to the same @post
In Java, you can certainly assign three things to the same variable:
int x = 1;
x = 2;
x = 3;
System.out.println(x); #=>3
And, if you have a class named Post you can also assign three different Post objects to the same variable:
Post p = new Post("hello");
System.out.println(p.getText());
p = new Post("world");
System.out.println(p.getText());
p = new Post("goodbye");
System.out.println(p.getText()); #=>goodbye
Each of: Post.new
, Post.new(post_params)
, and Post.find(params[:id])
returns a Post object; additionally they are being assigned to the same variable, so why are you confused by that coming from a Java background?
However, you should also note that Rails uses a language called ruby under the hood, and in ruby variables do not have types, and they do not have to be declared. So, in ruby you can assign different types to the same variable:
some_var = "hello" #String
some_var = 10 #Integer
some_var = [1, 2, 3] #Array
some_var = {a: 1, b: 2} #Hash
If you said that you were confused by something like that, it would make more sense. Yet, what's there to be confused about by even that? There are two simple rules:
Earlier, I said this:
When your browser requests a page, the request is routed to ONE of the methods you defined. That method executes, and that method sets the value of @post. After the response is sent to the browser, rails destroys all the variables that were created.
Internally, the way that works is:
When a url is routed to a certain controller, rails creates an instance of that controller class:
obj = PostsController.new
Rails uses the controller instance to call one of the methods defined in the controller class(the method is determined by the routing):
obj.show
(Just like in Java, there are ways to call a method when you have the name of the method as a String--and it's much easier in ruby.)
The method executes.
After the response is sent to the browser, rails destroys the controller instance:
obj = nil
Upvotes: 0
Reputation: 2451
In rails each action like index, new, show etc
which is a get
method has their corresponding views in the corresponding folder named as the controller
name.
So when a action is called then their particular view is called.
Eg:-
def index
@posts = Post.all.order('created_at DESC')
end
Their should be a view as index.html.erb
in the folder app/views/posts/
and in that view the instance variable @posts
will be accessible.
In this line Post.all.order('created_at DESC')
, Post
model query the database and fetch all the record from the table as posts
and also sort the record in descending order of created _at
column.
Post
model is inherited from ActiveRecord::Base
, due this it can map the posts
table in the database.
def show
@post = Post.find(params[:id])
end
In the above show
method it is querying only one record whose id is in params[:id]
.
Instance variables are accessible in the views so in @post = Post.find(params[:id])
@post
can be used in its corresponding view as show.html.erb
in app/views/posts/
Upvotes: 2
Reputation: 105
Ikanyu, the @post
variable is an instance variable i.e. its scope is limited to the method it is defined in. So the @post
variable defined in new method is different from the one defined in show and the hence these different variables are accessed in the views without any issue.
For more info as to how these variables are passed into view refer to this link:
How are Rails instance variables passed to views?
Upvotes: 0