I'm building a webapp that features a UI split into two sides, a menu bar and a content area.
The menu bar has a listing of the titles of all blogs that a user has written. When a title is clicked, the content area should change to show the posts of that blog.
1.) So on my menu bar, I have:
<%= link_to blog.title, blog, :remote=>true %>
And in my content area, I have:
<div id="contenthere"></div>
2.) So by my understanding, this should trigger the show method of the blog controller. There, I have the following in the method:
#blog = Blog.find(params[:id])
respond_to do |format|
format.js { render :show_blog }
end
3.) Which should go look for a file called show_blog.js.erb in views/blogs folder:
$("#contenthere").html("<%=escape_javascript(render :partial=>"show_blog")%>");
Which will take my div with commenthere id and render the _show_blog.html.erb partial (located in the blog view folder) with the blog parameter equal to the #blog parameter that was set in my blog controller.
4.) So my show blog partial has this code:
<%=#blog.title %>
<%=#blog.user_id %>
EDIT: Actually, I search around and found out that I can't use the method 'render' from within the assets folder-- where do I put the js.erb then? I've moved it to the blog view folder, home view folder (index.html.erb), and just the /view/ folder... The error is gone, but the link is not working...
EDIT: Put the show_blog.js.erb in my views/blogs folder, since it's the blog controller calling it. Nothing happening when I click the link and no JS errors shown in console. Is the js being called at all?
EDIT: Changed to reflect my final answer.
#blog = Blog.find(params[:id])
respond_to do |format|
format.js { render :show_blog }
end
That is not Rails default logic.
You didn't provided, how method is called, suppose
def show_blog
#blog = Blog.find(params[:id])
respond_to do |format|
format.js
end
end
Then, Rails will look for show_blog.js.erb in views/blogs and render that file.
Also, you need to pass actual instance to partial, because patrial is stand-alone chunk of code and doesn't know, what #blog is:
$("#contenthere").append("<%=j render :partial=>"show_blog", :locals=>{:#blog=>#blog}%>");
Very simple solution in the end--- The partial was calling for blog.title, blog.user_id, but #blog was the actual param that was passed. Just had to change to #blog.title and #blog.user_id.
Related
I appreciate help with this issue. I have been a bunch and trying different options but to no avail.
I have tasks folder with an index and a form partial that I render on the tasks/index page <%= render"form_tasks" %>. When I submit a task on the index page, everything works fine and the task gets added. I have also included the form partial on a global modal that displays from the nav <%= "tasks/form_tasks" %>. the idea being I want to be able to add a task no matter where you are on the site. Except, if I am anywhere on the site outside of the /tasks folder, I get an error.
ActionController::ParameterMissing in TasksController#create
param is missing or the value is empty: tasks
def tasks_params
params.require(:tasks).permit(:task, :details)
end
in my tasks controller I have
def create
#task = tasks.new(tasks_params)
if #task.save
flash[:notice] = "Task Recorded"
redirect_to task_index_path
end
end
private
def tasks_params
params.require(:tasks).permit(:task, :details)
end
Thanks in advance!
My question is : do we need a view file for each action in our controller?
(like if we defined a say_hello action in a controller, is it necessary to add say_hello.html.erb in his view directory?
I'll edit this to say it depends (with same content). If you plan on using that controller action as JS or JSON you don't need a view file. if you want one to share in multiple views, the file can contain a shared partial (which can be used in other views). This examples is shown by the generators scaffolding create examples like this. They are helpful if you are learning rails. Not great otherwise.
If you were to share a partial, you could have a partial named _form.html.erb and then inside your say_hello.html.erb file, it would just call:
<%= render 'form' %>
If you want to render JSON or JS files you can respond_to in your action:
respond_to do |format|
format.html # say_hello.html.erb
format.json { render json: #hello } #no file needed
format.js { render js: #hello }
#format.js {} #do nothing... or use a little javascript in there...
# or have a file named say_hello.js.erb and use your #hello variable
end
Edit:
One last update. Your say_hello.js.erb file can do the anything on another view (if called remotely):
say_hello.js.erb
<% if #hello.attribute == "some value" %>
$('#div_in_another_view').show();
<% else %>
$('#div_in_somewhere_else').hide();
<% end %>
You can do jQuery and anything you want to the view calling it (as long as it's using AJAX).
End edit
Guides are great place to get started. Railscasts.com as well (even though Ryan isn't updating anymore).
Edit: A great example on the different options on the respond_to is on this rails guide regarding javascript
You can just pass javascript straight from that format.js call, or use a file if you need more complicated stuff. You don't need to do anything also. You could just have it return xml or nothing as well, depending on your use case.
No, it is not required. For example, you can render json or xml data from the controller without needed a view at all. This article explains it very well http://guides.rubyonrails.org/layouts_and_rendering.html
No you do not need a view for each action. BUT you do need a view for each action that will reach the end of the method.
If you return anywhere in the action then you are fine. A view is only required when an implicit render is called due to execution reaching the end of the action.
No, it's really up to you and it depends on what the action will actually do. Actions can render different types content types: text, json, html, xml... etc. Here's an example:
def show
render xml: #something
end
This action doesn't have a view, but it'll output an xml when called. It can also render different things based on the format of the call:
def show
respond_to do |format|
format.html do
redirect_to '/'
end
format.json do
render xml: #something
end
end
end
The action may also redirect (again, this one doesn't have a file):
def show
redirect_to '/'
end
At the end, it's really up to the programmer to handle how the action behaves, but if you leave it empty, it'll assume there's a file to render.
I'm a RoR junior and I'm making online shop app, so:
on the show view of product I have remote form for #line_item
in the show action of products_controller I have #line_item = LineItem.new
I have create.js.erb file in views/line_items
My create action of line_items_controller looks like this:
respond_to do |format|
format.js { }
end
QUESTION: How to make a popup window with line_item's details information appearing when line item's create form is submitted?
You don't need that line in the controller there - all you need is to trigger the display of a popup inside your create.js.erb. That js file will be rendered by convention after executing the create controller method because it is an asynchronous call.
I am writing a Ruby on Rails application with a controller called "pages_controller" that is responsible for displaying pages to users. There are 3 different types of pages that can be displayed, and different things have to happen on the back end in each case, so I decided to break the functionality out into 3 methods within the controller. When the user requests a page, the "show" method is called, which figures out whether the page:
1. Belongs to the user
2. Belongs to another user, and can be viewed by the user requesting it
3. Belongs to another user, and cannot be viewed by the user requesting it (unauthorized)
The appropriate method is then called from there to display the page. The code looks something like this:
def show
if (something)
showMine
elsif (something else)
showAnother
else
showUnauthorized
end
end
def showUnauthorized
respond_to do |format|
format.html # showUnauthorized.html.erb
end
end
def showMine
respond_to do |format|
format.html # showMine.html.erb
end
end
def showAnother
respond_to do |format|
format.html # showAnother.html.erb
end
end
I am getting a template missing error because rails wants to render a view when "show" is called, but I do not want any views to be rendered when "show" is called. I simply want "show" to call the correct method from there, and the corresponding view for that method (showMine, showAnother, or showUnauthorized) to be rendered. How can I do this? Or am I going about this the wrong way entirely?
You need to declare these new actions that you have created in the routes file, as they don't belong to the RESTful routes.
I sugest to keep only the show action in your controller and create the IFs in the show view using the render method to include the partials(_showMine.html.erb, showAnother.html.erb, showUnauthorized)
example:
show view:
if (something)
<%= render 'showMine' %>
elsif (something else)
<%= render 'showAnother' %>
else
<%= render 'showUnauthorized' %>
end
I hope it helps...
I basically agree with Samy's comment, but here's some background:
The method that tells Rails what view to use is render. If there's no call to that method in your show method, Rails assumes you have a view called show.xxx.xxx, e.g. show.html.erb, that is supposed to be rendered. Note that it doesn't assume template will be prefixed with show because that's the name of the method. It assumes it will be show because that's the name of the action. The name of the action is passed to the controller as part of the request; it's not simply derived from the name of whatever method has a respond_to block in it.
All the respond_to blocks do is specify different view templates based on the MIME type of the request, but since you never call render, all of those extra methods are still trying to call the show view (show.html.erb in every case), because you never told Rails to render any other view, and the action name is show.
So, instead of the respond_to blocks, just call render [some_view] in each of your other methods.
This might not be the clearest answer, but I'd suggest also reading the following:
http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/
It describes what respond_to does, in particular how it keys off the action name to determine what view to render.
I think this question might have been asked before, but I honestly don't know how to search for it.
Basically, when I do a render :action => 'edit' in the update action in controller, somehow the view outputs the form as if it's a :action => 'new' page.
form_for gave the wrong action and f.submit gave wrong button text (it gave create instead of update)
edit:
relevant parts of controller
def edit
#user = User.find_by_email(current_user.email)
end
def update
old_password=params[:user].delete(:old_password)
#user=User.new(params[:user])
if User.find_by_email(#user.email).valid_password?(old_password)
logger.info 'Valid old password'
else
flash[:notice]='Invalid current password'
render :action=>'edit'
end
end
As discussed in the comments, #bassneck is right - while you are rendering the edit view, the form_for call looks at whether the object is persisted or not (#user.persisted?). This has the benefit in a lot of cases of being able to use one piece of form code for both new and edit views (I'll generally have a partial _form.html.erb that gets used for both situations).
In your case though, it isn't leading to the desired behaviour - so wwhat you need to do is make sure you're using the relevant user object. If you want to update a user, #user should be the object you want to update.