How do I send information from controller method to HTML page? - ruby-on-rails

I am developing a Rails application and want to put some info that I already read from an XML file and show it in a new page.
In my view I have:
<%= link_to 'Hoteles', :method => :hotels %>
and the controller method is:
def hotels
url = "http://api.hotelsbase.org/search.php?longitude="+#city_visit.longitude+"&latitude="+#city_visit.latitude
data = Nokogiri::HTML(open(url))
$name = data.xpath("//name")
$fulladdress = data.xpath("//fulladdress")
$phone = data.xpath("//phone")
$city = data.xpath("//city")
$description = data.xpath("//description")
$featured = data.xpath("//featured")
$stars = data.xpath("//stars")
$rating = data.xpath("//rating")
$long = data.xpath("//long")
$lat = data.xpath("//lat")
$dist = data.xpath("//dist")
$price = data.xpath("//price")
$tripadvisorurl = data.xpath("//tripadvisorurl")
$url = data.xpath("//url")
$hotelsbaseUrl = data.xpath("//hotelsbaseUrl")
end
Now I want to show that information in a HTML page.

All the global variables (starting with a $) you've defined should be instance variables (starting with an #)
#name = data.xpath("//name")
#fulladdress = data.xpath("//fulladdress")
And then you can use them in the hotels.html.erb view, like this
<%= #name %>
You should look at Rails guides to find more information and good practices about Rails; the one called "Layouts and Rendering in Rails" would have helped you for this question.

Related

How to set fake request object for rails controller object

I need to use render_to_string method outside the controller.
So I create controller instance like:
controller = class_name.constantize.new # Rails controller instance
controller.params = params
controller.action_name = 'index'
controller.create_global_current_user user
index_render_options = controller.send('index_render_options')
controller.send('render_to_string', index_render_options)
But it fails because request object inside is nil. Could you help me with it? how to create fake request for controller object?
SOLVED.
Added
controller.request = ActionDispatch::Request.new({})
resp = controller.class.make_response!(controller.request)
controller.set_response!(resp)
so now it looks like
controller = class_name.constantize.new
controller.params = params
controller.action_name = 'index'
controller.request = ActionDispatch::Request.new({})
resp = controller.class.make_response!(controller.request)
controller.set_response!(resp)
controller.create_global_current_user user
index_render_options = controller.send('index_render_options')
controller.send('render_to_string', index_render_options)
Based on this blog post the env parameter looks like
env = {
'REQUEST_METHOD' => 'GET',
'PATH_INFO' => '/hello',
'HTTP_HOST' => 'skylight.io',
# ...
}
Since Rails does not allow an empty map as the env parameter, the minimum code for creating a request object would be
request = ActionDispatch::Request.new({ "REQUEST_METHOD" => "GET" })

Adding a drop down in rails and do particular action

