I am thinking about question in routing... I have for example following in URL:
example.com/john
and for this URL I did this in routes
match "*a" => "people#person"
and in controller
def profile
#I have "john" in params[:a] variable
...
end
And know I am thinking, how to do following URL
example.com/john/something
How I should edit my routes and my controller for this shape of URL. I am newbie in Rails, and a bit confused yet in routing...
Thank you
match ":a(/:b)" => "people#person"
# controller
def person
a = params[:a]
b = params[:b]
end
Related
I'm trying to refactor the Companies_Controller#index method to encompass less logic by moving most of the query into a scope, company_search_params.
What is the best way to pass the param to the model scope? I'm getting an error thrown back, wrong number of arguments (given 0, expected 1). I'm relatively new to writing scopes and couldn't find much on passing arguments/conditions that was applicable in the Rails Guide.
Companies Controller
def index
params[:name_contains] ||= ''
Company.company_search_params(params[:name_contains])
#search = Company.company_search_params
#companies = #search.page(params[:page])
end
Company Model
scope :company_search_params, ->(name_contains){
where(
<<-SQL
"name LIKE :match OR subdomain LIKE :match", { match: "%#{name_contains}%" }
SQL
).where(is_archived: false).order(name: :asc)
}
Thanks for your help.
using named_scope sample and info
scope :named_scope, lambda {
|variable1, variable2|
where...
order...
}
#when you call it from your controller
Model.named_scope("value 1","value 2")
for your problem
in your company.rb
scope :company_search_params, lambda {
|name_contains|
where(
<<-SQL
"name LIKE :match OR subdomain LIKE :match", { match: "%#{name_contains}%" }
SQL
).where(is_archived: false).order(name: :asc)
}
company_controller.rb
def index
#search = Company.company_search_params(params[:name_contains])
#companies = #search.page(params[:page])
end
I have a Rails 3.2 app, where Angular code is calling a Rails route. I need to pass the route the (Rails) id of the page, and am having some difficulty. I have embedded the id onto the page using a hidden div, but cannot access it from Angular, in order to pass back into Rails.
I've reviewed this blogpost: http://spin.atomicobject.com/2013/11/22/pass-rails-data-angularjs/
Here is a similar question:
Rails route params in angular
I seem to be getting something but it is an object, not the id I need. A button is pressed which triggers the Angular call. An example url on the page would be, in which case I am trying to pass 833:
http://0.0.0.0:3000/batches/833/edit
worksheet.js.coffee
#WorksheetCtrl = ($scope) ->
.
.
$scope.exportCSV = ->
batchId = angular.element(document.querySelector("#data-batch-id"))
location.href = "/wizards/#{batchId}/worksheet_export.csv?#{Object.toQueryString($scope.getPostParams())}"
config/routes.rb
match 'wizards/:id/worksheet_export', :to => 'wizards#worksheet_export', :as => 'worksheet_export'
app/views/batches/edit.html.erb
<div ng-controller="WorksheetCtrl" ng-init="init()">
<div id="div-passed-data" data-batch-id="<%= #batch.id %>"></div>
app/controllers/wizards_controller.rb
def worksheet_export
Rails.logger.debug "id: #{params[:id]}"
Rails.logger.debug "params: #{params}"
.
.
Rails Console
Started GET "/wizards/[object%20Object]/worksheet_export.csv" for 127.0.0.1 at 2014-01-12 21:52:31 +0100
Processing by WizardsController#worksheet_export as CSV
Parameters: {"id"=>"[object Object]"}
id: [object Object]
params: {"controller"=>"wizards", "action"=>"worksheet_export", "id"=>"[object Object]", "format"=>"csv"}
SOLVED -- better solutions welcome
It seems rather convoluted, but I managed to pass in the id via the init() method and from there added it to the $scope.
app/views/batches/edit.html.erb
<div ng-controller="WorksheetCtrl" ng-init="init(<%= #batch.id %>)">
worksheet.js.coffee
$scope.init = (batch_id)->
console.log("batch: #{batch_id}")
$(document).ready ->
$('#editCriteriasModal').on 'hidden', ->
$scope.$apply ->
$scope.criteriaListValidation $scope.modalCriteriaList
$scope.search()
$scope.batchId = batch_id
.
.
$scope.exportCSV = ->
location.href = "/wizards/#{$scope.batchId}/worksheet_export.csv?#{Object.toQueryString($scope.getPostParams())}"
I have a really simple problem. I have a page of reports and each report has its own tab. I'm using current_page? to determine which tab should be highlighted. When I submit any report, current_page? doesn't seem to work anymore, apparently because the request method is POST.
Is this the intended behavior of current_page? I have a hard time imagining why that would be the case. If it is, how do people normally get around this problem?
Here's an example of a current_page? call:
<li><%= link_to "Client Retention", reports_client_retention_path, :class => current_page?(reports_client_retention_path) ? "current" : "" %></li>
All right, it looks like I figured out the answer to my own question about 5 minutes after putting up a bounty. It looks like current_page? will always return false on POST.
Here's the source code for current_page?:
# File actionpack/lib/action_view/helpers/url_helper.rb, line 588
def current_page?(options)
unless request
raise "You cannot use helpers that need to determine the current " "page unless your view context provides a Request object " "in a #request method"
end
return false unless request.get?
url_string = url_for(options)
# We ignore any extra parameters in the request_uri if the
# submitted url doesn't have any either. This lets the function
# work with things like ?order=asc
if url_string.index("?")
request_uri = request.fullpath
else
request_uri = request.path
end
if url_string =~ %r^\w+:\/\//
url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}"
else
url_string == request_uri
end
end
I don't really understand why they would have gone out of their way to make current_page? work only for GET requests, but at least now I know that that's the way it is.
You could create a new current_path? method in your ApplicationHelper:
def current_path?(*paths)
return true if paths.include?(request.path)
false
end
Pass in one or more paths and it returns true if any match the user's current path:
current_path?('/user/new')
current_path?(root_path)
current_path?(new_user_path, users_path '/foo/bar')
Or, you can create a new current_request? helper method to check the Rails controller + action:
def current_request?(*requests)
return true if requests.include?({
controller: controller.controller_name,
action: controller.action_name
})
false
end
Pass in one or more controller + action and it returns true if any match the user's current request:
current_request?(controller: 'users', action: 'new')
current_request?({controller: 'users', action: 'new'}, {controller: 'users', action: 'create'})
==UPDATE==
Ok, I decided to make using current_request? a little less verbose by not requiring that you type out the controller when you are trying to match multiple actions:
def current_request?(*requests)
requests.each do |request|
if request[:controller] == controller.controller_name
return true if request[:action].is_a?(Array) && request[:action].include?(controller.action_name)
return true if request[:action] == controller.action_name
end
end
false
end
Now you can do this:
current_request?(controller: 'users', action: ['new', 'create'])
I was having the same problem when using POST. My solution was to do something like this
def menu_item link_text, link_path
link_class = (request.original_url.end_with? link_path) ? 'active' : ''
content_tag :li, link_to(link_text, link_path), class: link_class
end
where link_path is just url_for(action: 'action', controller: 'controller')
I am trying to write api code that utilizes the JSON rendered from the controller. I was able to successfully get my desired results locally, but when I push to Heroku parts of my JSON is not rendered correctly.
To put in context, I am trying to create a nested JSON with meal information (name, id, etc) and photo urls. Locally the photo urls render correctly in the JSON. However, on Heroku the photo urls show up as null. On Heroku, I have also tested just rendering the url JSON alone and it is getting the urls correctly.
If you know why it is rendering correctly locally and not on Heroku please let me know. Thank you
I create my JSON the following way:
def api
#meals = Meal.all
#urls = Hash.new
#return_val = Array.new
#sorted_meals = Meal.select('meals.name as meal_name, meals.id as meal_id,
COALESCE(sum(meal_ratings.rating), 0) as meal_rating,
restaurants.id as restaurant_id, restaurants.name as restaurant_name').
joins('LEFT JOIN meal_ratings ON meals.id = meal_ratings.meal_id
LEFT JOIN restaurants ON restaurants.id = meals.restaurant_id').
group('meals.name, meals.id, restaurants.id, restaurants.name').
order('meal_rating DESC').all
#meals.each do |meal|
unless meal.meal_photos.empty?
#urls[meal.id] = {"thumb" => meal.meal_photos[0].photo.url(:thumb), "profile" => meal.meal_photos[0].photo.url(:profile)}
end
end
#sorted_meals.each do |meal|
#return_val.push("id" => meal.meal_id, "name" => meal.meal_name,
"rating" => meal.meal_rating, "restaurant" => meal.restaurant_name,
"restaurant_id" => meal.restaurant_id, "urls" => #urls[meal.meal_id])
end
respond_to do |format|
format.html # show.html.erb
format.json { render json: #return_val } # render json: #url render json: #meals
end
end
The problem was due to Postgres. When I query for a meal_id it returned a string and was not working as a hash key, so I was getting nil. After turning the id string into turn an int everything worked fine. Thanks to the help of Sena this has been resolved.
Hi Im trying to parse XML from a websites API with Nokogiri. Im just curious to see if Im on the right track. I have a controller wich handles the parsing and then I would like the model to initialize the necessary parameters and then display it as a simple list in the view. I was thinking something like this in the Controller:
def index
doc = Nokogiri::XML(open("http://www.mysomething.com/partner/api/1_0/somerandomkeynumber4b0/channel/11number/material/list/").read)
#news = []
doc.css("news").each do |n|
header = n.css("header").text
source_name = n.css("source_name").text
summary = n.css("summary").text
url = i.css("url").text
created_at = i.css("created_at").text
type_of_media = i.css("type_of_media").text
#news << News.new(
:header => header,)
end
and then the Model:
class News
include ActiveModel::Validations
validates_presence_of :url, :type_of_media
attr_accessor :header, :source_name, :summary, :url, :created_at, :type_of_media
def initialize(attributes = {})
#header = attributes[:header]
#source_name = attributes[:source_name]
#summary = attributes[:summary]
#url = attributes[:url]
#created_at = attributes[:created_at]
#type_of_media = attributes[:type_of_media]
end
Is this how you would do this?! Not sure Im thinking correct on this. Maybe you have any tips on a great way of incorporating Nokogiri with some other thing for the view like Google maps or something. Right now Im getting an error saying
Missing template news/index with {:formats=>[:html], :handlers=>[:builder, :rjs, :erb, :rhtml, :rxml], :locale=>[:en, :en]} in view paths
Thanks in advance!
#noodle: So this:
#news = doc.css('query').map do |n|
h = {}
%w(header source_name summary url created_at type_of_media).each do |key|
h[key.to_sym] = n.css(key).text
end
News.new(h)
end
Is equal to:
#news = []
doc.css("news").each do |n|
header = n.css("header").text
source_name = n.css("source_name").text
summary = n.css("summary").text
url = i.css("url").text
created_at = i.css("created_at").text
type_of_media = i.css("type_of_media").text
#news << News.new(
:header => header,)
end
Did I understand you correctly?! Regarding the template I have located the the problem. It was a minor misspelling. Cheers!
You're really asking two questions here..
Is my xml -> parse -> populate pipeline ok?
Yes, pretty much. As there's no conditional logic in your .each block it would be cleaner to do it like this:
#news = doc.css('query').map do |n|
#...
News.new(:blah => blah, ...)
end
.. but that's a minor point.
EDIT
You could save some typing by initializing a hash from the parsed xml and then passing that to Model.new, like:
#news = doc.css('query').map do |n|
h = {}
h[:header] = n.css('header').text
# ...
News.new(h)
end
EDIT 2
Or even shorter..
#news = doc.css('query').map do |n|
h = {}
%w(header source_name summary url created_at type_of_media).each do |key|
h[key.to_sym] = n.css(key).text
end
News.new(h)
end
In fact #inject could make that shorter still but I think that'd be a little obfuscated.
Why can't rails find my view template?
Dunno, is there one? You've not given enough details to answer that part.