I need to create search form to search for all the cases pt_name of the user
I got this error
Couldn't find User with 'id'=
In cases controller
def index
#user =User.find(params[:id])
#cases=#user.cases
if params[:search]
#search_term = params[:search]
#cases= #user.cases.casesearch_by(#search_term)
end
end
in case model
class Case < ActiveRecord::Base
belongs_to :user
def self.casesearch_by(search_term)
where("LOWER(pt_name) LIKE :search_term OR LOWER(shade) LIKE :search_term",
search_term: "%#{search_term.downcase}%")
end
end
in cases index.html.erb
<%= form_for "",url: cases_path(#user.id), role: "search", method: :get ,class: "navbar-form navbar-right" do %>
<%= text_field_tag :search, #search_term,placeholder: "Search..." %>
<% end %>
The problem is the first line in your controller.
When the form is submitted it's going to cases_path(#user.id) - that's what you specified in your form.
If you're checking with rails routes you'll see that cases_path is actually going to "/cases" (I am assuming you did not overwrite it) and that there isn't any placeholder for an id (like it would be for the show action for example which goes to "/cases/:id".
Now you still specify #user.id in cases_path(#user.id) and then you try to find a user with the id from the params. But if you check your params once you arrived in the controller (with binding.pry or other tools), you will see there is no key :id in the params. You can also check the url it is going to, I believe it will look something like this: "/cases.1".
You can solve that by changing the path to
cases_path(user_id: #user.id)
This way you add a new key value pair to the params hash and then in your controller you need to change it accordingly:
#user =User.find(params[:user_id])
You can also add a hidden field into your form in order to pass along the user id:
<%= form_for "", url: cases_path, role: "search", method: :get, class: "navbar-form navbar-right" do %>
<%= text_field_tag :search, #search_term,placeholder: "Search..." %>
<%= hidden_field_tag :user_id, #user.id %>
<% end %>
And then retrieve it in the controller.
To check your params that you get in the controller action use a gem like pry byebug or just the keyword raise and then inspect the params variable.
Related
I'm trying to replicate railscasts #343 in my rails app with this code:
class Article < ActiveRecord::Base
def self.text_search(query)
if query.present?
where("description ## :q", q: query)
else
where(nil)
end
end
class ArticlesController < ApplicationController
def index
#articles = Article.text_search(params[:query])
end
and this view form:
<%= simple_form_for articles_path, method: :get do |f| %>
<%= f.input :query, autofocus: true, label: false %>
<%= f.submit 'Search', name: nil %>
<% end %>
In console text_search method works. From log:
Parameters: {"utf8"=>"✓", "/en/articles"=>{"query"=>"word"}, "locale"=>"en"}
I see that params are sent but I still get all articles listed and no search is performed: Article Load (0.5ms) SELECT "articles".* FROM "articles"
I have rails 4.2.2, PostgreSQL 9.3.7, ruby 2.2.5
You need to pass the search params as:
Article.text_search(params[:search]["query"])
And add #article to the simpleform_for line:
<%= simple_form_for #article, articles_path, method: :get do |f| %>
And add #article = Article.new to your new action in the controller.
Your attribute will then be nested inside :article! You can see it in the console output that the parameters sent by the articles form will always be wrapped in the class name the form is for (Article) via Rails Form helpers.
Update:
Because the simple_form_for wasn't passed #article specifically, it will be wrapped in the name of the submit action which in this case is search. Leaving you with: params[:search]["query"]
A more Rails approach would be to include #article thus wrapping your parameter hash as described above (params[:article][:query]):
<%= simple_form_for #article, {url here}, {options like 'method: :get' or 'remote: true' here } do |f| %>
For extra info. since everyone loves extra info, Rails provides a way to specify the wrapper name for your params hash in the form_for call thus you can also do something like:
<%= simple_form_for (#article, as: :search), articles_path, method: :get do |f| %>
This would be best practice if you really want to keep the params wrapped in 'search' IMO because you're specifying the class object in the form call and letting yourself know what it's doing with that object.
I've a settings controller setup like this:
class Admin::SettingsController < ApplicationController
def index
#settings = Setting.all
end
def update
setting_params.each do |key, value|
Setting.where(key: key).first.update_attribute :value, value
end
redirect_to admin_settings_path, notice: "Settings saved."
end
private
def setting_params
params.require(:settings).permit(:site_title, :site_desc)
end
end
The index action has a view file in relevant path, its code is as follows:
<h1>Settings</h1>
<%= form_tag admin_settings_path, method: "put" do %>
<p>
<label>Site Title:</label>
<%= text_field_tag "settings[site_title]" %>
</p>
<p>
<label>Site Description:</label>
<%= text_field_tag "settings[site_desc]" %>
</p>
<p>
<%= submit_tag "Save settings" %>
</p>
<% end %>
Now, I'm able to save/update these fields data in relevant model and I can see the data through command Setting.all in rails console. But the issue is, after saving the record via form when I reload the settings index page the form is blank and it is not showing previously saved values in the fields.
What I'm doing wrong here?
You can do what has been mentioned in the previous answer i.e. using a form_for. However, this can also be accomplished by creating a Hash in both the controller actions that creates and processes this form.
In the action that creates this form, the values in the hash could be initialized to blanks/zeros depending upon the input tag and in the action that processes this form, the values in the hash could be assigned to the values obtained from the posted params[].
I ran into the similar issue with form_tag and I used the following code in my index action i.e. the action that renders the form initially:
#search = {name: "", ranking_group: 0}
Whereas, in the search action, I used the following code to fill up this hash:
#search = {name: params[:name], ranking_group: params[:ranking_group]}
Finally, in the view, I used the appropriate default value options with the input tags as below:
<%= text_field_tag :name, #search[:name] %>
<%= select_tag :ranking_group, options_for_select(AmenityEntities::Amenity.ranking_group_options, #search[:ranking_group]), include_blank: true %>
Hope this helps.
I think you need to use form_for(#variable) instead of just a form_tag because you need to persiste the object after save.
form_for works with resources, take a look here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html
I have tried to create a mailer using the following code:
routes code
resources :listings do
member do
put :lead
end
end
mailer controller code
def lead(listing)
#listing = listing
mail(to: #listing.leadrecepient, subject: "test")
end
standard controller code
def lead
Enquiry.lead(#listing).deliver
end
view
<%= form_for lead_listing_path(#listing), method: :put do |listing| %>
<%= listing.text_field :name %>
<%= listing.submit %>
<% end %>
In the context of a business directory, I want it so that there is a enquiry form on each listing page that when filled out and submitted, the information is sent to the relative listing email.
The problem however is that when I type into the form and click submit, I get the following error:
param is missing or the value is empty: listing
This seems to be because I have it in the "listing" controller which controls the showing and creation of the business listing itself. I therefore have strong params for a new listing which contains all the new listing variables:
def listing_params
params.require(:listing).permit(:fullname, :jobtitle, :email, :franchisename, :leadrecepint, :shortdescription, :longdescription, :website, :branchcount, :scale, :mininvestment, :investmentrange, :category, :hexbg, :logourl, :facebook, :twitter, :linkedin, :googleplus, :approved)
end
How do I go about fixing this? I'm a beginner if I'm honest, could really do with some help to get this mailer working! Thanks.
Strong params are for when you are submitting new resources or modifications to resources. To protect against people adding extra parameters that may circumvent security or other aspects of your application unexpectedly.
If you are adding an action to an existing resource that the user is authorized to access, which this appears to be, you want to just find the object by ID, and use it. So instead of finding it using the params filtered through listing_params, just find it like this in the controller:
def lead
listing = Listing.find(params[:id])
Enquiry.lead(listing).deliver
redirect_to listing
end
And invoke it using a simple link, instead of this:
<%= form_for lead_listing_path(#listing), method: :put do |listing| %>
<%= listing.text_field :name %>
<%= listing.submit %>
<% end %>
Just use this in your view:
= link_to 'Go!', lead_listing_path(#listing), method: :put
Nothing more to it.
I would like to have a drop down menu with a list of all the user names in the db. From there, I would like the user to choose his/her name and be able to click login and be taken to their respective page. At this point, a password is not needed. Currently, I have the following:
controller:
def login
#user = User.new
#users = User.all
# #user = User.find_by_id(:id)
# redirect_to user_path(#user)
end
view:
<%= form_for #user, url: '/login', html: {method: 'get'} do |f| %>
<%= f.label "Name" %>
<br/>
<%= select_tag :user, options_for_select(#users) do |users| %>
<%= link_to users.name, users %>
<% end %>
<br/>
<br/>
<%= f.submit 'Login' %>
<% end %>
I cannot seem to link the user to their path and also, i want to show the users name in the drop down menu. Currently, it shows a hexidecimal pointer.
Thank you in advance.
You shouldn't be making a new User object here: you just want to load one out of the database. What you want to do in the controller is just to set current_user to be one of the existing users, right?
Also you've got the form submitting back to the action which loads the form in, which seems weird. I would make it submit to a new action, like "set_current_user" which is a POST action.
in your login template:
<%= form_tag '/set_current_user' do %>
<%= f.label "Name" %>
<br/>
<%= select_tag "user_id", options_for_select(#users.collect{|user| [user.name, user.id] } %>
<br/>
<br/>
<%= submit_tag 'Login' %>
<% end %>
in the controller (you'll need to amend routes.rb to make the '/set_current_user' go to this action) you then need to set something which will keep the user logged in. The traditional way to do this is via session[:user_id], and to have a method current_user which uses this.
def set_current_user
session[:user_id] = params[:user_id]
redirect_to "/" and return
end
Your initial approach is reminiscent of how this sort of thing is normally handled, wherein you do have a form_for, but it's for a UserSession object rather than a User object.
I have an Article resource and have defined resourceful routes for it. I want to create a simple page that shows the articles of the current user. I am aware that it is possible to do so by adding another action, for example 'search' to articles controller which will contain the custom code that searches for articles that have the same user id. And for the routes:
resources :articles do
get 'search'
end
But I'm not sure if adding a custom action is a good idea in this case. I'm thinking I can still use the index action (which shows all articles) and pass some sort of parameter from the url so that it can distinguish if the user wants to see all articles or just his own. But I'm not sure exactly how this can be done. Any help would be great. Thanks!
You can use the query string to pass parameters. see here
So you can pass something like .../articles?user_id=2
In your controller, just change the behavior according to the user_id parameter.
you don't need to create a new action/view for it.
You can add a small form to filter all articles or only my articles, for example:
<%= form_tag articles_path, method: :get do %>
<%= radio_button_tag :search, "all", :checked => true %>
<%= label_tag :all %><br />
<%= radio_button_tag :search, "my" %>
<%= label_tag :my_articles %><br />
<%= submit_tag "filter", name: nil %>
<% end %>
than in your controller:
def index
if params[:search] == 'my'
#articles = current_user.articles
else
#articles = Article.all
end