pg_search model and controller relation - ruby-on-rails

This probably is a nooby one. I'm building a search form.
In the model document.rb, I have this :
pg_search_scope :search_full_text,
:against => :full_text,
:using => {
:tsearch => {
:prefix => true
}
}
and in documents_controller.rb, I have :
def find
$results = Document.search_full_text(params[:ch_acte][:text])
end
But NOTHING gets send to the database. The server log only says:
Started POST "/documents/find" for ::1 at 2017-01-19 08:48:07 +0100
Processing by DocumentsController#find as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZkqVYMuqMqnUjLer/FVdBdtv4cycp71dXqPQw6j0mfHKX5ptin7p7YiYFj8bNtjciQDmHzbKtBnZoILpGGvl8Q==", "ch_acte"=>{"text"=>"complet", "words"=>"", #[cut for brievity]}, "commit"=>"Cherche"}
Rendering documents/find.html.erb within layouts/messources
Rendered documents/find.html.erb within layouts/messources (0.4ms)
Completed 200 OK in 216ms (Views: 210.2ms | ActiveRecord: 0.0ms)
Other than the method pg_search_scope in the model and calling that method in the controller, what must I do to get this sent to the database?
When I run Document.search_full_text("esp") in rails console, it works fine.
UPDATE
I added this in documents/find.html.erb :
<% $results.each do |m| %>
<p>The id is <%= m.id %>.</p>
<% end %>
I get an page that displays my menu, and only white after that...

You should understand that Rails tries to be as performant as possible. When you build a search it does NOT execute until you attempt to access the results of the search.
So you would do...
def find
#documents = Document.search_full_text(params[:ch_acte][:text])
end
Then in your find.html.erb you might do...
<% #documents.each do |document| %>
<%= document.name %>
<% end %>
The query is only executed when the #documents.each line is executed to retrieve the documents... i.e. only when it needs to be executed.

Related

Insert multirows from checkboxes [duplicate]

