Rails SQL query in controller method - sql

I want to retrieve brand name depending on brand_id which is mentioned in the another table products. My brand ids are stored as an array in 'brandids'. Here is my controller code.
def index
catids = Array.new
brandids = Array.new
#products = nil
if(!(params[:catid].nil?) && params[:catid].to_s.downcase != "all")
catids = arrayConvertion(params[:catid])
end
if(!(params[:brandid].nil?) && params[:brandid].to_s.downcase != "all")
brandids = arrayConvertion(params[:brandid])
end
if(catids.length == 0 && brandids.length == 0)
#products = Product.solr_search do
paginate :page => params[:page], :per_page => 3
end
#brands={}
#products.each do |p|
brand = p.BrandsTest.first(p.brands_test_id)
#brands[p.id] = BrandsTest.name
end
end
and the view for this controller is:
<% #products.results.each do |p| %>
<%= image_tag("Images/#{p.id}.jpeg",:alt => p.name) %>
<p> Name: </p>
<%= p.name %>
<p> Price: </p>
<%= p.price %>
<p> Discount: </p>
<%= p.discount %>
<p> Brand Name: </p>
<%= #brands[p.id] %>
<% end %>
Product Model code is:
class Product < ActiveRecord::Base
belongs_to :brands_test
belongs_to :categories_test
attr_accessible :id, :name
searchable do
integer :id
text :name
integer :brands_test_id
integer :categories_test_id
end
end
What query should I need to add and where I have to add?
Please help me with this.

#products = Product.solr_search do
with :brands_test_id, brandids[0..brandids.length]
paginate :page=>params[:page], :per_page=>3
end
#brands={}
#products.each do |p|
brand=Brand.find_by_id(p.brand_id)
#brands[p.id]=brand.name
end
views:
<% #products.results.each do |p| %>
#other code
<p> Brand: </p>
<%= #brands[p.id]
<% end %>
I don't sure if I understood what are you trying to do.

I did some modification according my app with the answer that you gave.Here is the controller part.
if(catids.length == 0 && brandids.length == 0)
#products = Product.solr_search do
paginate :page=>params[:page], :per_page=>3
end
#brands={}
#products.results.each do |p|
brand=BrandsTest.find_by_id(p.brands_test_id)
#brands[p.id]=brand.name
end
end
Here is view part:
<% #products.results.each do |p| %>
<%= image_tag("Images/#{p.id}.jpeg",:alt => p.name) %>
<p> Name: </p>
<%= p.name %>
<p> Price: </p>
<%= p.price %>
<p> Discount: </p>
<%= p.discount %>
<p> Brand Name: </p>
<%= #brands[p.id]%>
<% 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

Create a select from existing or create new in a form Rails 3

