Camping is splitting URLs at question marks - ruby

Here's my problem:
Camping is splitting urls at question marks.
So if we have some code like this:
Camping.goes :CodeLine
module CodeLine::Controllers
class Index
def get
render :index
end
end
class TextEntered < R '/(.*)'
def get(textStringEntered)
"#{textStringEntered}"
end
end
end
module CodeLine::Views
def index
html do
head do
title "Uh Oh"
end
body do
text "Looks like you got to the index"
br
br
form :name => "input" do
input :type => "text", :name => "text"
input :type => "submit", :value => "Submit"
end
end
end
end
end
Run camping path/to/file
After going to localhost:3301 in your browser and entering some text in the text field and hitting submit, you should see everything after the slash, but instead it splits the url at the question mark and because it thinks there is nothing after the slash, it takes you to the index.
Question:
Is it possible to set up input so it does not use a question mark, or can I make camping not split at the question mark?
Appendix A
Tested in
1. Google Chrome
2. Firefox
3. Safari

The route only matches the path of the URL:
https://example.com/hello/world?a=this&b=hello&c=world#nice
^ ^ ^ ^ ^
Schema Host Path Query parameters Fragment
In Camping you get access to the query parameters through #input:
#input.a # => "this"
#input.b # => "hello"
#input.c # => "world"
Query parameters are more like "options" that you can pass to the controller. For example, you don't want to have a separate controller to handle "sorting by name" and "sorting by date", so instead you use query parameters:
class Search
def get
query = #input.q || "*"
page = (#input.page || 1).to_i
sort = #input.sort || "name"
#results = fetch_results_from_database_or_something(query, page, sort)
render :search
end
end
That way, all of these works:
/search?query=hello # Page 1, sort by name
/search?page=5 # Page 5, sort by name, search for everything
/search?query=cars&page=4&sort=date

Related

Ruby Conditional argument to method

I have some 'generic' methods that extract data based on css selectors that usually are the same in many websites. However I have another method that accept as argument the css selector for a given website.
I need to call the get_title method if title_selector argument is nos passed. How can I do that?
Scrape that accept css selectors as arguments
def scrape(urls, item_selector, title_selector, price_selector, image_selector)
collection = []
urls.each do |url|
doc = Nokogiri::HTML(open(url).read) # Opens URL
#items = doc.css(item_selector)[0..1].map {|item| item['href']} # Sets items
#items.each do |item| # Donwload each link and parse
page = Nokogiri::HTML(open(item).read)
collection << {
:title => page.css(title_selector).text, # I guess I need conditional here
:price => page.css(price_selector).text
}
end
#collection = collection
end
end
Generic title extractor
def get_title(doc)
if doc.at_css("meta[property='og:title']")
title = doc.css("meta[property='og:title']")
else doc.css('title')
title = doc.at_css('title').text
end
end
Use an or operator inside your page.css call. It will call get_title if title_selector is falsey (nil).
:title => page.css(title_selector || get_title(doc)).text,
I'm not sure what doc should actually be in this context, though.
EDIT
Given your comment below, I think you can just refactor get_title to handle all of the logic. Allow get_title to take an optional title_selector parameter and add this line to the top of your method:
return doc.css(title_selector).text if title_selector
Then, my original line becomes:
:title => get_title(page, title_selector)

ruby on rails, search results to json array (jbuilder)

I'm new to rails and I just have a quick question...
I have a calendar gem which currently pulls event data from json as such (viewings/index.json.jbuilder)
json.array!(#viewings) do |viewing|
json.extract! viewing, :id, :room_id, :user_id, :start_time, :end_time, :notes
json.title viewing.user.name
json.start viewing.start_time
json.end viewing.end_time
json.url viewing_url(viewing, format: :html)
end
anyway, I have created a search feature on my "viewings" index page, where a user selects the room from a drop-down and it displays the corresponding viewings.
However, I need to make a JSON array from the results of the search, so it can be fed to the calendar.
I know I can achieve this by doing something like, which does work:
#viewings = Viewing.where(room_id: 1 )
but obviously I want to pass a variable in to that line of code, something like
#viewings = Viewing.where(room_id: params[:search_string] )
The search string will always be a room ID, but the above code (and any variations I can think of) don't seem to work.
OR can I make a JSON array from my search output. my search is as so...
def search
#rooms = Room.all
#viewings = Viewing.simple_search(params[:search_string])
render :action => "index"
end
Can anyone help?!
EDIT:
I'm still struggling with this one a lot. I had a look at the jquery page below but its still not doing what I hoped.
I have simplified the function in my viewings controller as so:
def rmselect
#query1 = params[:rmno]
#rooms = Room.all
#viewings=Room.find(params[:rmno]).viewings
render :action => "index"
end
And I have created an _rmselect.json.jbuilder as so:
#viewings = Viewing.where(room_id: #query1 )
json.array!(#viewings) do |viewing|
json.title viewing.user.name
json.start viewing.start_time
json.end viewing.end_time
end
I was hoping the #query1 variable would be passed into the jbuilder page which would cause it only to display viewings for the selected room. However, it seems that jbuilder cannot see any variables unless they are in def index (where it's no good).
I also can't understand why _rmselect.json.jbuilder is taking the #viewings.all from def index, rather then the #viewings=Room.find(params[:rmno]).viewings from def rmselect.
Ok, I suppose the situation is like that:
Viewing model:
class Viewing < ActiveRecord::Base
...
belongs_to :room
...
end
Room model:
class Room < ActiveRecord::Base
...
has_many :viewings
...
end
Retrive viewings from room id, you can do something like:
#viewings=Room.find(params[:search_string]).viewings
For create JSON array of result, render jbuilder view who contains something like that:
# #people = People.all
json.array! #people, :id, :name
# => [ { "id": 1, "name": "David" }, { "id": 2, "name": "Jamie" } ]
I report an example of official jbuilder docs I think you can use json.array with viewings:
json.array! #viewings, field1, field2, ...
Otherwise you can use this in your controller:
render json: #viewings
but if you've used jbuilder, I think it's better you continue that way.

Datamapper into String

I want to be able to see the string like the TwitchTV name I have in my database. Here is my current code
get '/watch/:id' do |id|
erb :mystream
#result = Twitchtvst.all( :fields => [:Twitchtv ],
:conditions => { :user_id => "#{id}" }
)
puts #result
end
result in terminal;
#< Twitchtvst:0x007fb48b4d5a98 >
How do I get that into a string (TwitchTV answer in database)
Opppppsss!
Here is the real code sample. Sorry!
get '/livestream' do
erb :livestream
#users_streams = Twitchtvst.all
puts #users_streams
end
If I add .to_s at users_stream it does not work
By adding .to_csv, not exactly a string, but it should show the content:
get '/livestream' do
erb :livestream
#users_streams = Twitchtvst.all
#users_streams.each do |us|
p us.to_csv
end
end
You're getting a Collection of Twitchtvst objects, so you need to convert each to a String:
puts Twitchtvst.all.map(&:to_s).join

Does a Markdown parser exist that can also generate Markdown in Ruby?

I want to parse a Markdown document so I get a tree structure that I am able to manipulate. Afterwards I want the output to be Markdown again.
Example:
# This is a title
And a short paragraph...
m = SomeLib.parse("# This is a tit...")
m.insert(1, "Here is a new paragraph") # or something simmilar
m.to_md
Should become
# This is a title
Here is a new paragraph
And a short paragraph...
As I want to heavily change the document I do not want to use REGEX or simillar techniques.
I looked into Maruku and BlueCloth but somehow I cannot generate Markdown again.
Probably not out of the box, but using redcarpet you could write a custom renderer to build your tree and then manipulate it.
Though beware in this case you can't reuse the Markdown and Renderer instance and all methods in the custom Renderer subclass are supposed to return a string. Something like this could be a starting point:
class StackRenderer < Redcarpet::Render::Base
attr_reader :items
def initialize
super
#items = []
end
def header(title, level)
items << { :text => title, :level => level, :type => :header }
"#{'#' * level} #{title}\n\n"
end
def paragraph(text)
items << { :text => text, :type => :paragraph }
"#{text}\n\n"
end
end
# example...
sr = StackRenderer.new
md = Redcarpet::Markdown.new(sr)
text = <<-EOF
# This is a title
And a short paragraph...
EOF
md.render(text) # => "# This is a title\n\nAnd a short paragraph...\n\n"
sr.items # => [{:type=>:header, :level=>1, :text=>"This is a title"},
# {:type=>:paragraph, :text=>"And a short paragraph..."}]

Skip HTML escape in custom label_tag helper in Rail 3

I have this nice class ErrorFormBuilder that allows me to add the error description near the corresponding field in the form view :
class ErrorFormBuilder < ActionView::Helpers::FormBuilder
#Adds error message directly inline to a form label
#Accepts all the options normall passed to form.label as well as:
# :hide_errors - true if you don't want errors displayed on this label
# :additional_text - Will add additional text after the error message or after the label if no errors
def label(method, text = nil, options = {})
#Check to see if text for this label has been supplied and humanize the field name if not.
text = text || method.to_s.humanize
#Get a reference to the model object
object = #template.instance_variable_get("##{#object_name}")
#Make sure we have an object and we're not told to hide errors for this label
unless object.nil? || options[:hide_errors]
#Check if there are any errors for this field in the model
errors = object.errors.on(method.to_sym)
if errors
#Generate the label using the text as well as the error message wrapped in a span with error class
text += " <br/><span class=\"error\">#{errors.is_a?(Array) ? errors.first : errors}</span>"
end
end
#Add any additional text that might be needed on the label
text += " #{options[:additional_text]}" if options[:additional_text]
#Finally hand off to super to deal with the display of the label
super(method, text, options)
end
end
But the HTML :
text += " <br/><span class=\"error\">#{errors.is_a?(Array) ? errors.first : errors}</span>"
is escaped by default in the view...
I tried to add the {:escape => false} option :
super(method, text, options.merge({:escape => false}))
without success
Is there any way to bypass this behavior ?
Thanks
Have you tried making your string html_safe?
irb(main):010:0> a = "A string"
=> "A string"
irb(main):011:0> a.html_safe?
=> false
irb(main):012:0> b = a.html_safe
=> "A string"
irb(main):013:0> b.html_safe?
=> true
See http://www.railsdispatch.com/posts/security and scroll down to "What you need to know" near the bottom:
In general, you can build your Rails app exactly as before. Rails will automatically escape any Strings that it doesn’t create. In almost all cases, this is the right behavior, with no further modifications required.
If Rails is escaping a String that you want to pass through without escaping, simply mark it safe. If you create a String in a helper, you may want to mark parts of it as safe.
I can't test whether this will work in your sub-classed helper, but I'd think so.
Just use <%= raw your_variable_here %>

Resources