Rails: Content_for in partial - ruby-on-rails-3

I have something like this in my layout
...
<%= yield :test %>
...
<%= render :partial => 'user/bar' %>
And in user/bar.html.erb I have
<% content_for :test do %>
stuff
<% end %>
And this doesn't seem to work. And I have found out that yield :test executes before partial, but after executing the view of the action. Why does it do so and what can I do?

The syntax content_for :test do ... end captures the content of the block, and content_for :test gives the captured block. doc for content_for.
In your code, the restitution is done before the capture, so it cannot work.

I wrote the partial into a local variable before calling yield, and then rendered it into the document later:
...
<% partial = render(:partial => 'user/bar') %>
<%= yield :test %>
...
<%= partial %>

Related

Passing an instance variable into a form - rails

This is likely an error due to my minimal understanding of Rails and how to use variables across models, so if there is more code needed to answer it or if my terminology is incorrect, let me know and I will gladly update the question.
I have a feed of posts that I want a user to be able to "like." While the following code allows likes to work on an individual post's page - site.com:3000/posts/*post.id* - with the form data being passed of like[liked_post_id]:*post.id*, when I try to submit a like on a profile - site.com:3000/users/*user.id* - which contains a feed of posts, the form data being passed is like[liked_post_id]: (blank value)
How can I pass the post's ID within a feed of posts to the liked_post_id variable in _like.html.erb?
I have noticed that the action of the like form is /likes across the board. Would this will only work when you are on the page site.com:3000/posts/*post.id*? I'm curious if I need to modify the it so that the action of the form is /posts/*post.id*/likes when you are on the page site.com:3000/users/*user.id*
From my post view:
#views/posts/_post.html.erb:
...
<%= render 'posts/like_form' if signed_in? %>
...
Route to proper form:
#views/posts/_like_form.html.erb:
<div id="like_form">
<% if current_user.likes_this?(#post) %>
<%= render "posts/unlike" %>
<% else %>
<%= render "posts/like" %>
<% end %>
</div>
Like from:
#views/posts/_like.html.erb
<%= form_for Like.new, :remote => true do |f| %>
<%= f.hidden_field :liked_post_id, :value => #post.id %>
<%= f.submit "Like" %>
<% end %>
From profile (feed of posts):
#views/users/show.html.erb
...
<%= render #posts %>
...
Likes controller:
#controllers/likes_controller.rb
class LikesController < ApplicationController
before_filter :signed_in_user
def create
#post = Post.find(params[:like][:liked_post_id])
current_user.like!(#post)
respond_to do |format|
format.html { redirect_to root_url }
format.js
end
end
...
User model:
#models/user.rb
...
def like!(post)
likes.create!(liked_post_id: post.id)
end
...
#frank-blizzard has pointed out that my form markup is an issue. On a post's page the generated markup is:
<input id="like_liked_post_id" name="like[liked_post_id]" type="hidden" value="73" />
While on the feed page:
<input id="like_liked_post_id" name="like[liked_post_id]" type="hidden" />
You can do something like this:
<% form_for Like.new, :remote => true do |f| %>
<%= f.hidden_field :post_id, :value => #post.id %>
<%= f.submit %>
<% end %>
The current_user.likes.build(...) part should get out of your view and inside your controller. You are using a current_user.like! method so I guess you have implemented already some method in user model to accomplish this. If not build your like in the create action of LikesController where you can access params[:like].
def create
#post = Post.find(params[:like][:post_id])
current_user.likes.build(#post)
# ...
end
EDiT
You might need to pass your #post variable correctly into your _like_form partials, like so:
#views/posts/_post.html.erb:
...
<% if signed_in? %>
<%= render 'posts/like_form', :post => #post %>
<% end %>
...
This will give you acceess to a post variable inside the partial so you can prepopulate your forms value with its id. See this questions as well Pass a variable into a partial, rails 3? and make sure to read up on how to pass variables correctly to partials. you can debug your views using <%= debug <variablename> %>

How to render content_for with a block in Rails 3?

I haven't been able to find a solution elsewhere. This is the code I'd like to work:
<%= render :layout => "l/run" do %><%-
content_for :error do
-%>Error - Missing arguments<%-
end -%>
<%= render :inline => #api.data.views["html"], :locals => {:result => #result} %>
<%- end -%>
and in l/run:
<%-
...
if readQuery.value?(nil)
-%><%= yield :error %><%-
else
...
-%><%= yield %><%-
...
end
-%>
I feel like this approach should work but am stumped.
Normally this should work
view1.html.erb
<%= yield :error%>
view2.html.erb
<% content_for :error do %>
#your code
<% end %>

Ruby on Rails simple_form_for all.each do

I am using Rails 3.0, Ruby 1.9.2 and the Plataformatec simple_form gem. This code works with a form_for but not simple_form_for:
<%= simple_form_for(#provider) do |f| %>
<% Car.all.each do |c| %>
<div>
<%= check_box_tag :car_ids, c.id, #store.cars.include?(c), :name => 'store[car_ids][]' %>
$<%= c.cost %> | <%= c.description %>
</div>
<% end %>
<div class="actions">
<%= f.submit "New" %>
</div>
<% end %>
How do I get it to work with simple_form_for?
Thanks in advance!
You can't use simple_form right the same way as form_for.
For example ther is no any check_box_tag method in simple_form gem. There is ONLY inuput fields that you can specify with :as option. So your check_box_tag will be converted to
f.input car_ids, ..., :as => :check_box
Checkout Usage, Rdoc and other useful stuff https://github.com/plataformatec/simple_form
The problem was in the controller code.
In the "new" controller action I can't simply perform:
#provider = Provider.new(params[:provider])
as one would normally.
Instead I have to process each parameter separately:
#provider.location = params[:provider][:location]
etc...
For the Car check boxes, I add each car_id from the car_ids parameter to the "has_many" cars model association one at a time:
car_ids = params[:provider][:car_ids]
car_ids.each do |cid|
#provider.cars << Car.find(cid)
end
Then I can call:
#provider.save!
And it saves correctly (my initial problem was that it wasn't saving the selected Cars).
For some reason, I was able to figure this out only after posting the question here. Funny how that works.
Thanks all for your replies!

Partial in rails 3 application renders :per_page times while using will_paginate

I am using will_paginate in my rails 3 application.
In my Controller i have a line as
def index
#blogs = Blog.paginate(:per_page => 5, :page => params[page])
end
And in my index.html.erb
<div>
<% if #blogs.size.zero? %>
No Blogs Found
<% else %>
<%= render #blogs if #blogs %>
<% end %>
</div>
<%= will_paginate #blogs%>
And in my partial _blog.html.erb
<% #blogs.each do |blog| %>
<%= link_to blog.title, blog_path(blog.id)%>
<% end %>
When i run the app by $rails s
The partial displays the contents per_page times..
For the first page it displays for 5 times ..
How to avoid so ..
Give me some suggestions...
EDIT
I changed the partial code in _blog.html.erb to
<%= link_to blog.title, blog_path(blog.id)%>
which is the right one as already by default rails 3 will send the collection #blogs to the partial noneed for the loop in the partials ..
When render is passed a collection, it automatically renders the partial multiple times.
Therefore you want your partial _blog.html.erb to just be:
<%= link_to blog.title, blog_path(blog.id)%>
You don't need an each statement there because the render statement takes care of this.
See 3.4.5 "Rendering Collections" in http://guides.rubyonrails.org/layouts_and_rendering.html

Rails 3 controller methods for nested resource don't run

I'm creating nested resources Foo and Bar where Foo has_many Bars and Bar belongs_to Foo
This is the new method in BarsController:
def new
#foo = Foo.find(params[:foo_id])
#bar = #foo.bars.build
end
This is the code for the Bar new view:
<%= form_for([#foo, #bar]) do |f| %>
<%= f.text_field :name %>
<%= f.submit "Save" %>
<% end %>
When I try to load the "new bar" page, rails says that the model_name method cannot be found for value Nil. Curiously, this slightly modified view code works:
<%= form_for([#foo, #foo.bars.build]) do |f| %>
<%= f.text_field :name %>
<%= f.submit "Save" %>
<% end %>
However, when I put a logger.debug statement inside the new method in BarsController, it never runs. rake routes says and the server log confirms that BarsController#new is the action being called, but why won't the code that's inside the new action run? Am I missing something here?
Some changes you could make to make it work:
Bars is nested in Foo not the opposite, so instead of BarsController you should write your new action inside your FoosController as follow:
def new
#foo = Foo.new
#bar = #foo.bars.build
end
Inside your foo model you should have:
accepts_nested_attributes_for :bars
Your view:
<%= form_for #foo do |f| %>
<%= f.fields_for :bars do |ff| %>
<%= ff.text_field :name %>
<%= f.submit %>
<% end %>
Don't forget the create action inside your FoosController:
FoosController
def create
#foo = Foo.new(params[:foo])
if #foo.save
redirect_to #foo
else
render :new
end
end
Finally, pay attention to the validations written in your models! For instance it is possible that some fields (that you forgot to fill during your tests) are necessary for your form to be valid! Happened to me recently!