Ruby on Rails simple_form_for all.each do - ruby-on-rails-3

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!

Related

Forms on partial doesn't render properly

I have a Rails app that is running fine on Rails 3.x and ActiveAdmin 0.6.6. However I want to upgrade it to Rails 5 and ActiveAdmin 1.x. I started the upgrade process first upgrading from 3.x to 4.x and then to 5x, and with ActiveAdmin I tested with 1.0.0 and now I'm using the master from Github.
Everything worked fine with the App in both Rails versions and ActiveAdmin but the ActiveAdmin forms that are in a partial.
The problem is the following:
I have a file app/admin/menu.rb whose has a partial views/admin/menus/_form.html.erb.
The partial contains the form of the Menu.
This is the contents of the partial (views/admin/menus/_form.html.erb):
<%= semantic_form_for [:admin, #menu], builder: ActiveAdmin::FormBuilder do |f| %>
<% f.inputs 'Campos Menu' do %>
<% f.input :project if current_admin_user.admin? %>
<% f.input :title %>
<% f.input :title_en %>
<% f.input :item %>
<% f.input :icon, as: :file %>
<% end %>
<% f.inputs 'Submenus' do %>
<% f.has_many :submenus, heading: '' do |fa| %>
<% fa.input :title, as: :string %>
<% fa.input :title_en, as: :string %>
<% fa.input :kind, as: :select, collection: Submenu.kind_collection %>
<% fa.input :items_as, as: :select, collection: Submenu.items_as_collection %>
<% end %>
<% end %>
<% f.actions do %>
<% f.action :submit %>
<% end %>
<% end %>
The render result of this file is only the 'actions' buttons, in this case the 'submit' button. The interesting thing is that if I remove the <% f.actions do %>... from the partial then the <% f.inputs 'Submenus' do %> gets rendered and the same if I remove the later. In other others is being rendered on the last block that contains an end.
The same behaviour is being observed on Rails 4.x and 5.x (except Rails 5.1.x which I didn't tested).
If I move the form from the partial to the app/admin/menu.rb it gets rendered properly. This could be a solution for me however I have others forms that make use of JQuery for fields manipulation and other stuff on the front end.
As I said before, all these forms partials were working properly on Rails 3.x and ActiveAdmin 0.6.6.
Anyone knows what's the problem?
DISCLAIMER: I'm not a Rails or ActiveAdmin expert, so bear with me if is a silly mistake related to this issue.
Yes, it's activeadmin#3486 I'm glad you figured out the workaround. I'm curious if this Arbre branch fixes it for you. Glad to see people still upgrading, I'll do what I can to help.
The solution that I found was to put a = for the <% f.input(s) %> on the partial. Having something like this <%= f.inputs ... %> instead of this <% f.inputs ... %> solves the problem.

Add message to formtastic semantic error block

If there are semantic errors in the form (mostly from external API), I'd like to add an explanatory message, like so:
<%= semantic_form_for #order, :url => checkout_purchase_url, :html => {:class => 'payment'}, :wrapper_html => { :class => "field" } do |f| %>
<% if f.has_errors? %>
<p>There were errors that prevented your order from being submitted. If you need assistance, please contact us toll-free at <strong>1-800-555-5555</strong>.</p>
<%= f.semantic_errors %>
<% end %>
<% end %>
However, has_errors? is a protected method. Is there a way that I can do this? Thanks.
If you have nested attributes you won't see any errors associated with them. To ensure you get all base errors and any nested attributes errors. Make sure your model contains:
validates_presence_of :nested_object
validates_associated :nested_object
and in your form:
f.semantic_errors *f.object.errors.keys
Not as hard as I thought. I fixed it by checking for errors on the object instead of the form:
<% if #object.errors.any? %>
<p>There were errors that prevented your order from being submitted. If you need assistance, please contact us toll-free at <strong>1-800-555-5555</strong>.</p>
<%= f.semantic_errors %>
<% end %>
Thanks for those who viewed.
For completeness, here's an alternative approach if you want to show similarly helpful messages on each field:
= f.label :title
- if f.object.errors.any?
.error = f.object.errors[:title].flatten.join(' and ')
= f.text_field :title
This gives a nicely formatted and easily-styled list of errors for each field. (You can use semantic_errors instead of object.errors if you prefer, same result.)

Rails search functionality

I am taking a rails class at my University and I am trying to create a search form which will show the results on the same page rather than show a different page of results. Is this something simple to do? I am creating a museum app with artifacts for each museum but I want the user to search artifacts from either page.
On my routes.rb I have
resources :artifacts do
collection do
get 'search'
end
end
On my museum index I have the code below that he gave us but not sure how to tweak the get routes for the same page.
<%= form_tag search_artifacts_path, :method => 'get' do %>
<p>
<%= text_field_tag :search_text, params[:search_text] %>
<%= submit_tag 'Search' %>
</p>
<% end %>
<% if #artifacts %>
<p> <%= #artifacts.length %> matching artifacts. </p>
<h2> Matching Artifacts </h2>
<% #artifacts.each do |a| %>
<%= link_to "#{a.name} (#{a.year})", a %><br />
<% end %>
<% end %>
Yes, this is easy. Just have the index page return the search results if params[:search_text] is present - this way you don't need a new route or a different page.
class ArtifactsController < ApplicationController
def index
#artifacts = Artifact.search(params[:search_text])
end
end
class Artifact < ActiveRecord::Base
def self.search(query)
if query
where('name ILIKE ?', "%#{query}%")
else
all
end
end
end
So then your form looks like:
<%= form_tag artifacts_path, :method => 'get' do %>
<p>
<%= text_field_tag :search_text, params[:search_text] %>
<%= submit_tag 'Search' %>
</p>
<% end %>
Edit:
So what you really want to do is any page you want to search, include a form which makes a request to that same page.
Then in each of those controller methods just put this line of code:
#artifacts = Artifact.search(params[:search_text])
and that will populate the #artifcats array with only artifacts that match the search query.
Try using "Ransack" gem. It can also perform some more powerful searches.

Rails 3 ActiveRecord::UnknownAttributeError "unknown attribute: _destroy" for nested records

Let's say I have a schema in which an apple crate contains zero or more apples. While editing the apple crate in a form, I want to list the apples and provide a checkbox next to each apple, for deleting it when the form is submitted.
There is nothing going wrong that I can see. In my model I say
class AppleCrate < ActiveRecord::Base
has_many :apples
accepts_nested_attributes_for :apples, :allow_destroy => true
...
end
I have the form working, so far as I can tell. The checkboxes appear in the form html and when the form is processed by the controller each apple in the list has an attribute called "_destroy" which is set to either "1" or "0" depending on whether or not I checked the box before submitting.
According to the Rails API, when I set _destroy to 1 and save, the apple should be deleted. But when I submit the form I get
ActiveRecord::UnknownAttributeError in AppleCrateController#update
unknown attribute: _destroy
...
"apple_crate"=>{"id"=>"10101", "apples"=>{"1"=>{"id"=>"1",
"variety"=>"granny smith",
"apple_crate_id"=>"10101",
"_destroy"=>"1"},
"2"=>{"id"=>"2",
"variety"=>"fuji",
"apple_crate_id"=>"10101",
"_destroy"=>"1"},
"3"=>{"id"=>"3",
"variety"=>"macintosh",
"apple_crate_id"=>"10101",
"_destroy"=>"0"},
...
and so on.
I must be missing something obvious but after several days of futzing around I can't figure it out. I can successfully do everything else -- update, edit, index, etc -- so long as I leave out the :_destroy attribute. Any ideas?
(For what it's worth, I'm running rails 3.2.2 on Windows.)
Updated:
This is what I'm looking at in the documentation. (See the subsection "One-to-many".)
Updated:
As requested in comments, here is the view:
<%= form_for #apple_crate do |f| %>
<% #apples = #apple_crate.apples %>
<% #apples.each do |apple| %>
<%= fields_for "apples[]", apple do |apple_fields| %>
<%= apple_fields.text_field :variety %>
<%= apple_fields.hidden_field :apple_crate_id %>
<%= apple_fields.hidden_field :id %>
<%= apple_fields.check_box :_destroy %>
<% end %>
<% end %>
<%= f.submit "Save" %>
<% end %>
You should generate nested forms and forms with rails helpers, don't do it by your hands. So I think that's where your error at.
Try:
<%= form_for #apple_crate do |f| %>
<%= f.fields_for :apples do |apple_fields| %>
<%= apple_fields.text_field :variety %>
<%= apple_fields.hidden_field :apple_crate_id %>
<%= apple_fields.hidden_field :id %>
<%= apple_fields.check_box :_destroy %>
<% end %>
<% end %>
something like this, did not check if it's correct, but idea should be clear enough

Voting app in rails 3: how do I link to vote method?

To teach myself Rails, im building an extremely simple Voting app.
There are 2 models, Question and Option. Question has_many Options and Option belongs_to Question.
Using the standard scaffolding, I have reached a stage where you can add a question, view it, and add options to it and see these options.
What I would like to do now is add the code that increases an option.count value by one when clicking on a link. I have a vote_up method in the Option model:
class Option < ActiveRecord::Base
validates :text, :presence => :true
belongs_to :question
def vote_up
self.count += 1
end
end
My Options controller looks like:
class OptionsController < ApplicationController
def create
#question = Question.find(params[:question_id])
#option = #question.options.create(params[:option])
redirect_to question_path(#question)
end
end
My Question model looks like:
class Question < ActiveRecord::Base
validates :text, :presence => {:message => 'A question normally has text...'}
has_many :options, :dependent => :destroy
def vote
# Maybe the vote code will go here???
end
end
And my Question controller has the usual new, create, edit, destroy methods that the scaffold creates. V little customisation here.
My show.html.erb view where I would like to put the link to the vote method looks like:
<p id="notice"><%= notice %></p>
<p>
<b>Question <%= #question.guid %></b>:
<%= #question.text %>
</p>
<% if #question.options.count == 0 %>
<p>Shame! there are currently no options to vote on. Add some! </p>
<% elsif #question.options.count == 1 %>
<p>One option in a vote is a dictatorship... Maybe add some more?</p>
<% end %>
<h2>Options:</h2>
<% #question.options.each do |option| %>
<p>
<%= option.text %>: ** Link to vote here!
</p>
<% end %>
<h2>Add an option to vote on</h2>
<%= form_for([#question, #question.options.build]) do |f| %>
<div class="field">
<%= f.label :text %><br />
<%= f.text_field :text %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% if #question.options.count == 0 # Only show edit if no options saved. %>
<%= link_to 'Edit', edit_question_path(#question) %> |
<% end %>
<%= link_to 'Back', questions_path %>
So what I am trying to do is add a "vote" link next to each option that calls the vote_up method in the options model. This is probably laughably easy, but i've hit a wall and would really appreciate any help.
Also, any suggestions on how to do this better would be welcome!
Thanks
Simon
I think #oded-harth has showed a right way, but I have two remarks:
First of all, Rails is a beautiful language and is written to simplify our developer lives ;) When programming in Rails you must never forget that. With this in mind, I want to point you to "increment()" method. So you can simply up-vote without unnecessary += 1. To down-vote use decrement(). I believe you can use it like this: option.increment(:count)
Second, I think it's a little dirty to have a whole form for a simple vote action. You can use something like this
<%= link_to "Vote Up", :url => { :action => :vote_up, :option_id => option.id }, :method => :put %>
To make it work you'll have to set your route something like this:
resources :votes
put :vote_up
end
What I would do is make the vote_up method in the controller:
def vote_up
option = Option.find(params[:option_id])
option.count += 1
redirect (to where do you want...)
end
And in the view I would call that method this way:
<%= form_for( option, :url => { :action => "vote_up", :option_id => option.id} ) do |f| %>
<%= f.submit("vote up") %>
<% end %>