How to render content_for with a block in Rails 3? - ruby-on-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 %>

Related

ActiveAdmin - Pass locals to form

In my photos.rb file I have:
ActiveAdmin.register Photo do
form :partial => 'admin/forms/photo', :locals => { :events => Event.all }
end
In my _photo.html.erb file I want to be able to access the value of events, but it doesn't seem to be detectable. How can I do this?
As requested in a comment, here is my form:
<% if events.any? %>
<%= form_for [:admin, #photo], :validate => true do |f| %>
<!-- insert a bunch of standard field divs here -->
<div class="actions" style="margin-top: 20px">
<% if #photo.new_record? %>
<%= f.submit 'Create photo' %>
<% else %>
<%= f.submit 'Update photo' %>
<% end %>
</div>
<% end %>
<% else %>
<div style="font-size: 14px">
You cannot add photos until you have added at least one event.
</div>
<% end %>
The error message I am getting is around the events.any? line:
Completed 500 Internal Server Error in 108ms
ActionView::Template::Error (undefined local variable or method `events' for #<#<Class:0x007fdb8e841b80>:0x007fdb8a93e7a8>)
form do |f|
f.render partial: 'admin/forms/photo', locals: { f: f, events: Event.all }
end
Note that you will need to remove form_for, semantic_form_for, active_admin_form_for etc from your partial, since it will be covered by the form do part in the admin/photos.rb, otherwise there will be two nested forms.
Example partial:
# app/views/admin/forms/_photo.html.arb
if events.any?
f.inputs do
f.input :title, label: 'Etc'
f.input :file
end
f.actions
else
f.div 'You cannot add photos until you have added at least one event.',
style: 'font-size: 14px'
end
form do |f|
render partial: 'admin/forms/photo', locals: { value: 'random_data' }
end
You can use f.render or just render.
Note that partial: is required to send locals to the form
Example Partial
#app/views/admin/forms/_photo.html.arb
active_admin_form_for [:admin, resource] do |f|
f.semantic_errors *f.object.errors.keys
f.inputs do
f.input :name
f.input :random if (value == 'random_data')
end
f.actions
end
another thought on this, if you want to check only if there are any Events in db you can make any call directly on Class:
<% if Event.any? %>
do this
<% else %>
do that
<% end %>
without sending variables to partial, the above code result in:
2.0.0p0 :004 > Event.any?
(0.6ms) SELECT COUNT(*) FROM "events"
=> true
and leave the ActiveAdmin partial without locals:
ActiveAdmin.register Photo do
form :partial => 'admin/forms/photo'
end

Does a Rails plugin exist to build a show page (like a formbuilder)

I'm looking for a Rails plugin providing a builder for show.html.erb pages.
For example, with SimpleForm, an new.html.erb page might look like this :
<%= simple_form_for(#user, :url => user_registration_path, :html => ... }) do |f| %>
<%= f.input :email, :required => true %>
<%= f.input :password, :required => true %>
<%= f.input :password_confirmation, :required => true %>
...
<% end %>
But I was not able to find an equivalent for just displaying fields.
A generated show.html.erb page looks like :
<p>
<b>Email:</b>
<%= #user.email %>
</p>
...
But I'd like something like :
<%= simple_display_for(#user, :html => ... }) do |d| %>
<%= d.output :email %>
<%= d.output :name %>
...
<% end %>
Does this kind of builder exist?
Thanks
EDIT : If the builder use Twitter Bootstrap, that's even better :)
I don't know of any gems, but here is a simple example of how to build this feature yourself, which you can expand on:
lib/simple_output.rb
class SimpleOutput
def initialize(resource)
#resource = resource
end
def output(attribute)
#resource.send attribute
end
end
config/initializers/simple_output.rb
require_dependency 'lib/simple_output'
helpers/simple_output_helper.rb
module SimpleOutputHelper
def simple_output_for(resource, options={}, &block)
content_tag :div, yield(SimpleOutput.new(resource)), options[:html] || {}
end
end
users/show.html.erb
<%= simple_output_for(#user, html: { style: "background-color: #dedede" }) do |r| %>
<%= r.output :name %>
<%= r.output :email %>
<% end %>
Now, obviously this is just a very simple example, but hopefully it will get you started on the right track. Look at the simple_form source to see how they organize their code, and how they "typecast" fields. The simple_form codebase is very clean and easy-to-follow Ruby, and is a great example of what a gem should look like.

Rails: Content_for in partial

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 %>

How to access attributes in a partial of a nested rails form?

I want to use the boolean attribute is_white from my inner_object to switch between html code in the the partial _inner_object_form_fields. This is my attempt.
<%= form_for #outer_object do |f| %>
<%= f.fields_for :inner_object do |builder| %>
<%= render :partial => "inner_object_form_fields", :locals => { :f => builder } %>
<% end %>
<% end %>
This is my attempt of the partial _inner_object_form_fields.
<% if f.is_white == true %>
<%= f.label(:name, "White") %>
<% else %>
<%= f.label(:name, "Black") %>
<% end %>
This is the migration file of InnerObjects.
class InnerObjects < ActiveRecord::Migration
def self.up
create_table :inner_objects do |t|
t.string "name"
t.boolean "is_white", :default => true
t.timestamps
end
end
def self.down
drop_table :inner_objects
end
end
I found a similar question but could not retrieve an answer for me.
The question is: How can access the attribut is_white? My example does NOT work.
Try
<% if f.object.is_white == true %>
Seem to remember you could access the object this way (not 100% sure though ;)
Is it because f.is_white is based on a blank object in the partial? Try
<%= form_for #outer_object do |f| %>
<%= f.fields_for f.inner_object do |builder| %>
<%= render :partial => "inner_object_form_fields", :locals => { :f => builder } %>
<% end %>
<% end %>
That way it's referencing the attached object and any state you've created.
Even one step further would be to do something like this:
<%= f.fields_for f.inner_object do |builder| %>
<%= render :partial => "inner_object_form_fields", :locals => { :f => builder, :inner_object => builder.object } %>
<% end %>
Then you can do.
<% if inner_object.is_white == true %>
This way your partials code looks a little cleaner.

How do you pass rails 3 forms params into an array?

I have a nested form (using accepts_nested_attributes_for in respective models):
<%= form_for(:technician, :url => {:controller => 'pos', :action => 'create_ticket'}) do |f| %>
<%= f.fields_for :service do |s| %>
<%= s.text_field :name %>
<%= s.text_field :name %>
<%= s.text_field :name %>
<%= s.text_field :name %>
<% end %>
<% end %>
This works fine if I only have one s.text_field. But once I add additional text_fields, it doesn't run properly. If you look at the source code, the id and name are the same for all six?
How do I put these params into an array? [so that I can isolate them like this:]
service1 = Service.named(params[:technician][:service][1][:name])
(I've tried the method described on railscasts episode 192, but it didn't work either).
After hours of trial and error, I've hacked something that works (but please let me know if you know a better, more eloquent way):
in view:
<%= form_for(:technician, :url => {:controller => 'pos', :action => 'create_ticket'}) do |f| %>
<% for #i in 1..6 do %>
<%= f.fields_for "services[#{#i}]" do |s| %>
<% end %>
<% end %>
<% end %>
in controller:
for i in 1..6 do
#service = Service.named(params[:technician][:services][i.to_s][:name]).first
end
make sure you turn i into string