So I'm trying to set a name attribute of organizations and create a new organization or choose from a previously existing organization from the same form.
I've tried to follow Ryan Bates' railscast on the topic here: http://railscasts.com/episodes/57-create-model-through-text-field
I have also tried numerous solutions from stack. However, I can't quite seem to get it to run (that and I have a validation that does not recognize the virtual attribute I'm using)
so my organizations model:
class Organization < ActiveRecord::Base
has_many :materials
has_many :users
has_and_belongs_to_many :causes
has_and_belongs_to_many :schools, :join_table => 'organizations_schools'
####The following line has been edited ####
attr_accessible :name, :unlogged_books_num, :id, :new_organization_name
attr_accessor :new_organization_name
before_validation :create_org_from_name
validates_presence_of :name
def self.assign_school_to_organization(org, school)
orgschool = OrganizationsSchool.create(:organization_id=> org.id, :school_id=> school[0])
end
def create_org_from_name
create_organization(:name=>new_organization_name) unless new_organization_name.blank?
end
end
I have also tried the create_org_from_name as the following:
def create_org_from_name
self.name = new_organization_name
end
And this does not change the name to the organization name before validating or saving the instance.
I have also tried to change the before_save to before_validation, and that has not worked
My controller for organization (I also tried to change this in create)
def create
respond_to do |format|
#organization = Organization.new(params[:organization])
#organization.name = #organization.new_organization_name unless #organization.new_organization_name.blank?
if #organization.save
#school = params[:school]
Organization.assign_school_to_organization(#organization, #school)
format.html { redirect_to #organization, notice: 'Organization was successfully created.' }
format.json { render json: #organization, status: :created, location: #organization }
else
format.html { render action: "new" }
format.json { render json: #organization.errors, status: :unprocessable_entity }
end
end
end
And finally, I have what my form is doing currently:
<%= form_for(#organization) do |f| %>
<% if #organization.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#organization.errors.count, "error") %> prohibited this organization from being saved:</h2>
<ul>
<% #organization.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% #schools = School.all %>
<% #organizations = Organization.all %>
<div class="field">
<%= f.label 'Organization Name' %><br />
<%= f.collection_select(:name, #organizations, :name, :name, :prompt=>"Existing Organization") %>
Or Create New
<%= f.text_field :new_organization_name %>
</div>
<div class="field">
<%= f.label :unlogged_books_num %><br />
<%= f.number_field :unlogged_books_num %>
</div>
<div class="field">
<%= f.label 'School' %><br />
<% school_id = nil %>
<%= collection_select(:school, school_id, #schools, :id, :name) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
==================================EDIT============================================
So currently, when I try to make an organization with something only written in the virtual text field, My log tells me the following:
Processing by OrganizationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"igoefz8Rwm/RHrHLTXQnG48ygTGLydZrzP4gEJOPbF0=", "organization"=> {"name"=>"", "new_organization_name"=>"Virtual Organization", "unlogged_books_num"=>""}, "school"=>["1"], "commit"=>"Create Organization"}
Rendered organizations/_form.html.erb (7.1ms)
Rendered organizations/new.html.erb within layouts/application (8.0ms)
Completed 200 OK in 17ms (Views: 12.2ms | ActiveRecord: 1.0ms)
================================EDIT 2============================================
So this is what I get from the rails console if I try to create a new organization running this command: Organization.create(:new_organization_name=>"Virtual Organization", :unlogged_books_num=>"3")
irb(main):001:0> Organization.create(:new_organization_name=>"Virtual Organization", :unlogged_books_num=>"3")
(0.1ms) BEGIN
(0.1ms) ROLLBACK
=> #<Organization id: nil, name: nil, unlogged_books_num: 3, created_at: nil, updated_at: nil>
If the function of create_org_from_name is self.name = new_organization_name, then the result of the same command from the console is blank:
irb(main):002:1> Organization.create(:new_organization_name=>"Virtual Organization", :unlogged_books_num=>"3")
irb(main):003:1>
You need:
before_validation :create_org_from_name
and
def create_org_from_name
self.name = new_organization_name if not new_organization_name.blank?
end
You don't want to do a create in your before_validation method.

Updating quantity in Rails Form

I'm building a simple inventory app that keeps track of the quantity of an item.
In a basic form I would be updating item_quantity with whatever arbitrary number I type in.
But how would I create a form/code that would allow me to tag on +20 on top of the already existing item quantity?
You could do it with jquery/javascript
Something like:
In your view:
<%= f.text_field :item_quantity, :id => 'item_quanity' %>
+20
In javascript:
$(function() {
$('#increment_item_quantity').on('click', function(e) {
e.preventDefault();
var currentVal = parseInt($('#item_quantity').val());
$('#item_quantity').val(currentVal + 20);
});
});
You'd probably want to make sure the currentVal is a number (since parseInt('') => NaN)
And then submit as usual
Or
If you wanted to do this via a form:
In your view:
<%= form_for #item, incr_quantity_path(#item) do |f| %>
<%= f.submit %>
<% end %>
Then in your controller:
def incr_quantity
#item = Item.find(params[:id])
# I'd probably move the increment logic into the model
#item.quantity += 20
#item.save
# respond to it however you want
end
Or if you want to increment the value by what's entered:
Model:
class Item < AR::Base
...
attr_accessible :incr_quantity_by
def increment_quantity_by
quantity += incr_quantity_by
end
...
end
View:
<%= form_for #item, incr_quantity_path(#item) do |f| %>
<%= f.text_field :incr_quantity_by
<%= f.submit %>
<% end %>
Controller:
def incr_quantity
#item = Item.find(params[:id])
#item.increment_quantity_by
#item.save
# respond to how you want
end

No Method Error for "comments", can't find and correct the nil value to make the comment post

I'm relatively new to rails and am trying to pull off my first polymorphic association with comments.
I am running rails 3.2.3
Edit - When I try to post a comment, my log is returning this error:
Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 101 LIMIT 1
Completed 500 Internal Server Error in 126ms
NoMethodError (undefined method `Comment' for nil:NilClass):
app/controllers/comments_controller.rb:13:in `create'
I have tried out many different solutions offered on SO and elsewhere, including the answer from Jordan below, due, I'm sure, to my own inexperience, but have been unable to resolve the error.
The trace calls out line 13 in the Comments Controller and I commented after that line below to mark the error:
class CommentsController < ApplicationController
def index
#commentable = find_commentable
#comments = #commentable.comments
end
def new
#post = Post.find(params[:post_id])
end
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment]) #<<<<LINE 13
if #comment.save
flash[:notice] = "Successfully created comment."
redirect_to :id => nil
else
render :action => 'new'
end
end
private
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
end
Posts Controller:
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #post }
end
end
Comment template (in post show)
<ul id="comments">
<% if #comments %>
<h2>Comments</h2>
<% #comments.each do |comment| %>
<li><%= comment.text %></li>
<% end %>
<% else %>
<h2>Comment:</h2>
<% end %>
</ul>
<%= simple_form_for [#commentable,Comment.new], :html => { :class => 'form-horizontal', :multipart => true } do |f| %>
<fieldset>
<%= f.input :text %>
Upload Photo <%= f.file_field :photo %>
</fieldset>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
</div>
<% end %>
Post show:
<p id="notice"><%= notice %></p>
<div class="row">
<div class="span2 offset1">
<%= image_tag #post.photo.url(:show) %>
</div>
<div class="span5">
<h1><%= #post.title %></h1>
<p><%= #post.index_text.html_safe %></p>
<p><%= #post.show_text.html_safe %></p>
<%= render "comments/comment" %>
<%= render "comments/form" %>
<% if can? :update, #course %>
<%= link_to 'Edit Post', edit_post_path(#post), :class => 'btn btn-mini' %>
<%= link_to 'Delete Post', #post,
confirm: 'Are you sure?',
method: :delete,
:class => 'btn btn-mini' %>
<%= link_to 'New Post', new_post_path, :class => 'btn btn-mini' %>
<% end %>
</div>
<nav class="span2 offset1">
<ul class="well">
<li>Category 1</li>
<li>Category 2</li>
</ul>
</nav>
</div>
<div class="row offset2">
<%= link_to 'Back to Posts', posts_path, :class => 'btn btn-mini' %>
</div>
Routes:
resources :posts, :has_many => :comments
resources :comments
It is probably something obvious that someone with more experience can resolve. Let me know if anything comes to mind. Brian
The problem is that #commentable is nil, which means that CommentsController#find_commentable is returning nil. I think your regular expression is sound, so that means one of two things is happening in find_commentable:
There aren't any keys in params that match your regex.
Your regex is matching but there aren't any records in the resulting table with the id in value.
Debug this as usual by inspecting params and the records in your database to make sure they look like you expect them to look.
The problem is your find_commentable method.
Here are the params passed to your CommentsController#create:
Started POST "/comments" for 127.0.0.1 at 2012-05-20 13:17:38 -0700
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SOLcF71+WpfNLtpBFpz2qOZVaqcVCHL2AVZWwM2w0C4=", "comment"=>{"text"=>"Test this comment"}, "commit"=>"Create Comment"}
Here is your CommentsController#create:
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment]) #<<<<LINE 13
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
As you can see, find_commentable expects a param like xx_id (for example, comments_id) which it uses to search for an appropriate class (in case of comments_id, it will be Comment), otherwise it returns nil. Refer classify and constantize here.
Your params do not contain any such param. So, you always get a nil object.
Your find_commentable needs some rework. I think in case of nested_fields, it should be an expression like
/(.+)_attributes$/
instead of
/(.+)_id$/.
And you need to have
:accepts_nested_attributes_for :commentable
in your Comment model class.
I tried both of the above answers, but the problem continued.
I ended up consulting with a friend who suggested the following solution, which I like because it's more elegant than my original attempt and easier to read (for later, when I or someone else need to return to the code):
def find_commentable
if params[:post_id]
Post.find(params[:post_id])
#elsif params[:other_id]
# Other.find(params[:other_id])
else
# error out?
end
end
The commented out section will refer to other associations once I get them up and running.

How to select only checked records using check_box_tag?

Guys my check_box_tag looks like as follows
<%= form_tag({:action => 'update_survey_list_status',:projectid=>params[:id], :status=>4}, :id => 'to_be_approved_frm') do %>
<% #publishedlist.each do |b| %>
<%= fields_for "beneficiaryloan[#{b.id}]" do |bloan| %>
<%= bloan.text_field :amount, :class=>'forms_txtbx'%>
<%= bloan.text_field :rate, :class=>'forms_txtbx'%>
<%= bloan.text_field :period, :class=>'forms_txtbx'%>
<% end %>
<%= check_box_tag "benificiary_id[#{b.id}]",b.id,:name => "benificiary_id[]"%>
<% end %>
<%= submit_tag "Approve", :class=>'form_buttons' %>
<% end %>
And in controller, I'm reading all the beneficiary ids like this
params[:beneficiaryloan].each do |key, value|
beneficiary = Beneficiary.find(key) rescue nil
#benefciary_loan=beneficiary.beneficiaryloans.build(value)
#benefciary_loan.beneficiary_id=beneficiary.id
#benefciary_loan.hfi_id=session[:id].to_s
#benefciary_loan.status_id=params[:status]
#benefciary_loan.save if beneficiary
end
What I need is, Inserting all the beneficiary ids to [beneficiaryloans] table which are checked, but in my case it inserting all records even some of them are unchecked.
How to do I select only checked ids?
Try changing your check_box_tag to
<%= check_box_tag "beneficiaryloan[#{b.id}][enabled]", 1, true %>
Then in your controller do the following:
params[:beneficiaryloan].select{|k,v| v.delete(:enabled).to_i > 0 }.each do |k,v|
..
end
Since the enabled attribute has no influence in the model you can just delete it out of the resulting beneficiary_load hashes.