Rails 3 - Delete Multiple Records Using Checkboxes - ruby-on-rails-3

How do you delete multiple records using checkboxes in Rails 3?

routes.rb:
resources :blog_posts do
collection do
delete 'destroy_multiple'
end
end
index.html.erb:
<%= form_tag destroy_multiple_blog_posts_path, method: :delete do %>
<table>
...
<td><%= check_box_tag "blog_posts[]", blog_post.id %></td>
...
</table>
<%= submit_tag "Delete selected" %>
<% end %>
blog_posts_controller.rb:
def destroy_multiple
BlogPost.destroy(params[:blog_posts])
respond_to do |format|
format.html { redirect_to blog_posts_path }
format.json { head :no_content }
end
end

Assuming you want to display a list of records in a table, each with a check box, and have a delete button that will cause all checked records to be deleted.
First, you have to create names for the checkboxes that contain the record id, you could do this:
<%= check_box_tag("delete[#{#thing.id}]",1) %>
That will create HTML that will include the following
<input id='delete[1000]' type='checkbox' value='1' name='delete[1000]'>
So when you post a form, if you've checked the box for the records with id's 1001 and 1002, your post will contain:
"delete[1001]"=>"1"
"delete[1002]"=>"1"
So inside your controller, you could do this
params[:delete].each do |id|
Thing.find(id.to_i).destroy
end

Send the ids of all checked elements on controller. I am assuming u have send ids to be deleted for Foo class to be deleted
ids = params[:ids]
Foo.where("id in (#{ids}")).destroy
or
ids = params[:ids].split(",")
Foo.where(id => ids).destroy
Use destroy, don't use delete if you have any dependencies.

Related

render partial view recursively in rails 5

I'm new to ruby on rails and I'm facing a problem rendering nested questions.
What I want to achieve is rendering the question and check if it have children question then render the children questions as well.
there is no limit on the nesting levels, so I have to use recursion method to achieve this and this is what I came up with.
# view file code
<% #questions.each do |q| %>
<%= render partial: "shared/question_block", locals: {q: q} %>
<% if have_children_questions?(q.id) == 'true' %>
<%= print_children_questions( get_children_ids(q.id) ) %>
<% end %>
<% end %>
and here is the helper functions I created
def have_children_questions?(id)
children = Question.get_children(id)
if !children.empty?
'true'
else
'false'
end
end
def get_children_ids(id)
ids = Question.where(parent: id).pluck(:id)
end
def print_children_questions(ids)
ids.each do |id|
q = Question.find(id)
render partial: "shared/question_block", locals: {q: q}
if have_children_questions?(id)
print_children_questions( get_children_ids(id) )
end
end
end
print_children_questions method returning the ids instead of the partial view, what I'm doing wrong?
is there is a better solution
Thanks in advance

"Undefined method `each' for '2,1':String" when using #partner.products association?

I have a part file where I want to show all my products for a specific partner.
Here's the html.erb:
<% unless #products.nil? %>
<% #products.each do |prod|%>
<tr id="p_<%= prod.id%>">
<td><%= prod.name %></td>
<td><%= prod.price %></td>
<td><%= number_field_tag "product_qty_input[#{prod.id}]", get_offer_product_qty(#offer.id, prod.id),:min => 0, :max => 99 %></td>
<td>X</td>
</tr>
<% end %>
<% end %>
But I keep getting the error: undefined method `each' for "2,1":String
it says it's on this line: <% #products.each do |prod|%>
But I don't see the problem..
Here's my controller:
def select_products
#partner = Partner.find(params[:partner_id])
if params[:id] == "-1"
#offer = nil
else
#offer = Offer.find(params[:id])
end
#select_callback = url_for( #offer.nil? ? new_partner_offer_path(#partner) : [:edit, #partner, #offer] )
#products = #partner.active_products
#num_select = PRODS_PER_OFFER
respond_to do |format|
format.html { render :template => "products/select"}
end
end
You see I have #products = #partner.active_products method, but i changed that to see if it got there, and it's not, must be something before...
I would apreciate any help.
Thanks in advance
UPDATE
Here is the method active_products :
def active_products
self.products.where("active IS NOT NULL AND active = true")
end
It should be returning the object not string
What am I doing wrong?
Thanks #thesis
UPDATE 2
Guys, Thanks a lot for the help, and with the assistence of #thesis I figured it out.
It was actualy something that I haven't thought about before, and it wasn't describe here in the question.
My sessionkeeper helped me keep my form as I selected products in another page!
That was meesing it up!
Your problem is very simple. You have to fix your active_products method, as it returns String. In your case, string is "2,1" but you have to return collection of products, to iterate it with each method.
For additional help, please update your question and add active_products instance method from Partner model.
Do you really have products as numbers "2,1".
#partner.active_products should ideally return ActiveRecord::Relation, hence it should iterate objects of Product class.
Please go through http://guides.rubyonrails.org/
And before that, you may like to search for 'ruby philosophy' and 'rails philosophy'

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/

Any possible way to set radio_button_tag values by a database set value

I have a radio_button_tag in a form, which holds various values for a persons current availability:
Mike Donnall o Available o Out of office o Vacation
So originally you open the form, and select a value, this then sets the value in the Status table for that Person.
However, there's also functionality to re-open the form and update his present status, perhaps from Vacation to Available.
My question is, is there anyway at all that radio button :checked can be modified to accept a custom method, I have found something in a similar posting, but I want the value foe that radio button to be set to the value in the DB.
My code so far, a stab in the dark perhaps:
View:
<% #people.each do |p| %>
<% #statuses.each do |s| %>
<%= "#{p.name}" %>
<%= "#{s.status_name}" -%><%= radio_button_tag ['person', p.id], ['status',
s.id], checked?(p.id) %>
<% end %>
<% end %>
Helper:
def checked?(person)
#person = person
#status = Status.find_by_sql(['select status_id from statuses where person_id = ?, #person])
if #result
return true
end
As you can see Im a bit lost here, but I understand that the method should return the value of the checkbox that needs to be checked, but Im wondering because its a checked functionality, would it only be limited to being a true or false?
So for a persons.status.id check if its true or false.
It seems from your helper's SQL that you the following relationship setup between People and Statuses:
class Person < ActiveRecord::Base
has_one :status
end
class Status < ActiveRecord::Base
belongs_to :person
end
You can access one given person status like this:
person = Person.first
person_status = person.status
Using that knowledge, your desired view outcome becomes quite simple:
<% #people.each do |p| %>
<p><%= "#{p.name}" -%>
<% #statuses.each do |s| %>
<%= "#{s.status_name}" -%>
<%= radio_button_tag ['person', p.id],
['status', s.id],
(p.status == s) ? true : false %>
<% end %>
<% end %>
You can of course extract the logic to a helper, but that doesn't seem necessary.
On a personal note, this isn't the way I'd present the information to user, it' too heavy on information in one line. I suggest you put the person's name in a p tag, and use a ul tag for the statuses.

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!