I want to render a few instances of Post object on a single page.
Currently I have in my controller the code:
#post = Post.find(1)
and in the index view I have:
<%= render :partial => 'posts/post', :object => Post.find(1) %>
Now I want to print the second instance, how to do it? This code for the second instance does not work.
<%= render :partial => 'posts/post', :object => Post.find(2) %>
Couple of things:
When you set instance variable (prefixed with #) in your controller, they're available in your views. So you could do something like:
<%= render :partial => 'posts/post', :object => #post %>
Generally, index actions are meant to deal with a collection (#posts). I'd expect something like:
#posts = Post.where(author: current_user)
If you want to display a post identified by an id, I'd recommend taking a look at CRUD operations: https://guides.rubyonrails.org/routing.html#resources-on-the-web
Roughly, what you may want to do is something like:
# config/routes.rb
resources :posts
# app/controllers/posts_controller.rb
def show
#post = Post.find(params[:id])
end
# app/views/posts/show.html.erb
<%= render partial: 'posts/post', locals: { post: #post } %>
Remember that controllers sets the instance variables, and views use them
Related
i'm building this app where the user should be able to perform all rest actions in the same page. So below a table like the following:
<div class="row">
<div class="col-lg-3">Name</div>
<div class="col-lg-4">Lastname</div>
<div class="col-lg-3">Schedule</div>
<div class="col-lg-1"> </div>
<div class="col-lg-1"> </div>
</div>
<div id="table-body-clients">
<% #clients.each do |client| %>
<%= render :partial => 'client', :locals => { :client => client } %>
<% end %>
</div>
I should include a form to add a new client (same form will then load and edit selected clients. All on remote).
The easiest way i can think is to render 'new' page as a partial. But i don't seem to find the way to call the correct action and/or load the locals correctly.
This did not work:
<%= render 'new', :controller => "clients", :action => "new", :locals => { :client => #client } %>
'new' is actually a partial named '_new'
Anyway, I would appreciate a fix on this code as much as an insight for the right way to approach the issue.
Thanks
should be able to perform all rest actions in the same page
Don't worry about performing actions on the same page - make sure you keep your views structured in the resourceful style of Rails, but call them in the view you want (much the same as you would with partials)
As you have demonstrated, you can do this:
<%= render "clients/new", locals: { client: #client } %>
To give you a caveat here, you need to appreciate that since you're creating a new client, you'll want to build the resource in your controller:
#app/controllers/clients_controller.rb
class ClientsController < ApplicationController
def index
#clients = Client.all
#client = Client.new
end
end
--
As you mention you've got a nested route (IE client belongs to company), you want to make sure you have the following set up:
#config/routes.rb
resources :companies do
resources :clients #-> domain.com/companies/:company_id/clients
end
#app/controllers/clients_controller.rb
class ClientsController < ApplicationController
def index
#clients = Client.all
#company = Company.find params[:company_id]
#client = Client.new
end
end
#app/views/clients/index.html.erb
<%= render "new", locals: {company: #company, client: #client} %>
#app/views/clients/new.html.erb
<%= form_for [company, client] do |f| %>
...
<% end %>
Create a partial _form.html.erb as the following
<%= form_for client do |f| %>
your form fields here
<% end %>
Then, from new.html.erb and edit.html.erb, or whatever page where you need the form:
<%= render "form", client: #client %>
Replace #client with the actual client object you need the form for.
I am trying to render my questions form partial on my posts show page. Right now when i enter text and press post it redirects to the default form and keeps the text.
I am rendering the form like so:
<%= render :partial => "questions/form", :locals => {:question => #comment.questions.new} %>
The questions controller:
def create
#comment = Comment.find(params[:comment_id])
#question = #comment.questions.new(question_params)
end
the form:
<%= simple_form_for [#comment, Question.new] do |f| %>
<%= render :partial => "questions/form", :locals => {:question => #comment.questions.new} %>
this part , :locals => {:question => #comment.questions.new} seems to be useless cause you override it anyway in the form partial with Question.new in the simple_form_for.
create action should have a save call and redirect to somewhere if save successfull or not.
def create
#comment = Comment.find(params[:comment_id])
#question = #comment.questions.new(question_params)
if #comment.save
redirect_to :back
else
# somet actions here
end
end
I am using Ruby on Rails 3.2.13 and I would like to DRY (Don't Reapeat Yourself) my code in controllers e views. That is, at this time...
... in my controller I have:
# ArticlesController
def index
#articles = ...
...
case ...
when ... then render(:partial => 'partial_for_index', :object => #articles, :as => 'articles', ...)
else render :index
end
end
def show
#article = ...
...
case ...
when ... then render(:partial => 'partial_for_show', :object => #article, :as => 'article', ...)
else render :show
end
end
... in my helper I have:
# ArticlesHelper
def render_partial_for_index(articles, ...)
articles.map { |article| render_partial_for_show(article, ...) }.join('').html_safe
end
def render_partial_for_show(article, ...)
render(:partial => 'partial_for_show', :object => article, :as => 'article', ...)
end
... in my views I have:
# articles/_partial_for_index.html.erb
<%= render_partial_for_index(#articles, ...) %>
# articles/_partial_for_show.html.erb
<%= article.title %> created at <%= article.created_at %>
In order to DRY my code I thought to use helper methods directly in controller (note: I know this approach breaks the MVC pattern but it is just an example of what I aim to make and should make the issue to be more understandable), this way:
# ArticlesController
include ArticlesHelper
def index
#articles = ...
...
case ...
when ... then render_partial_for_index(#articles, ...)
else render :index
end
end
def show
#article = ...
...
case ...
when ... then render_partial_for_show(#article, ...)
else render :show
end
end
This way I can delete the _partial_for_index.html.erb view file since it is not used anymore and the code is DRYed and consistent throughout the application. However, whilst the controller show action works as expected, the controller index action does not since I get the DoubleRenderError error because multiple render methods run in the render_partial_for_index helper method.
In few words, I would like to use as less as possible statements for rendering. How can / should I DRY my code in order to reach what I aim to make? That is, how can I make it to work by keeping availability of render_partial_for_index and render_partial_for_show methods in views and controllers the right way?
Actually I don't like your controller because it mixes the logic which should belong to view, and the render_blah methods make things unnecessarily complex.
I prefer this style:
# ArticlesController
def index
#articles = ...
end
def show
#article = ...
end
# views/articles/index.html.erb
<% #articles.each do |article| %>
<%= render partial: 'article', locals: {article: article}
<% end %>
# views/articles/show.html.erb
<%= render partial: 'article', locals: {article: #article}
# views/articles/_article.html.erb
<%= article.title %>
<%= article.body %>
# blah blah
Same effect. DRYer code. Cleaner logic. No helpers needed.
I've followed this Railscast on submitting a form via Ajax and updating a div without reloading the page, but I'm having trouble with one portion of it.
Ryan has $("#products").html("<%= escape_javascript(render(#products)) %>"); in an index.js.erb file to update the #products div when the form is submitted. I'm struggling to understand whether an instance variable like #products is relevant for my situation, or if I can simply substitute it for a URL.
I'm trying to do the same thing as Ryan in this screencast, but instead of display search results I just want to display the updated value.
In show.html.erb I have:
<% #project.project_todos.order("created_at DESC").where(:status => false).each do |todo|%>
<%= form_for todo, :remote => true, :"data-replace" => "#dueon" do |f| %>
<%= f.text_field :due %>
<%= f.submit :class => "primary", :value => "Add" %>
<% end %>
<div id="dueon">
<%= render "duedate", :todo => todo %>
</div>
<% end %>
The partial _duedate.html.erb has one line in it: <%= todo.due %>
So in my index.js.erb I currently have this: $("#dueon").html("<%= escape_javascript(render("_duedate")) %>"); but it's clearly not working. Do I have to use a variable here in place of the _duedate? And if so, how would I set this up in the controller? I mean what does the variable have represent?
Also, for what it's worth, the partial is rendering correctly and displaying the todo.due value...it's just not updating when I submit the form.
ProjectsController:
def show
#project = Project.find(params[:id])
# Display the form to create a new todo
#project_todo = ProjectTodo.new
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #project }
end
end
Try this
in you controller action , (say sample_action)
def sample_action
#todos = #your code
respond_to do |format|
format.js
end
end
and you have a sample_action.js.erb
$("#dueon").html("<%= raw escape_javascript(render(:partial => 'duedate')) %>")
then inside the partial, you have access to the new #todos instance variable
HTH
I will answer you separately as I believe your entire setup should be little change (IMO, this might not be the case)
I think you should have a todos controller with a project belongs to it,
--- models ----------------
class Project < ActiveRecord::Base
has_many :todos
end
class Todo < ActiveRecord::Base
belongs_to :project
end
---- routes ---------------
resources :projects do
resources :todos do
end
end
---- controllers ----------
class ProjectsController < ApplicationController
end
class TodosController < ApplicationController
def new
#project = Project.find(params[:project_id])
#todos = #project.todos.build
end
end
in your view (views/todos.html.erb)
<%= #project.name %>
<%= form_for([#Project, #todos]) do |f| %>
#todo form code
<% end%>
As per the relation, project has many todos, its always clear to show the project details in the todo add screen, rather than allowing users to add new todos from project screen.
and again, this is my personal view, feel free to ask any questions :)
I am running Ruby on Rails 3 and I would like to render a template (show.html.erb) passing a local variable.
In RAILS_ROOT/views/users/show.html.erb I have
Name: <%= #user.name %>
Surname: <%= #user.surname %>
I have also a page controller to handle pages and in the application_controller.rb an istance of #current_user. A page is called user, so in RAILS_ROOT/views/pages/user.html.erb I have
<%= render :template => "users/show", :locals => { :user => #current_user } %>
The above code doesn't work (I get this error: RuntimeError in Pages#user, Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id) but this works:
<%= render :template => "users/show", :locals => { :user => #user = #current_user } %>
I think it is not a good approach to "overwrite" the #user variable. This is because, for example, if I need to recall #user after the above 'render' statement it will don't work anymore.
So, what is a solution in order to render show.html.erb?
I tryed also
<%= render :template => "users/show", :locals => { #user => #current_user } %>
<%= render :template => "users/show", :locals => { :object => #current_user, :as => #user }
but those don't work.
UPDATE
If in pages_controller.rb I put this
def user
#user ||= #current_user
end
it will work and in the view files you can just use
<%= render :template => "users/show" %>
Anyway, I discoverd that I have this error (see below for more info):
ActionController::RoutingError in Pages#user
No route matches {:action=>"destroy", :controller=>"users"}
The error is generated from this form statement located in a partial loaded from show.html.erb:
<%= form_for(#user, :url => user_path) do |f| %>
...
<% end %>
:locals => { :user => #current_user }
and in template
Name: <%= user.name %>
Local variables are local, so you don't need # to refer them.
#user502052
You can render view explicitly from your controller.
render :template => "users/show", :locals => {...}
When you don't execute render in controller, framework does that for you with default parameters. When you do, you can specify different template file, pass local variables, render a partial: anything render function supports.
Just in case you are NOT rendering a partial, and do not want to use :template option, this can also be done in Rails 4 with:
render 'users/show', {user: #current_user}
Url:
http://localhost/pages/user
this will call the user method on pages_controller. You have this:
def user
#user ||= #current_user
end
Rails creates an instance variable #users and by default will try to render a view template at app/views/pages/user.html.erb. If that is not what you want, you have to say so in the controller:
def user
#user ||= #current_user
render :template => "users/show", :locals => { :user => #current_user }
end
This will now render app/views/users/show.html.erb with a local variable called user instead of the default app/views/pages/user.html.erb.
Currently you are waiting until you are inside a view template and then asking to render another view template. Once you are in a view template you should only need to render partial templates:
render :partial => 'users/show', :locals => {:user => #current_user}
Hopefully that helps clarify.