Rails not passing the DB Query on search form - mysql

Here what looks better, this is the log, its passing the param, but its not passing a query with that param
Started GET "/items?utf8=%E2%9C%93&search=blanca" for 65.34.251.106 at 2016-08-30 03:55:51 +0000
Processing by ItemsController#index as HTML
Parameters: {"utf8"=>"✓", "search"=>"blanca"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 3]]
Item Load (0.3ms) SELECT "items".* FROM "items" LIMIT 50 OFFSET 0
Item Load (0.2ms) SELECT "items".* FROM "items" ORDER BY "items"."id" ASC LIMIT 1 OFFSET 0
Rendered items/_items.html.erb (3.2ms)
Rendered items/index.html.erb within layouts/application (4.9ms)
This is the controller:
def index
#items = Item.search(params[:search])
end
and this is the model:
class Item < ActiveRecord::Base
has_many :stocks
attr_accessible :nombre, :espesor, :material, :quantity
accepts_nested_attributes_for :stocks
attr_accessible :stocks_attributes
self.per_page = 50
# def self.search(search)
# Item.where("nombre LIKE ?", "%#{search}%")
# end
def self.search(search_term)
where("nombre LIKE ?", "%#{search_term}%")
end
protected
end
and the search form in the view:
<%= form_tag items_path, :method => 'get', :id => "items_search" do %>
<p>
<%= text_field_tag :search, params[:search], class: "form-control" %>
<%= submit_tag "Search", :name => nil, class: "btn btn-danger" %>
</p>
<div id="items"><%= render 'items' %>
</div>
<% end %>
I have a _items.html.erb file which has the items to render, that part works because no matter my input on the search bar, it always shows all the items
This is the ouput when i try to use .search method in the console
2.3.0 :041 > Item.search("blanca")
NoMethodError: undefined method `search' for #<Class:0x0000000203fc58>
from /usr/local/rvm/gems/ruby-2.3.0/gems/activerecord- 4.2.6/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
from (irb):41
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/commands/console.rb:110:in `start'
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/commands/console.rb:9:in `start'
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/commands/commands_tasks.rb:68:in `console'
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /usr/local/rvm/gems/ruby-2.3.0/gems/railties-4.2.6/lib/rails/commands.rb:17:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'

Are you sure you defined the class method search in item.rb? Cause the error says that there's no search method defined on the Item class. However, try if the following works for you.
You only want to search if the form is being submitted. You can use the present? method to know if the search term was actually passed.
Modify your controller to
def index
#items = params[:search].present? ? Item.search(params[:search]) : Item.all
end
Note that an object is present only if its not blank. This is handy because if someone enters " " in the form, you shouldn't search for an empty space in the nombre field but display all the records in the items table.
If the form was not submitted, Item.all will be executed.
Modify your class method to
def self.search(search_term)
where("nombre LIKE ?", "%#{search_term}%")
end
You don't need a Item.where because the class Item is the current context on which the where method is called. Note that I have changed the pattern to %#{search_term}% cause you don't always want to match strings ending with some pattern.
Hope this helps!

Related

