How can I set a parameter using link_to in rails? - ruby-on-rails

In a haml file I have an element such as the following:
%th Movie Title
that I am trying to turn into a clickable element that will sort the column it is the header for. So far I've worked out that this may look something like the following
%th= link_to "Movie Title", "foo"
except I need to set a parameter and instead of going to "foo" I want to just reload the current page with the list of movies sorted in the controller (though separate research, my guess is that this can be done via something like:
def index
#movies = Movie.find(:all, :order => params[:sort])
end
Can someone give me some advice on what I should do about the link_to call? Is anything I've written above way off? Thanks.

Here you go :)
= link_to 'Movie Title', request.parameters.merge({:sort => "title ASC"})

Related

Storing values in Rails session

I'm taking a course on Rails, and I need to "remember" the values selected by the user across https requests, in order to filter a list.
I am supposed to do this in the session 'Hash'.
Here is my index:
def index
#list all different values for the key ratings
#all_ratings = Movie.uniq.pluck(:rating)
#order movie list based on interaction with link from view
#movies = Movie.order(params[:sort_param])
#filter movies by rating, based on checkbox from view
#movies = #movies.where(:rating => params[:ratings].keys) if params[:ratings].present?
# I intend to store here the ratings selected, and then save in session
#selected_ratings = params[:ratings].present? ? params[:ratings] : [])
#It gives this error: undefined local variable or method `selected_ratings'
session[:selected_ratings] = #selected_ratings
end
Here my view:
%h1 All Movies
= form_tag movies_path, :method => :get do
Include:
- #all_ratings.each do |rating|
= rating
= check_box_tag "ratings[#{rating}]", #all_ratings, #selected_ratings.include?(rating)
= submit_tag 'Refresh'
%table#movies
%thead
%tr
%th{:class=> helper_class('title'), :id => ('title_header')}= link_to 'Movie Title', movies_path(sort_param: 'title')
%th Rating
%th{:class=> helper_class('release_date'), :id => 'release_date_header'}= link_to 'Release Date',movies_path(sort_param: 'release_date')
%th More Info
%tbody
- #movies.each do |movie|
%tr
%td= movie.title
%td= movie.rating
%td= movie.release_date
%td= link_to "More about #{movie.title}", movie_path(movie)
And now the questions:
When I render the debug in the view, and I choose one filter (PG in this case), I get this:
--- !ruby/hash-with-ivars:ActionController::Parameters
elements:
PG: G R PG-13 PG
ivars:
:#permitted: false
I don't quite understand that. I guess ivars are instance variables, but I don't know why the hash is not shown in a proper {hash}, and only with the values selected.
How do I use session[:selected_ratings] to remember the filter for the movies? I mean, how do I use session as a parameter.
Maybe:
#movies =#movies.where(:rating => session[selected_ratings].keys)
Where can I read about how to use session, how to store, how to access and use the params stored... I have read this, and that, and also some blogposts about sessions, authentication...
But I didn't manage to understand and apply to other situations than the ones described in the blog.
Why do I get the undefined variable error if selected_ratings is defined?
#selected_ratings is defined; selected_ratings is not. What you meant to do, I think, is something like:
#selected_ratings = (params[:ratings] || session[:selected_ratings] || [])
session[:selected_ratings] = #selected_ratings
Note that this is using a symbol, rather than an undefined variable.
Let's pretend session[selected_ratings] works, how do I use it to filter the movies? Maybe: #movies =#movies.where(:rating => session[selected_ratings].keys)
Well, what does #selected_ratings equal? I suspect it's probably an array of ratings, right? - Something like: ["PG", "PG-13", "R"]. In which case, ActiveRecord is clever enough and generating SQL, that you can just do something like:
#movies.where(rating: #selected_ratings)
Most importantly, where can I read about how to use session, how to store, how to access and use the params stored... I have read this, and that, and also some blogpost about sessions, authentication... But I didn't manage to understand and apply to other situation than the described in the blog.
That's a bit vague; I don't know what to suggest beyond the Rails documentation etc. for a beginners' overview. If you have a more specific question, I'd be happy to help.
Undefined error is because you refer to variable selected_ratings which isn't defined (you defined #selected_ratings, which isn't the same thing).
To answer your second question, you can do like so:
#movies = #movies.where(:rating => session[:selected_ratings])
session hash is easy to work with. You save and retrieve values just like you would with a regular hash.

Using Acts-As-Taggable on Multiple Tags

Quick question.
I'm trying to use the Acts-As-Taggable gem to search for multiple tags at the same time. The trick is, I want to search for any posts containing at least one of the tags. I've partially figured it out.
If in my songs controller I put
if params[:tag]
#songs = Song.tagged_with(["Hip-Hop-3, Hip-Hop-5"], :any => true)
elsif...
It will find all posts containing one or more of the tags.
The problem is, when I want to move these parameters into a ERB link_to
Here is my controller:
if params[:tag]
#songs = Song.tagged_with(params[:tag], :any => true).order("created_at DESC").paginate(:page => params[:page], :per_page => 36)
elsif
Here is my link_to
<%= link_to "House", tag_path(["Hip-Hop-5","Hip-Hop-3"]) %>
In this situation the URL is the same, http://localhost:3000/tags/Hip-Hop-5/Hip-Hop-3, but it doesn't show any of the posts like the previous method did.
Am I doing something wrong with the parameter?
OR
Is there a way I can have the tagged_with method search for tags containing certain characters. So find tags that contain the word "Hip-Hop" in it? Thank you!
Thank you,
Matt
You need to modify the url as follows:
<%= link_to "House", tag_path(tag: ["Hip-Hop-5","Hip-Hop-3"]) %>
I believe that the controller won't be able to find params[:tag] as per your link because it is not passed as hash to the method tag_path, using tag: params[:tag] should ensure correct assignment of the params[:tag] to the parameters you were passing.

