How can i use attribute_fu and treat the first element differently? - ruby-on-rails

I am using attribute_fu with rails 2.2 and I would like to treat the first nested element differently than the rest, meaning I would like to render a different partial or pass a parameter to the existing partial.
Is that possible ?
Thanks,
Cezar

I found the answer to my own question !
For those running into the same problem: you can pass a locals hash like you would pass it to a normal render :partial like so :
<%= f.render_associated_form(#your_model, :locals => {:var => value}) %>
Regards,
Cezar

Related

how to pass and access data to partial view in ruby on rails?

I'm adding a new partial view in ruby on rails project and want to pass some additional data to the partial. I have code below for rendering a view . I understand this is the way to pass data (id in my case) to partial view. I'm not sure if this is the best way, as I'm new to rubyonrails. How do i access in my partial view file?
render "index" , :locals => {:id => params[:id]}
You can pass data to your view(s) using options on render, one of which is locals, or by setting instance variables which automatically propagate.
Normally what's done is something like this:
#id_param = params[:id]
Where within your view you can use #id_param wherever and whenever:
<%= #id_param %>
I've chosen #id_param for a name here instead of #id to give it a bit more context as #id on its own might prompt questions of "What ID?"
If you want to do the locals method, then:
render 'index', locals: { id: params[:id] }
Using the Ruby 1.9 hash notation for simplicity here, versus the outdated 1.8 style in your original example. This produces a local variable called id that can be used in that view, like:
<%= id %>

Questions about Rails render call

When seeing in the code the following lines :
<%= render :partial => 'ingredients/form',
:locals => {:form => recipe_form} %>
I wonder what is actually happening.
I have noticed render is a part of RenderingHelper. How do I know which object I can use while writing? How can I use it without RenderingHelper prefix as in Java (i.e. RenderingHelper.render). Am I inheriting from it in the form view?
Since I know Java and C#, I have searched for ingredients/form and couldn't find it in the code. I am guessing it is part of the convention over configuration rule. What is it? Where is it defined?
Regarding the :locals => {:form => recipe_form} line, is that a parameter sent to render? Is that double assignment? What does the => operator actually do here?
If it is a parameter it was hard to understand from the render signature:
Returns the result of a render that's dictated by the options hash. The primary options are:
:partial - See ActionView::PartialRenderer.
:file - Renders an explicit template file (this used to be the old default), add :locals to pass in those.
:inline - Renders an inline template similar to how it's done in the controller.
:text - Renders the text passed in out.
In the future, please try to ask one question per post.
RenderingHelper is a module, and its methods are made available via an include somewhere. Read more about how Ruby's modules work.
Partial filenames are always prfixied with an underscore, your partial will be located in app/views/ingredients/_form.html.erb
Both :form and :locals are keys in an options hash being passed to render; The corrpsponding value for :locals is a nested hash, which contains one key, :form whose value is a local variable named recipe_form. This might be more obvious if you explicitly specify some of the optional punctuation:
<%= render({:partial => 'ingredients/form', :locals => {:form => recipe_form}}) %>
Ruby (and Rails specifically) use variable length lists of arguments in the form of key/value hashes. They aren't hard to use or understand at all once you understand the basic syntax
2. "ingredients/form" isn't code--it's a string. It refers to the _form partial for the ingredient model. It's located in app/views/ingredients/_form.erb.html.
3. :locals => { ... } means the render function is getting a map entry with the symbol :locals as its key. render knows what to do with that map.
It's not "double assignment", it's that the value of the :locals key is also a map. =>, or the "hash rocket", is Ruby 1.8/1.9 syntax for assigning a map value to a map key. In Ruby 1.9 you can use a shortcut, locals: { ... }.
(IMO which is more readable depends on the values--when the values are keys, I think the new syntax is heinous, otherwise I like it.)
4. How is the signature difficult to understand? The argument is a hash of options.

How to upgrade the :update=>'div_id' option of remote_form_for from Rails 2 to Rails 3?

I can't figure out how to upgrade this code from Rails 2 to Rails 3:
<% remote_form_for(item, :update => 'div_id') do |f| %>
...
I tried this:
<%= form_for :item, :remote => true, :url => { :controller => "items", :action => "create" }, :update => 'div_id' do |f| %>
...
It creates the new item but it fails in updating the content within <div id="div_id"></div> tags. It seems Rails 3 no longer supports the ":update" option for a remote form_for. Any suggestion?
You could use RJS, but that's being deprecated too (and for good reason). The simplified, best-practices way to handle this in Rails 3+ is as follows (assuming jQuery):
# your_view.html.erb
<div id="receiver-id"></div>
<%= form_for :some_model, :remote => true, :id => 'form-id' do |f| %>
...
<% end %>
# application.js (or any other .js loaded on the page)
$(function(){
$('#form-id').bind('ajax:success', function(xhr, data, status){
$('#receiver-id').html(data);
});
});
The ajax:success hook gets called by the jquery-ujs (aka jquery-rails, aka rails-ujs) remote link/form handler. See for yourself. There are lots of other callbacks/hooks available for you to use, too. If you wanted to make this even more flexible, you could use live instead of bind, and bind to a class that dictates where the ouput goes (e.g. "sidebar") and then all remote links/forms with the sidebar class would have their HTML response go to div#sidebar.
The most straightforward way to do this would be to write a javascript view template, e.g. create.js.erb which would look something like this:
$('#div_id').html("<%= escape_javascript(render(#item)) %>");
(depending on your setup, of course, I'm assuming an #item variable and an associated _item partial)
Edit:
coreyward is right. This is the RJS way which is more of the old fashioned Rails 2.x "Rails way". It's probably more familiar, but has issues. Your specific case is one of them, actually, as typically you might bind to an HTML element to update using the record's id (e.g. div #item_1), and in the create case there is no id available beforehand, complicating matters.
Binding via clientside JS eliminates this issue. RJS works in something of a vacuum, making assumptions about the state of the client's HTML and having no access to it.
I know the question is old but I when migrating to Rails 3 I found a pretty good way of doing this, so I thought I would post it here in case anyone else is in a similar solution.
In layouts/update_page.js.erb I put this file:
$j('#<%=#update_div_id||"list_div"%>').html('<%= escape_javascript render(:partial => (#partial_div||"index"), :locals => #local_hash) %>');
This is mainly used for searches that use remote, so in the index action in the controller, I just added the following code.
respond_to do |format|
format.html
format.js {render 'layouts/update_page'}
end
Since remote is being used, it will always try to use javascript first, so it will render the update_page.js.erb file from above. For us, we almost always use the div#list_div on our index pages, so we update that by the default, however if you need to update something different, you can pass in #update_div_id, and if you need to render a different page, you can pass in #partial_div.
To clarify, for a lot of things, it is probably better practice to use the callbacks, but I found this to be a much easier way, when we had to migrate over nearly 100 of these calls.

How to render partial in lib ruby class using render_to_string

I am writing a custom tag for Liquid and want to render a partial in the tag. I am assuming I have to use render_to_string but I can't seem to get it to work.
I've tried all sorts of things, including:
ActionController::Base.render_to_string(:partial => 'path/to/partial')
But nothing seems to work. There has to be some easy way to do this that I'm missing.
Thanks in advance.
The render_to_string method is an instance method:
ActionController::Base.new.send(:render_to_string,
:partial => 'path/to/partial')

Rendering a Heterogeneous Collection: How can I specify a single directory for the partials?

I have a collection, #comments, that is heterogeneous but hierarchical. Each comment is either an instance of Comment or some derived class, like ActionComment or InactionComment. I am rendering a different partial for each type of Comment. The View code is:
= render #comments
As all the partials are related, I would like to keep them in a single view directory, i.e.:
app/views/comments/_comment.haml
app/views/comments/_action_comment.haml
app/views/comments/_inaction_comment.haml
But right now in order to use the automatic rendering of the correct partial, I am using separate directories, like:
app/views/comments/_comment.haml
app/views/action_comments/_action_comment.haml
app/views/inaction_comments/_inaction_comment.haml
Rails 3.2 makes a Model#to_partial_path method available which allows you (as its name suggests) to override the partial pathname.
def to_partial_path
self.action.to_s
end
The path it returns does not include the leading underscore and is assumed to be relative to .../views/modelname/. See http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/ for an overview
You can't do it quite as magically, but you can do it by just rendering each item individually and specifying the partial.
example in haml:
- #comments.each do |c|
= render :partial => "comments/#{c.class.to_s.underscore}", :locals => {:comment => c}

Resources