I am using mechanize to deal with a form . I have parsed the form using mechanize and the output comes is as follows:
{forms
#<Mechanize::Form
{name nil}
{method "POST"}
{action "/dashboard/checks/50114dbeae6f61b428000ad8"}
{fields
[hidden:0x60c476a type: hidden name: _method value: put]
[text:0x60c4616 type: text name: check[name] value: Testing]
[text:0x60c4512 type: text name: check[url] value: http://www.pintile.com]
[text:0x60c445e type: text name: check[interval] value: 120]
[text:0x60c435a type: text name: check[maxTime] value: 1500]
[textarea:0x60c4116 type: name: check[tags] value: ]}
{radiobuttons}
{checkboxes}
{file_uploads}
{buttons
[button:0x60c3d88 type: submit name: value: ]
[button:0x60c3d24 type: submit name: delete value: ]
There are 2 buttons in this form
Save Changes(1st), Delete(2nd),
I use the following code to save the changes and it works fine:
form.field_with(:name => "check[name]").value = "Testing"
button = form.buttons.first
agent.submit(form, button)
The changes are saved successfully. But when i try to delete using the code below it does not work:
button = form.buttons.first
agent.submit(form, button)
It does nothing. Please help me out to get over with this issue.
If the website is a typical rails form, the delete button is most likely a JavaScript action. Mechanize does not support JavaScript. You may want to use something like capybara with the web kit driver instead, which has full JavaScript support and all of the functionality you already have in mechanize.
The code snippet below work well with link.Have you tried click
agent.get("http://your url")
agent.page.link_with(:text => "link name").click
Give it a try..
Else as mentioned above you can use Capybara
Delete is the last button. Therefore you want:
button = form.buttons.last
agent.submit(form, button)
or more simply:
form.submit form.buttons.last
If Mechanize is good enough for you and you do not require any javascript support that would bring Capybara, you should be able to emulate what the Javascript does. In this case, the source would be needed to better know what append, but I guess the value of the hidden field _method is replaced by delete prior the submit.
Related
I am trying to test mechanize gem. I would like to subscribe to a website using the form. I selected all the elements correctly ( I guess) but the submit button, does not submit the form. When the form is submitted a mail is instantly received. I am a new to the gem, and I am testing registering to a website with a single mandatory field. I am using the webservice for spam mail to check if it works, so every mail field could substitute with anything before #moncourrier.fr.nf and later check if a mail is received on yopmail website, but I got nothing. Do you have any idea why is not working?
require 'rubygems'
require 'mechanize'
require'pry'
agent = Mechanize.new
agent.get('http://blackburnecreek.com/newsletter-registration') do |page|
form=agent.page.forms[1]
button=form.button_with(:value => "Subscribe")
agent.page.forms[1]["EMAIL"]= "testmechanizegem#moncourrier.fr.nf"
agent.submit(form, button)
end
Your form is not getting submitted, because the actual form uses jquery which submits the form with some extra params. They are unbinding the submit event of form and are performing a ajax request to submit the form instead with an extra param id.
You can confirm so by looking at the request being initiated in network tab of your browser it contains following params:
Also the page runs following javascript which adds the extra id param to the request:
function mce_init_form(){
jQuery(document).ready( function(jQuery) {
var options = { errorClass: 'mce_inline_error', errorElement: 'div', onkeyup: function(){}, onfocusout:function(){}, onblur:function(){} };
var mce_validator = jQuery("#mc-embedded-subscribe-form").validate(options);
jQuery("#mc-embedded-subscribe-form").unbind('submit');//remove the validator so we can get into beforeSubmit on the ajaxform, which then calls the validator
options = { url: 'http://blackburnecreek.us8.list-manage.com/subscribe/post-json?u=68692d660a16c9b7e4be6f51e&id=f19ba31349&c=?', type: 'GET', dataType: 'json', contentType: "application/json; charset=utf-8",
See the url: part in above function. So when you're submitting it via mechanize you're performing an invalid request(no param id).
I guess mechanize doesn't support execution of javascript. I would recommend you to use capybara which uses web drivers like poltergiest that facilitates support for js execution.
I have created a site using LocomotiveCMS, I have created two content types called Photo and Gallery, these content types have a relationship so that I can create image galleries on my site.
I am currently looking to use the RESTful API in order to create multiple content entries for Photo as it traverses through a file.
I can connect to the API with no issue and modify the site etc.
I would assume that the cURL command for a new content entry would take the form of:
curl -X POST -d 'photo[image_id]=blah&photo[gallery]=1234&photo[file]=<filepath>photo[published]=true' 'http://<your site>/locomotive/api/current_site.json?auth_token=xxxx'
However I am unsure how to pass a file through in this command, I have substituted this for for now, how would you write this part?
My fields are set up as follows for Photo:
fields:
- image_id:
label: Image ID
type: string
required: true
localized: false
- file: # Name of the field
label: File
type: file
required: true
localized: false
- gallery: # Name of the field
label: Gallery
type: belongs_to
required: true
localized: false
# Slug of the target content type (eg post if this content type is a comment)
class_name: gallery
I ended up making a Ruby Script to parse files and upload them by sending the post data to
/locomotive/api/content_types/photos/entries.json?auth_token=XXXX
The following code can potentially help with this task:
data = {
content_entry: {
title: 'Title',
image: File.new('media/images/screen.png'),
}
}
HTTMultiParty.post(
"http://localhost:8080/locomotive/content_types/blogs/entries.json?auth_token=#{#token}",
query: data,
headers: { 'Content-Type' => 'application/json' }
)
I'm using HTTMultiParty since we actually need to do a multipart-post. Helpful information on how to do this with curl:
https://github.com/locomotivecms/documentation/pull/175
To get the token you need something like this:
HTTParty.post(
'http://localhost:8080/locomotive/api/tokens.json',
body: { api_key: 'YOUR_API_KEY_HERE' }
)
I hope that helps.
There is an api gem for LocomotiveCMS by now, works for 2.5.x and 3.x https://github.com/locomotivecms/coal
the attribute used need to end with _url for content entry fields with type=file https://github.com/locomotivecms/engine/pull/511/commits/f3a47ba5672b7a560e5edbef93cc9a4421192f0a
I am trying to build a Rails application with w2ui.
I have hit my first snag when trying to submit a form built with w2ui.
I have a simple model called Project with two attributes: name and description.
The standard, scaffolded form built by Rails submits the form data as follows:
project[name]:Test Project
project[description]:A description
However, the form data submitted by w2ui looks as follows:
record[project[name]]:Test Project
record[project[description]]:A description
That is, w2ui wraps the data further in a record variable, which means I must either change the controller in Rails, which I am not wanting to do, or find a way to get w2ui to not wrap the data the way it does.
My code for w2ui is taken pretty much straight from their demos:
$(function () {
$('#project_form').w2form({
name : 'project_form',
url : '/projects.json',
fields: [
{ name: 'project[name]', type: 'text', required: true },
{ name: 'project[description]', type: 'text' }
],
actions: {
reset: function () {
this.clear();
},
save: function () {
this.submit(); // tried .save() as well, same result
}
}
});
});
First prize would be if w2ui could be configured to do this. Any ideas? I don't see anything in the w2ui docs...
I faced the same problem and straight away could not get a solution.
I added the below to form options, it just copies all params inside record to post data.
onSubmit: function(formName, formObj){
$.extend(formObj.postData, formObj.postData.record);
},
Its been long you have asked this question, if you knew a better solution please let me know.
I'm trying to create a new event using the Koala gem and it's returning with the same error I got when I tried to update an event with an incorrectly formatted datetime value.
I can update just fine now but still cannot create an event.
Here's the code I use on my update method which works:
start_time = safe_params[:start_time].in_time_zone
end_time = safe_params[:end_time].in_time_zone
graph.put_connections(safe_params[:fb_id], "event", {
name: safe_params[:name],
description: safe_params[:description],
privacy: safe_params[:privacy]
})
And here's the code I'm trying to use to create a new event object:
graph.put_connections("/me/events", "event", { #this is the line that errors
name: safe_params[:name],
description: safe_params[:description],
privacy: safe_params[:privacy]
})
According to Facebook's documentation on creating an event (https://developers.facebook.com/docs/graph-api/reference/user/events/), I should be able to create a new event just by initiating a post to /me/events. Anyone have any idea?
I also tried:
graph.put_connections("/"+current_user.fb_id.to_s+"/events", "event", {
Thanks!
What happens if you do something like this?
graph.put_connections("me", "events", {
name: safe_params[:name],
description: safe_params[:description],
privacy: safe_params[:privacy],
start_time: ...,
end_time: ...
})
So after messing with Facebook's Graph Explorer and attempting hundreds of different combinations with put_connections I decided to make a straight graph_call using Koala.
Finally got an ID response back. I almost cried. Thought I'd share with the community in case there's someone else trying to do the same thing.
event_response = graph.graph_call("/me/events",{
name:safe_params[:name],
start_time: safe_params[:start_time],
privacy_type: safe_params[:privacy],
access_token: current_user.oauth_token}, "POST")
safe_params[:fb_id] << event_response["id"]
#event = Event.create safe_params
I make the call in a stored variable event_response because the Facebook Id returned is used in my app.
First thing I found out: despite using "privacy" as the name of the privacy field when GETting from Facebook and saying so in their documentation, "privacy_type" is actually what you want (found this out in another SO post).
The second thing I found out is even though you are authenticated (have a user token) when you make a graph_call you STILL need to pass along the current_user access token along with making a POST graph_call.
Hope this helps someone!
I am building an application using MVC & Web Api. On a View I am using JqGrid. Previously we used to assign local data to JqGrid which was working fine. Now due to some changes in logic, we are using WebApi to bring data from Server, this is a Json data, we store it in variable then we assign this data object to JqGrid but data does not get displayed.
When instead of data option i give "url" of web api then everything works fine, but as soon we use "data" option then jqgrid does not work.What could be the possible reason? Reason for doing this is that I want to add, edit, update data locally and then when final save button is pressed, data goes back to Server.
$().ready(function () {
//{"total":1,"page":1,"records":3,"rows":[{"id":"1","cell":["1","Tomato
//Soup","db#db.com","db#db.com","Groceries"]},{"id":"2","cell":["2","Yo-
//yo","db#db.com","db#db.com","Toys"]},{"id":"3","cell":
//["3","Hammer","db#db.com","db#db.com","Hardware"]}]}
//
$.getJSON("api/userwebapi/",
function (data) {
//userDataFromApi = jQuery.parseJSON(data);
userDataFromApi =data;
//alert(userDataFromApi[0].ID);
ConfigureUserGrid(userDataFromApi);
});
});
function ConfigureUserGrid(userDataFromApi) {
var grdUsers = $("#grdUsers");
var lastsel = 0;
$("#grdUsers").jqGrid({
datatype: "json"
, data: userDataFromApi
//, url: "api/userwebapi"
,colNames: ['ID', 'Name', 'User Role', 'Email', 'Address']
,colModel: [
{ name: 'ID', index: 'ID', width: 80, hidden: true }
, { name: 'Name', index: 'Name', width: 150 }
, { name: 'UserRole', index: 'UserRole', width: 150 }
, { name: 'Email', index: 'Email', width: 200, sortable: true }
, { name: 'Address', index: 'Address', width: 200, sortable: true }]
, viewrecords: true
, pager: '#pager1'
, mtype: 'GET'
,rowNum:true
,caption: 'My first grid'
}); //close of jQuery("#grdUsers").jqGrid({
$("#grdUsers").jqGrid('navGrid', '#pager1',
{ add: false, del: false, edit: false, search: false, refresh: false });
}
The reason of the problem is wrong usage of jqGrid parameters (options). To be exactly you use wrong combination of jqGrid options. Tony Tomov (the developer of jqGrid) added many features in jqGrid during every new version. He wanted to hold backwards compatibility if it's possible. As the result there are a lot of options without clear name conversion. Many options work only if some other options are set. Exactly like in case of jQuery or jQuery UI there are no validation of input parameters. It makes many problems who people who starts to use jqGrid.
The problem in your case is the usage of data parameter together with datatype: "json". It's wrong combination of parameters. The problem is that jqGrid supports two remote datatypes and some local datatypes.
If you use datatype: "json" or datatype: "xml" then jqGrid get for you AJAX request for initial filling of grid and on every sorting, paging and (optionally) filtering. In any way the request to the url will be send. One uses HTTP command specified by mtype parameter. The paging and sorting of data have to be implemented on the server side. The request contain the requested page number, the length of the page, the index of the column used for the sorting and the direction of sorting. The data returned from the server should in the format described here. If you have non-standard data format you can use jsonReader options of jqGrid and jsonmap (xmlmap) in colModel to specify how the server response should be used to fill the grid.
If you don't want to implement server side paging, sorting and filtering of data you can use loadonce: true option. In the case the server should return all data at once. The data should be sorted once based on the initial sorting column (based of sortname and sortorder which you use). jqGrid will change datatype automatically to "local" after the first loading of data.
All other datatypes will be interpreted as local datatypes. The data parameter will be used only in case of datatype: "local". One should use another format of data in the case. One can use localReader (see here) to change the way how the data should be read from data parameter.
There are special case datatype: "jsonstring" where you can fill the grid in the way close with datatype: "json", but to use an object or JSON string as the input. In the case one should use datastr (not data !!!) as the input of data. After the first filling the datatype will be changed by jqGrid from datatype: "jsonstring" to datatype: "local".
So you have some options to fix the problem:
to use url and loadonce: true options if you don't want to implement paging of data.
to use datatype: "jsonstring" and datastr instead of data.
to use datatype: "local" and data filled as array of named items (properties of items should be the same as the value of name property of the columns).