ruby on rails search form

I'm new to RoR and I've managed to make a basic search form but keep getting errors when trying to expand the search tags (name).. I have a model with various data (location, website, email, telephone) and was wondering how I can add these to my current search code.
/models/ciir.rb
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
static_pages_controller.rb
def home
#ciirs = Ciir.search(params[:search])
end
/home.html.erb
<%= form_tag ciirs_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag " Search Database Records ", :name => nil %>
</p>
<% end %>
When clicking the submit button (no search terms) the url is:
ciirs?utf8=✓&search=
but when modifying the name condition to something like 'website' the url changes to
ciirs?utf8=✓&search=&commit=+Search+Database+Records+ –
Since you mentioned you are new to RoR, I must share the way I learned RoR was reading, using and analyzing one issue at a time. I would suggest you to take a look at following points one at a time and try & learn how RoR treats them and how these fit your question:
How form_tag works?
How text_field_tag works?
Once you have understood form_tag, difference between text_field_tag and f.text_field?
How params objects are created, and it uses names of form controls?
How and when to use GET and/or POST form methods? Inadvertently, what are different types of method and when to use them?
How URL are used in the form_tag and what components are they made of?
Sprinkle a bit of knowledge of Ruby language by learning between Arrays and Hashes? In fact, learn Ruby as much as you can.
Answering your question,
/home.html.erb
<%= form_tag "/static_pages/home", :method => 'post' do %>
<p>
<%= text_field_tag "search[name]", params.has_key?("search") && params[:search].has_key?("name") ? params[:search][:name] : "" %>
<%= submit_tag " Search Database Records " %>
</p>
<% end %>
/models/ciir.rb
def self.search(search)
if search
find(:all, :conditions => ["name LIKE '%?%'", search[:name]])
else
find(:all)
end
end
So I modified your form, and told RoR about search params containing data for name.
params is a Hash (which is a key-value pair) having key named search, which further is a Hash having key named name.
The same principle is followed in the model code. We passed the Hash of key search to the function and in there, used the value of key named name.
I also updated the url in form_tag, to point it to home action of your controller. Assuming that you have added it to your routes.rb file, it usually follows the pattern controller_name/action_name or the function name action_name_controller_name_path or action_name_controller_name_url. Run rake routes command at your root directory to list out all paths in your application.
Also note, I used POST method instead of original GET. You may wish to use GET here, so please change it back.
I hope this works.
I found no error in your code. the url changed to ciirs?utf8=✓&search=&commit=+Search+Database+Records+ is normal. submit_tag generates a button named "commit" defaultly, it will be parsed in the params. I see you add :name => nil , it will fix the problem, the other part of your code needn't to be modified. I copied your code and tested it, it ran smoothly.

Use button_to to create habtm join?

G'day all.
In a Rails app I have 2 models: users and spots, with a habtm relationship and join table. In the spot/show action I can create a form to ask the current user if they have visited this current spot (checkbox) and click save to create a record in the join table.
This works well (so I know my models and relationships are all good) however is not that elegant. Is there a way to do this without having to use a checkbox and submit button? Preferably with just a button?
My research suggests the rails button_to might do it, but I can't find a working example.
Many thanks.
Yes, button_to will work fine:
<%= button_to "I've visited here", {:action => "visited", :id => #spot} %>
Will generate a button that when pressed will pass in the #spot in the params as expected. You can then (assuming you have a current_user method because you're using a standard user model framework), do something like this:
def visited
spot = Spot.find(params[:id])
current_user.spots << spot
redirect_to :action => "show", :id => spot
end
Hope that helps.

Display search query in results of basic search in Rails

I built a basic search form that queries one column in one table of my app. I followed episode 37 Railscast: http://railscasts.com/episodes/37-simple-search-form
Here's my problem. I want to display the search query that the user makes in the view that displays the search results. In my app, the search queries the zip code column of my profile model, and returns a list of profiles that contain the right zip code. On the top of the list of profiles returned from the search, I want it to say "Profiles located in [zip code that was queried]."
I'm sure I can do this because the queried zip code gets passed into the url displaying the results. So if the url can pick it up, there must be some way to display it in the view on the page as well. But I don't how.
Please keep in mind that I'm not using any search pluggins and I don't want to use any for now. This is my first app, so I don't want to add complexity where it's not needed.
Per Ryan's instructions in the Railscast, here's my setup:
PROFILES CONTROLLER
def index
#profiles = Profile.search(params[:search])
end
PROFILE MODEL
def self.search(search)
if search
find(:all, :conditions => ['zip LIKE ?', "%#{search}%"])
else
find(:all)
end
end
PROFILE/INDEX.HTML.ERB
<% form_tag ('/profiles', :method => :get) do %>
<%= text_field_tag :search, params[:search], :maxlength => 5 %>
<%= submit_tag "Go", :name => nil %>
<% end %>
The search itself is working perfectly, so that's not an issue. I just need to know how to display the queried zip code in the view displaying the results.
Thanks!
Just set it to an instance variable and use that.
def index
#search = params[:search]
#profiles = Profile.search(#search)
end
In your view, you can reference #search.
Also, as a friendly tip, please use an indent of 2 spaces for Rails code. It's the standard way to do it, and others who are reading your code will appreciate it.

Resources