I am stuck in that although my array parameter is being captured, it fails to insert it into the database. I do not get an unpermitted parameters error or anything. It just fails to recognize the array when inserting to the DB.
What I would like to do: Capture any box that is checked off, and insert the data as separate rows into the database.
Here is what I have:
/subscribe/categories/2
<div>
<%= simple_form_for #subscription do |f| %>
<div class="form-inputs">
<%= f.hidden_field :dashboard_id, value: 1 %>
<%= f.hidden_field :category_id, value: #category.id %>
<%= f.collection_check_boxes :feed_id, Feed.where("category_id = ?", #category), :id, :name %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
</div>
CategoriesController
def show
#subscription = Subscription.new
end
SubscriptionsController
def subscription_params
params.require(:subscription).permit(:dashboard_id, :category_id, :feed_id => [])
end
When submitted, here is the console output:
Processing by SubscriptionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Zw2VkwujDLQjV4krjPF8N1EiYo5L/XOrUwedlHCvwB0=", "subscription"=>{"dashboard_id"=>"1", "category_id"=>"2", "feed_id"=>["3", "4", ""]}, "commit"=>"Create Subscription"}
(0.2ms) BEGIN
SQL (1.6ms) INSERT INTO `subscriptions` (`category_id`, `created_at`, `dashboard_id`, `updated_at`) VALUES (2, '2014-01-06 02:17:41', 1, '2014-01-06 02:17:41')
(116.6ms) COMMIT
Redirected to http://localhost:3000/subscriptions/3
Completed 302 Found in 173ms (ActiveRecord: 119.3ms)
Two questions:
Why is there an extra "" for my feed_id array? (Only 2 possible checkboxes)
Why am I not capturing the array to insert it into the database?
Thanks!
The reason your array is not being inserted into the database is that Active Record currently does not support the Postgresql array type. In order to insert these as separate rows the check-boxes need to be represented as individual instances of a model.
Possibly something like...
Category < ActiveRecord::Base
has_many: feeds
...
end
Feed < ActiveRecord::Base
belongs_to: category
...
end
Now this would also mean that you would need to use the form_tag helper instead of the form_for. This would allow you to create a composite form consisting of multiple individual objects. Inserting this would just mean iterating and inserting over each object; giving you separate rows. Hope this helps.
For anyone that wants to know how to do this, here is one solution I've come up with. Everything in my first post remains the same. In my SubscriptionsController (from which the form is created), here is my create action:
def create
dashboard = params[:subscription][:dashboard_id]
category = params[:subscription][:category_id]
feed = params[:subscription][:feed_id]
#subscription = feed.map { |subscribe| Subscription.create(dashboard_id: dashboard, category_id: category, feed_id: subscribe) }
end
Works as advertised. If anyone thinks for some reason that I am overlooking this is a terrible idea, please comment.

Ruby on rails Common error: Params missing?

I am building a Order management system. I recently posted a problem about adding a order to a customer. It seems that i have fixed it for 99%. if i look in my terminal it first finds the current customer ID and then creates a new order. The following result is.
Customer Load (0.2ms) SELECT "customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1 [["id", 111]]
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "orders" ("customer_id", "created_at", "updated_at") VALUES (?, ?, ?) [["customer_id", 111], ["created_at", "2015-11-12 13:28:21.185604"], ["updated_at", "2015-11-12 13:28:21.185604"]]
(8.2ms) commit transaction
But the problem is, it doesn't add the params. I did this intentionally just to check if my syntax would execute the following sql statement. But once i add params i get a common error "param is missing or the value is empty: order"
Here is my code:
Controller
def createorders
#customer = Customer.find(params[:id]) #find current id??
#current_user = Order.find(params[:id])
#orders = #customer.orders.new(order_params)
if #orders.save
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
#If save fails, redisplay the form so user can fix problems
render('new') #het zit in de new.html template
end
end
private
def order_params
#same as using "params[:subject]", expect that it:
# - raises an error if :subject is not present
# - allows listed attributes to be mass-assigned
params.require(:order).permit(:pakket, :verstuurt)
end
end
View
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subject new">
<h2>Create Subject</h2>
<%= form_for(:order, :url=> {:action => 'createorders'}) do |f| %>
<table summary="subject form fields">
<tr>
<th>pakket</th>
<td><%= f.text_field(:pakket) %></td>
</tr>
<tr>
<th>verstuurt</th>
<td><%= f.text_field(:verstuurt) %></td>
</tr>
</table>
<div class="form-buttons">
<%= submit_tag("Create Subject") %>
</div>
<% end %>
</div>
Error message
ActionController::ParameterMissing in OrderController#createorders
param is missing or the value is empty: order
Extracted source (around line #107):
105
106
107
108
109
110
def order_params
params.require(:order).permit(:pakket, :verstuurt)
end
end
Serverside Log
Started GET "/order/createorders?id=111" for ::1 at 2015-11-13
11:58:30 +0100 Processing by OrderController#createorders as HTML
Parameters: {"id"=>"111"} Customer Load (0.2ms) SELECT
"customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1
[["id", 111]] Completed 400 Bad Request in 5ms (ActiveRecord: 0.2ms)
ActionController::ParameterMissing (param is missing or the value is empty: order): app/controllers/order_controller.rb:107:in
order_params' app/controllers/order_controller.rb:44:in
createorders'
Rendered /Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_source.erb
(8.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.6ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
(1.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/actionpack-4.2.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
within rescues/layout (68.2ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_markup.html.erb
(0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_inner_console_markup.html.erb
within layouts/inlined_string (0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/_prompt_box_markup.html.erb
within layouts/inlined_string (0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/style.css.erb
within layouts/inlined_string (0.4ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/console.js.erb
within layouts/javascript (60.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/main.js.erb
within layouts/javascript (0.3ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/error_page.js.erb within layouts/javascript (0.5ms) Rendered
/Users/cecil/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/web-console-2.2.1/lib/web_console/templates/index.html.erb
(124.2ms)
Thank you stackoverflow for showing me support. I am new with ruby, and i understand i am making noob mistakes. So pointing out flaws are welcome!
I was ignoring your minor, non-fatal issues earlier while I was focused on locating the major issue, but I'll include them now that the major issue is apparent.
First, I'll discuss Rails naming conventions a little bit. You have two models, which are named Customer and Order. You've used the singular form of the noun for these, which is good. Each instance of a model is one thing, so it should be singular. Your controller for the Order model actions, however, should be named with the plural form, so it should be called OrdersController. This is because it controls the actions related to all of your orders. This leads us to your createorders action, which would make a little more sense if it were named createorder, since it only creates one Order. Actually, though, the convention is to name that action create. The action is in your OrdersController, so we already assume that it deals with an Order instance. (When you have Rails automatically generate REST-ful routes for a model's controller with the resources function, it assumes you have an action named create.) Lastly, in your create method, the new Order instance that will be referenced in your view should be called #order instead of #orders, since it contains only one Order.
Now things get a little more complicated. Your param is missing error means exactly that. The parameters for the new Order instance are missing. The request to the server that is producing that error is a GET request that has only one parameter, which you're providing in your URL with ?id=111. Your form's data is not being submitted to the server with that GET request. You should be doing a POST request to create a new Order. I'm going to avoid further exploration (and speculation without seeing your full code) regarding why things aren't working right now and I'll just suggest some key adjustments. It's turning in to a bit a puzzle to figure out how your app works without seeing all of the pieces.
In routes.rb, you should have this line:
resources :customers, :orders
I've made minimal changes to the view you provided, which I assume is called show.html.erb and is in your app/views/customers folder:
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subject new">
<h2>Create Subject</h2>
<%= form_for #order do |f| %>
<table summary="subject form fields">
<tr>
<th>pakket</th>
<td><%= f.text_field(:pakket) %></td>
</tr>
<tr>
<th>verstuurt</th>
<td><%= f.text_field(:verstuurt) %></td>
</tr>
</table>
<%= f.hidden_field :customer_id %>
<div class="form-buttons">
<%= submit_tag("Create Subject") %>
</div>
<% end %>
</div>
Here is the necessary code from customers_controller.rb to support it:
def show
customer = Customer.find params[:id]
#order = customer.orders.new
end
Notice, in the view, the parameter for form_for is the instance that was created in the controller. Also, I've added a hidden field to submit the customer_id with the new Order data.
Finally, your create action in orders_controller.rb might look like this:
def create
#order = Order.new(order_params)
if #order.save
flash[:notice] = "Subject created successfully"
redirect_to(:action => 'index')
else
render 'customers/show'
end
end
And your order_params method should be changed to include the customer_id parameter:
def order_params
params.require(:order).permit(:pakket, :verstuurt, :customer_id)
end
Notice that on a failed save, the action renders customers/show, because this is the page that they were on where the save failed. This will allow Rails to re-populate the form (in the same context) with the data that was present during the failed submission.

Incorrect routing in controller using Rails 4 Autocomplete

I'm following along with this tutorial (http://www.yoniweisbrod.com/autocomplete-magic-with-rails/) using jQuery-ui's autocomplete, but when I attempt to search using the text field, it routes to the controller's show method instead of the autocomplete_ingredient_name method.
Here's the code for my form:
<%= form_tag(cocktail_path(1), :method => 'get', :class => "search_form", :remote => true) do %>
<%= label_tag(:query, "Choose ingredients:") %>
<%= autocomplete_field_tag(:query, params[:query], autocomplete_ingredient_name_cocktails_path, {class: "search-query", placeholder: "", type: "search"}) %>
<% #ingredients.each do |ingredient| %>
<%= hidden_field_tag "ingredients[]", ingredient.name %>
<% end %>
<%= submit_tag("Search") %>
<% end %>
And my controller.
class CocktailsController < ApplicationController
autocomplete :ingredient, :name
def index
#cocktails = []
#ingredients = []
end
def autocomplete_ingredient_name
#ingredients = Ingredient.order(:name).where("name LIKE ?", "'%#{params[:query]}%'")
respond_to do |format|
format.html
format.json {
render json: #ingredients.map(&:name)
}
end
end
def show
hash = {}
#cocktails = []
#ingredients = Ingredient.all.map {|ingredient| ingredient}
#ingredients.select! {|ingredient| ingredient.name.downcase.include?(params[:query])}
if params[:ingredients]
old_ingredients = []
params[:ingredients].each do |ing|
old_ingredients << Ingredient.find_by(name: ing)
end
cocktails = #ingredients.map {|ingredient| ingredient.cocktails }.flatten
old_cocktails = old_ingredients.map {|ingredient| #cocktails << ingredient.cocktails }.flatten!
old_cocktails.each do |cocktail|
hash[cocktail] = 1
end
cocktails.each do |cocktail|
if hash.has_key?(cocktail)
#cocktails << cocktail
end
end
#cocktails = #cocktails.uniq.flatten
else
#cocktails = #ingredients.map {|ingredient| ingredient.cocktails }.flatten
end
end
end
And here is the message from my server, going to the CocktailsController#show method, instead of the autocomplete method.
Started GET "/cocktails/autocomplete_ingredient_name?term=mi" for ::1 at 2015-10-12 15:32:21 -0500
Started GET "/cocktails/autocomplete_ingredient_name?term=mi" for ::1 at 2015-10-12 15:32:21 -0500
Processing by CocktailsController#show as JSON
Processing by CocktailsController#show as JSON
Parameters: {"term"=>"mi", "id"=>"autocomplete_ingredient_name"}
Parameters: {"term"=>"mi", "id"=>"autocomplete_ingredient_name"}
Ingredient Load (8.6ms) SELECT "ingredients".* FROM "ingredients"
Ingredient Load (8.6ms) SELECT "ingredients".* FROM "ingredients"
Completed 500 Internal Server Error in 38ms (ActiveRecord: 8.6ms)
Completed 500 Internal Server Error in 38ms (ActiveRecord: 8.6ms)
TypeError (no implicit conversion of nil into String):
app/controllers/cocktails_controller.rb:25:in `include?'
app/controllers/cocktails_controller.rb:25:in `block in show'
app/controllers/cocktails_controller.rb:25:in `select!'
app/controllers/cocktails_controller.rb:25:in `show'
TypeError (no implicit conversion of nil into String):
app/controllers/cocktails_controller.rb:25:in `include?'
app/controllers/cocktails_controller.rb:25:in `block in show'
app/controllers/cocktails_controller.rb:25:in `select!'
app/controllers/cocktails_controller.rb:25:in `show'
The code is supposed to create a jQuery-ui dropdown that predicts what you're searching, but the dropdown never shows up and it immediately returns a 500 error.
Any thoughts on why this isn't routing to the right method would be extremely appreciated!
This is likely because of a routing error, i.e. your GET "/cocktails/autocomplete_ingredient_name?term=mi" directive is handled by the wrong entry in your /config/routes.rb file.
Make sure the route that handles your autocomplete process is defined prior to the route that handles the show action of your cocktails controller.
Since the latter usually takes the form get 'cocktails/:id', the 'autocomplete_ingredient_name' part of the URI is affected to the :id component and the processing is delegated to the show action of your controller with said id.
The autocomplete route is defined, since the autocomplete_ingredient_name_cocktails_path directive in your form generates a properly formatted URI ; so I believe this is merely an issue of precedence.
You have another potential issue, however: your autocomplete query parameter is 'term' in your request, but it is 'query' in your controller action. They should have the one and same name.

Attaching params to form

In my app, a micropost is simply called an "item". On each user's "show" page, there should be a form for making a new "item" that belongs to that user.
I am getting stuck making such a form.
When the form is submitted, the controller action below fires:
#user = User.find_by(name: params[:name])
#user.items.create(item_params)
redirect_to 'root'
By the way, the 'item_params' method is
params.require(:item).permit(:title, :content, :user_id)
I am getting an error about the second line. The error is
undefined method 'items' for nil:NilClass
I checked in the rails console whether I could make a new item by first selecting a user by name
#user = User.find_by(name: "tester1")
then create an item for it with the below statement:
#user.items.create(title: "new_item_title", content: "new_item_content")
and the new item was created as expected. I cannot explain the browser error, though.
EDIT
The form in question is on a "show_user". Here is the log for the HTTP request for that page:
Started GET "/center/show_user?utf8=%E2%9C%93&name=tester&commit=Search" for 12
.0.0.1 at 2014-03-19 11:46:51 -0700
Processing by CenterController#show_user as HTML
Parameters: {"utf8"=>"√", "name"=>"tester", "commit"=>"Search"}
←[1m←[35mUser Load (1.0ms)←[0m SELECT "users".* FROM "users" WHERE "users"."
ame" = 'tester' LIMIT 1
Rendered center/show_user.html.erb within layouts/application (2.0ms)
Completed 200 OK in 23ms (Views: 18.7ms | ActiveRecord: 1.0ms)
The form is hosted on this page. Here is the request that is sent with submission of the form:
Started POST "/center/show_user" for 127.0.0.1 at 2014-03-19 11:47:14 -0700
Processing by CenterController#create_item_owned as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"P6mb63rhTHx6Q17zhfu4WXErG5Pb0
8t0d/L1RppKAl0=", "item"=>{"title"=>"uno", "content"=>"uno1"}, "commit"=>"Save I
tem"}
←[1m←[36mUser Load (1.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users
"."name" IS NULL LIMIT 1←[0m
Completed 500 Internal Server Error in 4ms
NoMethodError (undefined method `items' for nil:NilClass):
app/controllers/center_controller.rb:18:in `create_item_owned'
So no information about the user is being passed along with the parameters when the form is submitted. How how I fix this?
Here are my relevant routes:
get "center/show_user/" => 'center#show_user'
post "center/show_user" => 'center#create_item_owned'
The "create_item_owned" action is the one described at the beginning of this question.
The "show_user" action is
#user = User.find_by(name: params[:name])
#new_item = Item.new
How should I forward along those parameters in such a way that the new object created by the form is automatically associated with the specific user in the database (along with automatic creation of foreign keys)?
My form is
<%= form_for :item do |x| %>
Title: <%= x.text_field :title %> <br>
Content: <%= x.text_field :content %> <br>
<%= x.submit %>
<% end %>
I think you might still have to find by id rather than by name. The name might not be passed in the params. You should check your logs to see what params are being sent.

Rails: Couldn`t find #controller with ID of

When submitting an answer I get this error:
ActiveRecord::RecordNotFound (Couldn't find Question with ID=answer):
app/controllers/questions_controller.rb:6:in `show'
From what I understand I either made a error with passing an argument from the form or
didn`t define it correctly in my controller.
Would appreciate some help finding this bug, thanks in advance!
Questions_Controller:
class QuestionsController < ApplicationController
def index
end
def show
#question = Question.find(params[:id])
#choices = #question.choices
end
def answer
#choice = Choice.find(:first, :conditions => { :id => params[:id] })
#answer = Answer.create(:question_id => #choice.question_id, :choice_id => #choice.id)
if Question.last == #choice.question
render :action => "thank_you"
else
question = Question.find(:first, :conditions => { :position => (#choice.question.position + 1) })
redirect_to question_path(:id => question.id)
end
end
end
views/questions/show.html.erb :
<div data-role="content">
<div align="center">
<h3><%= #question.question %></h3>
</div>
<br><br>
<ul data-role="listview">
<% #choices.each_with_index do |c, i| %>
<% i = i + 1 %>
<li data-theme="c">
<%= link_to "#{i}. #{c.choice}", answer_questions_path(:id => c.id) %>
</li>
<% end %>
</ul>
</div>
::EDIT::
This happens when I try to select a choice & submit an answer while on the first question.
Started GET "/questions/1" for 127.0.0.1 at Thu Dec 01 01:38:36 -0500 2011
Processing by QuestionsController#show as
Parameters: {"id"=>"1"}
SQL (0.6ms) SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
Question Load (0.3ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = 1 LIMIT 1
Choice Load (10.8ms) SELECT "choices".* FROM "choices" WHERE ("choices".question_id = 1)
Rendered questions/show.html.erb within layouts/application (28.8ms)
Completed 200 OK in 424ms (Views: 118.0ms | ActiveRecord: 11.6ms)
Started GET "/questions/answer?id=1" for 127.0.0.1 at Thu Dec 01 01:38:38 -0500 2011
Processing by QuestionsController#show as
Parameters: {"id"=>"answer"}
Question Load (0.1ms) SELECT "questions".* FROM "questions" WHERE "questions"."id" = 0 LIMIT 1
Completed in 10ms
ActiveRecord::RecordNotFound (Couldn't find Question with ID=answer):
app/controllers/questions_controller.rb:6:in `show'
Hope this helps.
My best guess is that you don't have a route correctly setup. Assuming that you're using Rails 3 and you're using resources, you need to do add the following:
resources :questions do
member do
put 'answer'
end
end
This will create a route like /questions/#{id}/answer.
Answer is not an HTTP verb, so using resources in your routes will not create a route to your answer action.
Edit based on comment:
First, if you're updating or creating data, you should use put or post. It's a bad idea to modify data on the server with a get. Secondly, I assume that you would be doing an answer per question. If that is the case, you should do the action on a member, not a collection. Also, in your answer action, you have params[:id]. You won't get params[:id] if you try to do an action on a collection rather than a member.

Resources