简体   繁体   中英

Passing parameters in URL in Rails

I am starting to learn Rails and I am facing an issue which I suppose is very simple but I have not been able to find an answer.

I have a catalog of movies and the index page displays it showing several columns and I need to make two of them a link. This link will re-display the index page again but sorted by the selected criteria.

So far I have only added one link as follows:

%th= link_to 'Movie Title', root_path

But I am not able to send a URL parameter so I can get it in the controller and perform the sort. The actual controller is as follows:

def index
  @movies = Movie.all
end

I guess that, if I can get a parameter in the controller then using an "if" statement would do the job. I imagine an URL like this, where "1" means to sort by the first criteria:

http://www.mysite/1

I saw a solution like this but I guess it is not a good choice. Please advice.

<%= link_to "Link Title", something__path(:param1 => "value1", :param2 => "value2") %>

I will very much appreciate any suggestions on how to modify the view and the controller. I have googled several solutions but I am having a hard time understanding the solutions. Maybe there is a better approach to achieve this. If so, then I am ready to listen.

Respectfully,
Jorge Maldonado

Main question

This comes down to RESTful path design. It really depends on the kind of field that you're trying to pass to the controller and represent in the URL.

It's important to think of paths as access routes to resources .

Generally speaking, there are two ways to represent the data that you want:

  • As path variables : The form of these is /path/to/resource/:resourceId . Use this format to represent properties of the resource itself.
    • eg The ID of a post on a blog is a property of the blog resource.
  • As query parameters : The form of these is /path/to/resource?queryKey=queryVal . Use this format for metadata and operations on data.
    • eg The way that you sort blog posts is not a property of the blog posts themselves, it's just an operation you're performing on them.

Mechanics

Your initial guess is actually pretty close. What you'll want is something like this instead:

In your controller:

movie = Movie.find(params[:id])

In your view:

<%= link_to 'View Movie', movie %>

Under the hood, Rails is performing some magic that turns this into something that looks fairly similar to your code in the question. It's best to let Rails perform this magic itself though, as it makes changing things later easier.

Also, just to be clear, using path variables (instead of query params) is the best approach for your situation. You can read more on routing in the docs here: http://guides.rubyonrails.org/routing.html

Follow-up question

Answering this (I don't have enough rep to comment yet):

I appreciate your response. It works fine. I still have one question. What does it mean a link like this? What is the last parameter ( :id ) used for? link_to "Movie Title", movies_path(:sort => "title"), :id => "title_header"

On link_to tags, :id adds an id field to the generated HTML tag.

This: link_to "Articles", articles_path, id: "news", class: "article"

Generates: <a href="/articles" class="article" id="news">Articles</a>

See the Rails docs here: http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to
(Search for "Classes and ids for CSS are easy to produce:")

What you can do is add the params as you mentioned above. Than in your controller you can do

def index 
if params[:param_1] == "param_one"
@movies = Movie.where(id: 'param_one')
else
@movies = Movie.all
end
end

etc. Your solution could like like this =link_to 'xxx', movies_path(:param_one=> "p1", :param_two=>"p2") Will call the index action of movies_controller.rb.

I'd send them in the query string.

For example, taking an URL with a query string such as: www.exmaple.com/resource_name/?sortBy=name

The params hash contains: "{"filterBy"=>"name", "controller"=>"resource_name", "action"=>"index", "sortBy"=>"name"}"

It's now easy to know by what to sort.

Make sure you don't directly inject that value in an SQL query to avoid SQL injections. Maybe use a switch statement for example.

If you don't like the query string approach (there is no reasons, really, but that's up to you), that a look at what the Rails routing mechanism has to offer.

References:

http://guides.rubyonrails.org/routing.html#the-query-string http://guides.rubyonrails.org/routing.html#non-resourceful-routes

The link implementation is good, I don't see anything bad about it

<%= link_to "Link Title", some_url_helper_path(:param1 => "value1", :param2 => "value2") %>

From the controller's perspective, here are some options on how to filter the data:

https://makandracards.com/makandra/65468-rails-how-to-get-url-params-without-routing-parameters-or-vice-versa

# On /users?query=Bob&page=2

>> request.params
=> {"page"=>"2", "query"=>"Bob", "controller"=>"users", "action"=>"index"}

>> request.query_parameters
=> {"page"=>"2", "query"=>"Bob"}

>> request.path_parameters
=> {:controller=>"users", :action=>"index"}

Then you can filter and sanitize the parameters and pass them to the .where() method.

https://github.com/chrisfrank/rack-reducer

GET /artists #=> all artists
GET /artists?name=blake #=> artists named 'blake'
GET /artists?genre=electronic&name=blake #=> electronic artists named 'blake'

Controller:

# app/controllers/artists_controller.rb
class ArtistsController < ApplicationController

  # Step 1: Instantiate a reducer
  ArtistReducer = Rack::Reducer.new(
    Artist.all,
    ->(name:) { where('lower(name) like ?', "%#{name.downcase}%") },
    ->(genre:) { where(genre: genre) },
  )

  # Step 2: Apply the reducer to incoming requests
  def index
    @artists = ArtistReducer.apply(params)
    render json: @artists
  end
end

https://github.com/plataformatec/has_scope - you can read more about it here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM