RoR: Add a blank field to a simple_fields_for loop - ruby-on-rails-3

I am sure this is a silly question, but I have been searching for some time now without finding an answer.
I have a nested form using simple_forms. I get all the child objects successfully with
= f.simple_fields_for :fund_levels do |fl|
= fl.input :title
= fl.input :description
= fl.input :maxnumber
= fl.input :price
This gets all existing fund_levels. However, I also want to add a blank set at the end of the list. So that if there are no existing fund_levels, it simply shows a blank "subform", if there are two existing fund_levels, it will show those two plus a blank "subform".
Is there an easy way of doing this?

Build it in your controller:
#object.fund_levels.build
where #object is the object being passed to form_for.

You can use a simple conditional in the view to check if there are any fund_levels and show a form to add a new one conditionally
- unless #fund_levels.any?
= f.simple_fields_for #fund_levels.build do |f|
= f.input :title
= f.input :description
= f.input :maxnumber
= f.input :price

Related

How to Pass Hash parameter of Boolean attribute from view?

I am using Meta-search Gem to search from table by below controller action. I am Using The Rails version 3.2.9.
class FeedEntriesController < ApplicationController
def index
#search = FeedEntry.search(params[:is_star])
#feed_entries = #search.page(params[:page])
#app_keys = AppKey.all
end
end
feed_entries table contain is_star:boolean attribute. So, I just want to pass the hash parameter is_star == true into the params[:is_star] from view using form_for or link_to . I tried using the below way.
In Views/feed_entries/index.html.erb
<%= link_to "Stared", {:controller => "feed_entries", :action => "index", :is_star => true }%>
but the above way is now worked, So I decided to make use of form_for in the below way,
<%= form_for(#is_star) do |f|%>
<%= f.hidden_field :is_star_is_true %>
<%= f.submit "Search" %>
<% end %>
But, nothing is worked, please someone help me resolve this problem.
true and false when passed as a string is parsed as their truthy value when used in a boolean column. This is also true for 0, 1, '0' and '1'
>> m = Model.new
>> m.active = 'false'
>> m.active? # false
>> m.active = 'true'
>> m.active? # true
Knowing this, you can pass 'true' as the value of the hidden_field
<%= f.hidden_field :is_start, value: 'true' %>
You can pass in the value of the parent in the view where the form is being rendere ultimately with something like <%=params[:is_start] = 1 %> . I am not sure how the layout of the app is setup. Also make sure to attr_accessible :is_start
Update: I may have understood your problem wrong. So try this as well
<%= f.hidden_field :is_star, value: 'true' %>
Or you could have a radio button ?
<%= f.radio_button :is_star, value: 'true' %>

How do I group radio buttons for separate fields?

I have a rails app that gives users assignments and prompts them via email to come back and note that their assignment is completed or take some other action. I have three different actions (remind me later, choose a different assignment, or get help from a coach) which are represented by three radio buttons. How do I group these so that the user can only choose one of the three actions at a time?
<%= form_for(#assignment, :url => user_assignment_path(#user, #assignment)) do |a| %>
<%= a.radio_button :next_reminder_date, value: (Date.today + 2) %> <h3>Remind me again in 2 days.</h3><br>
<%= a.radio_button :coach_requested, true %> <h3>I'm stuck! Have a coach contact me.</h3><br>
<%= a.radio_button :abandoned, true %> <h3>This sucks. Give me another assignment.</h3><br>
<%= a.submit "Update assignment", class: "btn btn-primary btn-large" %>
<% end %>
I think you have two options. One would be to set the values using JavaScript. When any of the values is set, you can reset the other values. This won't work if a user doesn't have JavaScript so I'd recommend option 2.
Use something like this in your View:
radio_button_tag :next_action, :next_reminder_date
radio_button_tag :next_action, :coach_requested
radio_button_tag :next_action, :abandoned
Then in your Controller:
case params[:next_action]
when :next_reminder_date
#assignment.next_reminder_date = Date.today + 2
when :coach_requested
#assignment.coach_requested = true
when :abandoned
#assignment.abondoned = true
end
I hope that helps.

form_for non-AR model - fields_for Array attribute doesn't iterate

I'm having trouble getting fields_for to work on an Array attribute of a non-ActiveRecord model.
Distilled down, I have to following:
models/parent.rb
class Parent
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
extend ActiveModel::Translation
attr_accessor :bars
end
controllers/parent_controller.rb
def new_parent
#parent = Parent.new
#parent.bars = ["hello", "world"]
render 'new_parent'
end
views/new_parent.html.haml
= form_for #parent, :url => new_parent_path do |f|
= f.fields_for :bars, #parent.bars do |r|
= r.object.inspect
With the code as above, my page contains ["hello", "world"] - that is, the result of inspect called on the Array assigned to bars. (With #parent.bars omitted from the fields_for line, I just get nil displayed).
How can I make fields_for behave as for an AR association - that is, perform the code in the block once for each member of my bars array?
I think the correct technique is:
= form_for #parent, :url => new_parent_path do |f|
- #parent.bars.each do |bar|
= f.fields_for "bars[]", bar do |r|
= r.object.inspect
Quite why it can't be made to Just Work I'm not sure, but this seems to do the trick.
I think that it can be done without the need of each:
= form_for #parent, :url => new_parent_path do |f|
= f.fields_for :bars do |r|
= r.object.inspect
You need to set some methods that are expected in the parent class to identify the collection.
class Parent
def bars_attributes= attributes
end
end
And you also will need to make sure that the objects in the array respond to persisted (so you cannot use strings) :(
I ditched the fields_for and added multiple: true
= form_for #parent, :url => new_parent_path do |f|
- #parent.bars.each_with_index do |bar, i|
= f.text_field :bars, value: bar, multiple: true, id: "bar#{i}"

Rails filtering with acts_as_taggable gem

I am working the acts-as-taggable-on gem and have a question about how to filter down search results based on tags users select. Here's an abridged look at my controller:
class PhotosController < ApplicationController
def index
#photos = Photo.where(["created_at > ? AND is_approved = ?", 1.months.ago, true])
#tags = ["Animals", "Architecture", "Cars", "Flowers", "Food/Drink", "General", "Landscape", "Mountains", "Nature"]
end
def search_by_tag(tag)
#photos = Photo.where('tagged_with LIKE ?', tag)
end
end
Photos/index
<% #tags.each do |tag| %>
<%= link_to tag, {:search_by_tag => tag}, :class => "tag" %>
<% end %>
This lists out all of the tags from the hash #tags defined in index, but clicking them doesn't actually filter anything down. Here's a look at what clicking one of those links produces in the log:
Started GET "/photos?search_by_tag=Animals" for 127.0.0.1 at Sun Oct 09 17:11:09 -0400 2011
Processing by PhotosController#index as HTML
Parameters: {"search_by_tag"=>"Animals"}
SQL (0.5ms) SELECT name FROM sqlite_master WHERE type = 'table' AND NOT name = 'sqlite_sequence'
The result I want is for the page to display only Photos that are tagged_with whichever tag was clicked on. I can't quite figure out how to accomplish this.
(Side-question: I can't seem to find a way to list out all of the tags from the tags table that acts-as-taggable-on generated. Doing something like Photo.tagged_with or Photo.tags doesn't work. I am able to see the "tags" table the gem created, and the entries inside of it; I'm just not really clear how to handle that using this gem)
Any thoughts greatly appreciated.
UPDATE
I've updated my code and am a bit closer.
class PhotosController < ApplicationController
def search_by_tag
#photos = Photo.tagged_with(params[:tag_name])
end
photos/index
<% Photo.tag_counts_on(:tags).map(&:name).each do |tag| %>
<%= link_to tag, {:action => 'search_by_tag', :tag_name => tag}, :class => "tag" %>
<% end %>
I believe this is closer, but still working through this...
You have a number of errors in your code:
Your link_to call is actually calling the index action.
Your search_by_tag method is expecting an argument, where it should be using the params hash to access the parameters passed to it in the web request.
tagged_with is a class method added by acts_as_taggable_on, not a field in your table - therefore you can't use it in the where method like you have done.
Finally, to get all the tag names: Photo.tag_counts_on(:tags_or_whatever_you_tagged_on).map(&:name)
Take a look at the acts_as_taggable_on documentation and you'll see examples of how to use tag_counts_on and tagged_with.
As for the Rails things: http://guides.rubyonrails.org/ http://railsforzombies.org/ and/or http://railscasts.com/

Rails HABTM fields_for – check if record with same name already exists

I have a HABTM-relation between the models "Snippets" and "Tags". Currently, when i save a snippet with a few tags, every tag is saved as a new record.
Now i want to check if a tag with the same name already exists and if that´s the case, i don´t want a new record, only an entry in snippets_tags to the existing record.
How can i do this?
snippet.rb:
class Snippet < ActiveRecord::Base
accepts_nested_attributes_for :tags, :allow_destroy => true, :reject_if => lambda { |a| a.values.all?(&:blank?) }
...
end
_snippet.html.erb:
<% f.fields_for :tags do |tag_form| %>
<span class="fields">
<%= tag_form.text_field :name, :class => 'tag' %>
<%= tag_form.hidden_field :_destroy %>
</span>
<% end %>
Ok, i´m impatient… after a while i found a solution that works for me. I don´t know if this is the best way, but i want to show it though.
I had to modify the solution of Ryan Bates Railscast "Auto-Complete Association", which handles a belongs_to-association to get it working with HABTM.
In my snippet-form is a new text field named tag_names, which expects a comma-separated list of tags.
Like Ryan, i use a virtual attribute to get and set the tags. I think the rest is self-explanatory, so here´s the code.
View "_snippet.html.erb"
<div class="float tags">
<%= f.label :tag_names, "Tags" %>
<%= f.text_field :tag_names %>
</div>
Model "snippet.rb":
def tag_names
# Get all related Tags as comma-separated list
tag_list = []
tags.each do |tag|
tag_list << tag.name
end
tag_list.join(', ')
end
def tag_names=(names)
# Delete tag-relations
self.tags.delete_all
# Split comma-separated list
names = names.split(', ')
# Run through each tag
names.each do |name|
tag = Tag.find_by_name(name)
if tag
# If the tag already exists, create only join-model
self.tags << tag
else
# New tag, save it and create join-model
tag = self.tags.new(:name => name)
if tag.save
self.tags << tag
end
end
end
end
This is just the basic code, not very well tested and in need of improvement, but it seemingly works and i´m happy to have a solution!