I am new to rails and this might me be a basic question. I checked on the internet but not able to find a simple example(might be my search is bad).
I need to create a form in my view and based the value selected and button clicking action i need to execute a particular action in my controller. I am able to create a drop down in my view using following lines.
= form_tag("/rtes", method: "get") do
= label_tag(:q, "Get Trip Type:")
= select_tag(:q, options_for_select({ "a" => "r4d_001", "b" => "r4d_002" })
<br>
= button_to( "Get Trip", :action => "rtes", :controller =>:q)
where rtes is my controller and i have mapped the value of the drop down values to the corresponding action names that needs to be executed when the button is clicked. This is my controller.
class RtesController < ApplicationController
##client=OptimusRtesServiceModel.new
def index
end
def r4d_001
result = ##client.r4t_001()
#driver_username = result.trip.loads[0].driver_details[0].driver_user_name
#driver_password = result.trip.loads[0].driver_details[0].driver_password
#trip_id = result.trip.trip_id
#carrier_username = result.carrier_details.carrier_user_name
#carrier_password = result.carrier_details.carrier_password
end
def r4d_002
result = ##client.r4t_002()
#driver_username = result.trip.loads[0].driver_details[0].driver_user_name
#driver_password = result.trip.loads[0].driver_details[0].driver_password
#trip_id = result.trip.trip_id
#carrier_username = result.carrier_details.carrier_user_name
#carrier_password = result.carrier_details.carrier_password
end
end
Now, if the first option in the drop down is selected and the button is clicked the "r4d_001" action in the controller needs to be executed. Your help is highly appreciated.
Rails is not like angular that you are trying to use :q variable to pass the value of selection to the button. You can create a drop-down menu instead of using select field to send them to different action for different option. Still if you want to use select field, then you need javascript to handle the front-end task here.
I have slightly modified my code to made it work. The idea is to get use the rails params and execute the corresponding action in my controller using case/when.
My view code:
= form_tag({:controller=>"r4d", :action=>"result"}, method: :get) do
= label_tag(:q, "Trip Type: ")
= select_tag(:q, options_for_select({"a" => "1", "b" => "2"})
= submit_tag("GetDetails")
My Contoller code:
class R4dController < ApplicationController
##client=ServiceModel.new
def r4d_result
result = case params[:q]
when "1"
##client.1
when "2"
##client.2
end
#value = result.value
end
end
By this way, i am able to pass the selected value of the drop down and execute the corresponding thing.

Ruby On Rails - Make less Database Queries

In my application I have a WebsiteAd model & website_ads table where I have all my websites ads that I can control from my admin.
Currently in a page I do 1 query for each ad to database and in my view as well to see if the ad is active.
In my controller:
# START - Desktop ads
def ads_desktop_tablet
#header_desktop_tablet = ad_placement('header_desktop-tablet')
#footer_desktop_tablet = ad_placement('footer_desktop-tablet')
#footer_desktop_tablet_c = ad_placement('footer_desktop-tablet_C')
#desktop_tablet_b1 = ad_placement('desktop-tablet_B1')
#desktop_tablet_b2 = ad_placement('desktop-tablet_B2')
#desktop_tablet_b3 = ad_placement('desktop-tablet_B3')
#desktop_tablet_s1 = ad_placement('desktop-tablet_S1')
#desktop_inline_banner = ad_placement('desktop_inline_banner')
#desktop_inline_video = ad_placement('desktop_inline_video')
#desktop_tablet_b2_c = ad_placement('desktop-tablet_B2_C')
#desktop_tablet_b3_c = ad_placement('desktop-tablet_B3_C')
#desktop_tablet_s1_c = ad_placement('desktop-tablet_S1_C')
#desktop_tablet_l1 = ad_placement('desktop-tablet_L1')
end
# END - Desktop ads
# START - Mobile ads
def ads_mobile
#header_mobile = ad_placement('header_mobile')
#footer_mobile = ad_placement('footer_mobile')
#mobile_b1 = ad_placement('mobile_B1')
#mobile_b2 = ad_placement('mobile_B2')
#mobile_b3 = ad_placement('mobile_B3')
#mobile_s1 = ad_placement('mobile_S1')
#mobile_inline_banner = ad_placement('mobile_inline_banner')
#mobile_b3_c = ad_placement('mobile_B3_C')
end
# END - Mobile ads
In my helper:
def ad_placement(placement)
WebsiteAd.where(placement: placement).first
end
# I have a method/`def` for each ad like below
def ad_desk_s1_active?
if desktop_tablet_s1.status == true
desktop_tablet_s1.ad_tag.html_safe
end
end
In my view:
= ad_desk_s1_active?
I know this is not a good practice and right way to do. How can I make this more efficient and much less code and db queries?
You can use index_by
#ads = WebsiteAd.all.index_by(&:placement)
or get only the required ads
placements = %w(header_mobile footer_mobile)
#ads = WebsiteAd.where(placement: placements).index_by(&:placement)
Which results in a hash
#header_mobile = #ads['header_mobile']
or just use #ads in the view directly
<%= #ads['header_mobile'] %>

Rails querying with an array

so in my controller i made a page which shows only the group_pages(the scaffold) in which the array #group_post_users contain the current user so:
def my_group
#group_pages = GroupPage.all
#group_pages.each do |group_page|
#group_page_users = group_page.page_users.split(',')
#group_page_users.push(group_page.user.email)
#mg_users = User.find_by_email(#group_page_users)
#gg_users = User.where(:email => #group_page_users)
group_page.super_uses = #gg_users
#g_pages = GroupPage.where(:super_uses => #selected_posts.map(&:id))
end
end
now i have an array of users for a group_page in #group_page_users and i only want to show the group pages which contain the current user inside the #group_page
basically i want something like this :
#g_pages = GroupPage.where(:super_uses => current_user.email)

Unable to submit Amazon form via Mechanize (Ruby)

In the script I wrote, I'm logging into Amazon successfully on behalf of the user with their credentials. Then I'm trying to fill out the form to enter a new address. Here's my current code:
class AmazonCrawler
def initialize
#agent = Mechanize.new do |agent|
agent.user_agent_alias = 'Mac Safari'
agent.follow_meta_refresh = true
agent.redirect_ok = true
end
end
def login
login_url = "https://www.amazon.com/gp/css/account/address/view.html?ie=UTF8&ref_=ya_add_address&viewID=newAddress"
#agent.get(login_url)
form = #agent.page.forms.first
form.email = "whatever#gmail.com"
form.radiobuttons.last.check
form.password = "my_password"
dashboard = #agent.submit(form)
end
end
class UsersController < ApplicationController
def index
response = AmazonCrawler.new.login
form = response.forms[1]
# fill out form
form.enterAddressFullName == "Your Name"
form.enterAddressAddressLine1 = "123 Main Street"
form.enterAddressAddressLine2 = "Apartment 34"
form.enterAddressCity = "San Francisco"
form.enterAddressStateOrRegion = "CA"
form.enterAddressPostalCode = "94101"
form.enterAddressPhoneNumber = "415-555-1212"
form.AddressType = "RES"
form.enterAddressIsDomestic = "0"
form.GateCode = ""
new_response = form.submit( form.button_with(value: /Save.*Continue/) )
end
end
I submit the form and it takes me to the same "Add an Address" form but there are no discernible errors, nothing new on the page. The new_response request has the same form filled out.
When I inspect the post request, here's what I get:
enterAddressFullName=test+user&enterAddressAddressLine1=123+Main+Street&enterAddressAddressLine2=123&enterAddressCity=san+francisco&enterAddressStateOrRegion=ca&enterAddressPostalCode=94101&enterAddressCountryCode=US&enterAddressPhoneNumber=4155551212&enterAddressIsDomestic=0&AddressType=RES&GateCode=&isDomestic=0&newAddress.x=55&newAddress.y=17&newAddress=Save+%26+Continue&addressID=&sessionId=204-4423391-1593712
The main thing that stands out to me is the last part of it:
&newAddress.x=55&newAddress.y=17&newAddress=Save+%26+Continue&addressID=&sessionId=176-3067966-1293712
I'm not setting newAddress.x or newAddress.y anywhere, I seem to be unable to.
Any ideas as to why this isn't submitting successfully? Is it an SSL issue perhaps?
newAddress is the name of the button. The .x and .y indicate where exactly on the button was clicked. There's a lot of reasons why a form will return you back, most likely it didn't like one of your values.
Figured it out. I was setting the name with the == rather than = which was causing the field to be empty

Resources