undefined method `user_revisers_path' "NoMethodError in Revisers#new "

I got this weird error I'm assuming this comes from the routes.rb part of my app. Im trying to give the chance for a user to become a reviser when they enter a form. a user can only become a reviser once so its a has_one reviser on user.rb model Thanks!
routes.rb:
Rails.application.routes.draw do
root 'pages#home'
devise_for :users ,
:path => '' ,
:path_names => { :sign_in => 'login', :sign_out => 'logout', :edit => 'profile' },
:controllers => { :omniauth_callbacks => 'omniauth_callbacks',
:registrations => 'registrations'
}
resources :users, only: [:index, :show] do
resource :reviser
end
revisers_controller:
class RevisersController < ApplicationController
before_action :set_reviser, only: [:show, :edit, :update]
before_action :authenticate_user!, except: [:show]
def index
#reviser = current_user.reviser
end
def show
end
def new
#reviser = current_user.build_reviser(params[:reviser])
#user = User.find(params[:user_id])
end
def create
#reviser = current_user.reviser.build(reviser_params)
if #reviser.save
redirect_to #reviser,notice: "saved...."
else
render :new
end
end
def edit
set_reviser
end
def update
set_reviser
if #reviser.update(reviser_params)
redirect_to #reviser, notice: "updated.."
else
render :edit
end
end
private
def set_reviser
#reviser = Reviser.find(params[:id])
end
def reviser_params
params.require(:reviser).permit(:description, :average_start, :average_end, :max_pages, :price_per, :active)
end
end
new.html
<%= form_for [current_user, #reviser] do |f| %>
<div class="row">
<div class="div.col-md-4 select">
<div class="form-group">
<label>dsd</label>
<%= f.input :description, label: false, class: 'controls',:input_html => { :id => 'description' } %>
</div>
</div>
</div>
<%= f.submit "Become Adviser", class: "btn btn-large btn-primary" %>
<% end %>
Error log:
Rendered revisers/_form.html.erb (14.7ms)
Rendered revisers/new.html.erb within layouts/application (15.9ms)
Completed 500 Internal Server Error in 48ms (ActiveRecord: 1.1ms)
ActionView::Template::Error (undefined method `user_revisers_path' for #<#<Class:0x007faf35f0cc60>:0x007faf35ee7e60>):
5: <div class="panel-body">
6: <div class="container">
7:
8: <%= form_for [current_user, #reviser] do |f| %>
9:
10: <div class="row">
11: <div class="div.col-md-4 select">
app/views/revisers/_form.html.erb:8:in `_app_views_revisers__form_html_erb___2471522092853631188_70195335070980'
app/views/revisers/new.html.erb:1:in `_app_views_revisers_new_html_erb___1451348464463745171_70195280947160'
Rake routes:
Prefix Verb URI Pattern Controller#Action
root GET / pages#home
new_user_session GET /login(.:format) devise/sessions#new
user_session POST /login(.:format) devise/sessions#create
destroy_user_session DELETE /logout(.:format) devise/sessions#destroy
user_omniauth_authorize GET|POST /auth/:provider(.:format) omniauth_callbacks#passthru {:provider=>/facebook/}
user_omniauth_callback GET|POST /auth/:action/callback(.:format) omniauth_callbacks#(?-mix:facebook)
user_password POST /password(.:format) devise/passwords#create
new_user_password GET /password/new(.:format) devise/passwords#new
edit_user_password GET /password/edit(.:format) devise/passwords#edit
PATCH /password(.:format) devise/passwords#update
PUT /password(.:format) devise/passwords#update
cancel_user_registration GET /cancel(.:format) registrations#cancel
user_registration POST / registrations#create
new_user_registration GET /sign_up(.:format) registrations#new
edit_user_registration GET /profile(.:format) registrations#edit
PATCH / registrations#update
PUT / registrations#update
DELETE / registrations#destroy
user_confirmation POST /confirmation(.:format) devise/confirmations#create
new_user_confirmation GET /confirmation/new(.:format) devise/confirmations#new
GET /confirmation(.:format) devise/confirmations#show
user_reviser POST /users/:user_id/reviser(.:format) revisers#create
new_user_reviser GET /users/:user_id/reviser/new(.:format) revisers#new
edit_user_reviser GET /users/:user_id/reviser/edit(.:format) revisers#edit
GET /users/:user_id/reviser(.:format) revisers#show
PATCH /users/:user_id/reviser(.:format) revisers#update
PUT /users/:user_id/reviser(.:format) revisers#update
DELETE /users/:user_id/reviser(.:format) revisers#destroy
users GET /users(.:format) users#index
user GET /users/:id(.:format) users#show
photos GET /photos(.:format) photos#index
POST /photos(.:format) photos#create
new_photo GET /photos/new(.:format) photos#new
edit_photo GET /photos/:id/edit(.:format) photos#edit
photo GET /photos/:id(.:format) photos#show
PATCH /photos/:id(.:format) photos#update
PUT /photos/:id(.:format) photos#update
DELETE /photos/:id(.:format) photos#destroy
pages GET /pages(.:format) pages#index
POST /pages(.:format) pages#create
new_page GET /pages/new(.:format) pages#new
edit_page GET /pages/:id/edit(.:format) pages#edit
page GET /pages/:id(.:format) pages#show
PATCH /pages/:id(.:format) pages#update
PUT /pages/:id(.:format) pages#update
DELETE /pages/:id(.:format) pages#destroy
autocomplete_user_country_suggestions GET /suggestions/autocomplete_user_country(.:format) suggestions#autocomplete_user_country
autocomplete_user_city_suggestions GET /suggestions/autocomplete_user_city(.:format) suggestions#autocomplete_user_city
autocomplete_user_school_suggestions GET /suggestions/autocomplete_user_school(.:format) suggestions#autocomplete_user_school
autocomplete_user_major_suggestions GET /suggestions/autocomplete_user_major(.:format) suggestions#autocomplete_user_major
suggestions GET /suggestions(.:format) suggestions#index
POST /suggestions(.:format) suggestions#create
new_suggestion GET /suggestions/new(.:format) suggestions#new
edit_suggestion GET /suggestions/:id/edit(.:format) suggestions#edit
suggestion GET /suggestions/:id(.:format) suggestions#show
PATCH /suggestions/:id(.:format) suggestions#update
PUT /suggestions/:id(.:format) suggestions#update
DELETE /suggestions/:id(.:format) suggestions#destroy
conversation_messages GET /conversations/:conversation_id/messages(.:format) messages#index
POST /conversations/:conversation_id/messages(.:format) messages#create
conversations GET /conversations(.:format) conversations#index
POST /conversations(.:format) conversations#create
post_comments GET /posts/:post_id/comments(.:format) comments#index
POST /posts/:post_id/comments(.:format) comments#create
new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment GET /posts/:post_id/comments/:id(.:format) comments#show
PATCH /posts/:post_id/comments/:id(.:format) comments#update
PUT /posts/:post_id/comments/:id(.:format) comments#update
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
post_places GET /posts/:post_id/places(.:format) places#index
POST /posts/:post_id/places(.:format) places#create
new_post_place GET /posts/:post_id/places/new(.:format) places#new
edit_post_place GET /posts/:post_id/places/:id/edit(.:format) places#edit
post_place GET /posts/:post_id/places/:id(.:format) places#show
PATCH /posts/:post_id/places/:id(.:format) places#update
PUT /posts/:post_id/places/:id(.:format) places#update
DELETE /posts/:post_id/places/:id(.:format) places#destroy
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
You have a singular resource definition for your :reviser route. This makes sense for what you're trying to do, however the route generated by form_for [current_user, #reviser] will try to generate a route with both a :user_id, and an :id to identify your reviser.
So, the :id field isn't defined in your case since resource :reviser doesn't create an :id.
The solution is to explicitly set the url in your form_for to the route your want:
It should be something along the lines of:
form_for #reviser, url: edit_user_reviser_path(user_id: current_user.id)
The bigger issue with your code is that you're still directly referencing reviser by id in your controller. Under your current route settings, this will return an error on the Reviser.find() method. However, more importantly this presents a security concern since a malicious user could send an id param in the PATCH request to hijack and update a record that belongs to another user.
A simple solution is to just reference the reviser object directly on current_user.
def set_reviser
#reviser = current_user.reviser
end

Attribute Not Changing in DB

I am trying to change an attribute for contract, allowing the user to "approve" or "reject"
<%= link_to_unless_current("Approve", { decision: "approve" }) %>
<%= link_to_unless_current("Reject", { decision: "reject" }) %>
I am not getting any errors but the change is not showing up in my database. In my rails console, it seem like the action is being pass through. I've also added :status to my strong params in my contracts controller.
Here is my controller snippet
def evaluate
if params[:decision] == "approve"
#contract.status = "approve"
else params[:decision] == "reject"
#contract.status = "reject"
end
#contract.save
end
And my controller params
def contract_params
params.require(:contract).permit(:price, :start_date, :end_date, :open_ended, :lessor_contact_name, :lessor_business_name, :lessee_name, :lessee_email, :lessee_address, :lessee_business_name, :lessee_guarantor, :status)
end
And here is my rails console. You'll see that the contract is being "approved". . . it's just not saving to the db.
Started GET "/spaces/1/contracts/17?decision=approve" for ::1 at 2015-08-07 09:23:27 -0400
ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by ContractsController#show as HTML
Parameters: {"decision"=>"approve", "space_id"=>"1", "id"=>"17"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 2]]
Space Load (0.1ms) SELECT "spaces".* FROM "spaces" WHERE "spaces"."id" = ? LIMIT 1 [["id", 1]]
Property Load (0.1ms) SELECT "properties".* FROM "properties" WHERE "properties"."id" = ? LIMIT 1 [["id", 1]]
Contract Load (0.2ms) SELECT "contracts".* FROM "contracts" WHERE "contracts"."id" = ? LIMIT 1 [["id", 17]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]]
Rendered contracts/_landlord.html.erb (6.5ms)
Rendered contracts/show.html.erb within layouts/application (11.6ms)
Rendered layouts/_header.html.erb (0.8ms)
Completed 200 OK in 563ms (Views: 494.5ms | ActiveRecord: 2.1ms)
And here are my routes
resources :spaces do
collection do
get 'search'
end
resources :galleries do
resources :pictures
end
resources :contracts do
post 'evaluate', on: :member
end
resources :reviews
end
Any help is great. Thanks
The problem you are having is directly related to the way that rails updates and saves data in the database. In your evaluate method you are setting the value of status to approve or reject, but simply setting the value doesn't actually save the value. So, you can do one of two things.
1) In your evaluate method you can save the record after setting it:
def evaluate
if params[:decision] == "approve"
#contract.status = "approve"
else params[:decision] == "reject"
#contract.status = "reject"
end
#contract.save
end
2) Or you can use the update_attributes which automatically saves it for you:
def evaluate
if params[:decision] == "approve"
#contract.update_attributes(status: "approve")
else params[:decision] == "reject"
#contract.update_attributes(status: "reject")
end
end
Try that out and see how it goes.
Firstly, it looks like you misspelled the parameter name. Change it to this:
<%= link_to_unless_current("Approve", { decision: "approve" }) %>
<%= link_to_unless_current("Reject", { decision: "reject" }) %>
...because you use params[:decision] in your controller, not params[:evaluate].
Secondly, I'm not very sure that decision (or evaluate) parameter would present in your initial request to the Rails, when you render this view. Just to make things certain, use regular if operator instead:
<% decision = {'approve' => 'reject', 'reject' => 'approve'}[#contract.status] %>
<%= link_to("Approve", url_for(decision: decision)) %>
Finally, you have wrong URL for your link. That's the right one:
<%= link_to("Approve", url_for(action: 'evaluate', decision: decision), method: :post) %>

ruby like query error

This is my code for mysql like query:
def search
params.permit!
#query = params[:query]
respond_to do |format|
#outlet = Outlet.select(:name).where("name like ?","%#{#query}%")
format.json { render json: #outlet }
end
end
It renders all of my data from table. It does not respond to the query. Do you have any ideas?
My route is:
namespace :api do
resources :outlets, :defaults => { :format => 'json'}
get 'outlets/auto_complete' => 'outlets#auto_complete', :defaults => { :format => 'json'}
post 'outlets/search' => 'outlets#search', :defaults => { :format => 'json' }
end
The development.log is
Started POST "/api/outlets/search" for 127.0.0.1 at 2015-05-30 16:56:22 +0530
Processing by Api::OutletsController#search as JSON
Parameters: {"outlet"=>{"query"=>"life"}}
[1m[35mOutlet Load (0.1ms)[0m SELECT `outlets`.`name` FROM `outlets` WHERE (name like '%%')
Completed 200 OK in 28ms (Views: 22.3ms | ActiveRecord: 1.7ms)
Looking at the log file and below trace :-
Parameters: {"outlet"=>{"query"=>"life"}}
I found the issue. You need to do #query = params[:outlet][:query].
It is because params[:query] is nil, so the resulting sql is
where name like '%%'
You do have a query parameter in params[:outlet][:query] which you could use without changing your view.
However, as you're not creating or updating an Outlet, and query probably isn't an attribute of the Outlet model, it doesn't really make sense to structure the form in this way.
Try using form_tag instead of form_for and don't pass it an instance of Outlet. Also use text_field_tag instead of form.text_field. This way params[:query] will be set, instead of being wrapped under params[:outlet].
The new form would look a bit like this:
<%= form_tag do %>
<%= text_field_tag :query %>
<%= submit_tag %>
<% end %>

Rails first_or_create! creating null values in database table

I'm using first_or_create to populate a table with a list of email subscribers (called members). The code is as follows:
def community_members=(members)
self.members = members.split(",").map do |member|
Member.where(email: member.strip, community_id: self.id).first_or_create! unless member.strip == nil
end
end
Everything works fine, except that when I add additional emails to the same community, the table turns the "community_id" column for all previous rows to NULL.
Here's the server log:
Member Load (0.2ms) SELECT "members".* FROM "members" WHERE "members"."email" = $1 AND "members"."community_id" = $2 ORDER BY "members"."id" ASC LIMIT 1 [["email", "lisa#holy.com"], ["community_id", 1]]
SQL (0.3ms) INSERT INTO "members" ("email", "community_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["email", "lisa#holy.com"], ["community_id", 1], ["created_at", "2015-04-30 16:14:25.930012"], ["updated_at", "2015-04-30 16:14:25.930012"]]
Member Load (0.2ms) SELECT "members".* FROM "members" WHERE "members"."community_id" = $1 [["community_id", 1]]
SQL (0.4ms) UPDATE "members" SET "community_id" = NULL WHERE "members"."community_id" = $1 AND "members"."id" = 30 [["community_id", 1]]
(0.3ms) COMMIT
The first "Member" load does exactly what it's supposed to do. But for some reason it always ends with the second Member load that goes in and sets all "community_id" fields to NULL.
Right now I call :community_member from a form on a community page:
<%= form_for(#community) do |f| %>
<%= f.text_area :community_members, class:"form-control input-lg", placeholder:"Please add your list of comma separated member email addresses here" %>
<%= f.submit "Save", class: "btn btn-lg btn-green btn-block pad-top" %>
<% end %>
Seems like I'm missing something obvious here. Any ideas? Thank you.
You're going to want to find by the unique attribute, email, and create by community name, I think.
If that's the case, you'll have to do something like:
Member.where(email: member.strip).first_or_create(community: self) unless...
If you have records with non-unique emails, you'll have to redesign your associations.
class Subscriber
#this should have the email attribute
has_many :community_subscribers
has_many :communities, through: :community_subscribers
end
class CommunitySubscriber
#this is a 'bridge' table
belongs_to :subscriber
belongs_to :community
end
class Community
has_many :community_subscribers
has_may :subscribers, through: :community_subscribers
#I suggest new method and arg names
#Using self will keep the query within the scope of the community you are working on
#This also allows for creation of Subscriber records if you insist placing that here
#are you sure you want to map instead of just iterating the split list of emails?
def new_subscribers(emails)
emails.split(",").map do |email|
clean_email = email.strip
subscriber = Subscriber.where(email: clean_email).find_or_create unless clean_email.blank?
self.community_subscribers.where(subscriber: subscriber).first_or_create unless subscriber.blank?
end
end
end
Docs:
http://apidock.com/rails/v3.2.1/ActiveRecord/Relation/first_or_create
http://guides.rubyonrails.org/v3.2.13/active_record_querying.html#first_or_create

How to assign variables when using RSpec to test jbuilder views

I am trying to write RSpec tests to test the templates I have constructed using jbuilder which ultimately serves up JSON data for my API. I have many tests in spec/controllers which test my controller functionality, but I am looking to also test that I am rendering the correct JSON fields in my jbuilder views. Here is an example of what I have setup:
# app/views/api/v1/users/create.json.jbuilder
json.first_name user.first_name
# spec/views/api/v1/users/create.json.jbuilder_spec.rb
require 'spec_helper'
describe "api/v1/users/create.json.jbuilder" do
it "renders first_name" do
assign( :user, User.create( :first_name => "Bob" ) )
render
hash = JSON.parse( rendered )
hash.has_json_node( :first_name ).with( "Bob" )
end
end
What I get when I run rspec spec/views/api/v1/users/create.json.jbuilder_spec.rb is the following error
Failures:
1) api/v1/users/create.json.jbuilder render a user
Failure/Error: render
ActionView::Template::Error:
undefined local variable or method `user' for #<#<Class:0x007fa2911c3118>:0x007fa29105f2b8>
# ./app/views/api/v1/users/create.json.jbuilder:1:in `_app_views_api_v__users_create_json_jbuilder___3806288263594986646_70168098229960'
# ./spec/views/api/v1/users/create.json.jbulder_spec.rb:6:in `block (2 levels) in <top (required)>'
No matter how I have tried to assign/create/pass a user object to the template, it fails. Any idea what I might be doing wrong?
After much reading and iteration, this is what works:
require 'spec_helper'
describe "api/v1/users/create.json.jbuilder" do
let( :user ) { User.create( :not_strict => true ) }
it "renders first_name" do
render :template => "api/v1/users/create", :locals => { :user => user }, :formats => :json, :handler => :jbuilder
rendered.should have_json_node( :first_name ).with( user.first_name )
end
end
note: the have_json_node comes from the api_matchers gem.
assigns method sets instance variables, your view should be #user.first_name instead of user.first_name, or is that a partial? if it's a partial you should do render :partial => ..., if it's a template you should use #user