Forum: Ruby on Rails Submit form through GET requets

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
408016ab4c062f421c418946185aa232?d=identicon&s=25 Cisco Ri (ciscor)
on 2009-04-26 08:54
I'm trying to create a form that a user can submit data into through the
URL, using a get request.  That is, they would go to something like
http://localhost:3000/links/new?url=http://www.google.com and
http://www.google.com would be submitted.

Right now my controller looks like:

<% form_for @link, :method => :get do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :url %><br />
    <%= f.text_field :url %>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

Currently, going to that address doesn't do anything in the browser and
this gets output in the terminal: "Processing LinksController#new (for
127.0.0.1 at 2009-04-25 11:36:26) [GET]
  Parameters: {"url"=>"http://www.google.com"}"

Putting "http://www.google.com" in the actual textfield and hitting the
submit button gets this output: "  Parameters: {"commit"=>"Create",
"authenticity_token"=>"nii2AAhoBYGSYW3ggw1Ul8ENZJLMRR6mJg2AfBWdloQ=",
"link"=>{"url"=>"http://www.google.com"}}".

Can anyone let me know what I'm doing wrong?  Thanks in advance.
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-04-26 11:58
Cisco Ri wrote:
>
> Right now my controller looks like:
>
> <% form_for @link, :method => :get do |f| %>

1) Controller?  Isn't that a View?

2) Looking at an example in my book for form_for shows that the first
argument for form_for is a Symbol, e.g. :link.

3) You didn't specify the action(a method in the controller) that you
want the form data to get sent to, for instance:

<% form_for :link,
            :url => {:action => :new}  ....... %>

Since a rails url is of the form:

host/controller/action

and your url is:

http://localhost:3000/links/new?url=http://www.google.com

you are trying to call an action(or method) named new that is defined in
the links controller.  That is why I specified :new for the action.


4)  My book shows specifying the :method a different way:

<% form_for :link,
            :url => {:action => new},
            :html => {:method => :get}  ....... %>


5) Did you define a method called new in the controller whose view this
is?

I don't know if some of those changes are because I'm using rails 2.3.2
and you are using a 1.x version or not.  I would guess that it's
mandatory to state what version of rails you are using when you post a
rails question.
408016ab4c062f421c418946185aa232?d=identicon&s=25 Cisco Ri (ciscor)
on 2009-04-26 12:19
Rails 2.3.2.  Yeah, I meant that is the view.  The relevant actions in
the controller are:

  # GET /links/new
  # GET /links/new.xml
  def new
    @link = Link.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @link }
    end
  end

  # POST /links
  # POST /links.xml
  def create
    @link = Link.new(params[:link])
    @link = current_user.links.build(params[:link])
    @link.title = WWW::Mechanize.new.get(@link.url).title
    respond_to do |format|
      if @link.save
        flash[:notice] = 'Link was successfully created.'
        format.html { redirect_to(@link) }
        format.xml  { render :xml => @link, :status => :created,
:location => @link }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @link.errors, :status =>
:unprocessable_entity }
      end
    end
  end
408016ab4c062f421c418946185aa232?d=identicon&s=25 Cisco Ri (ciscor)
on 2009-04-26 12:23
When I use <% form_for :link,
            :url => {:action => :new},
            :html => {:method => :get} do |f| %>

the type http://www.gmail.com into the form and hit submit, the address
bar changes to
http://localhost:3000/links/new?link[notspamurl]=h...
 (remove notspam) and nothing gets added to the database.
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-04-26 15:55
Cisco Ri wrote:
> When I use <% form_for :link,
>             :url => {:action => :new},
>             :html => {:method => :get} do |f| %>
>
> the type http://www.gmail.com into the form and hit submit, the address
> bar changes to
> 
http://localhost:3000/links/new?link[notspamurl]=h...
>  (remove notspam) and nothing gets added to the database.

Sorry, I just started with rails, and modifying the scaffold generated
files like you did seems to interfere with the complex web of
relationships.  Also, any attempt I made to call one of the methods in
the LinksController directly, e.g.

http://localhost:3000/links/create

gave me a routing error.  That is probably for security reasons.

Because you don't care about the form page, why not bypass it
altogether?  The form page is for gathering the data from the user and
assembling it into a url and then calling the url.  Your user is going
to assemble the url themselves and call the url by themselves--by
entering the url in their browser's address bar.  So you can tell the
user to assemble a url that calls one of your own methods(=an action),
which then enters the link in the links table.

Here's something that worked for me:

1) Create a new controller and action that the user will enter as the
url:

$ ruby script/generate controller direct entry

That creates a controller called DirectController with one action(=a
method) called entry.  Open up app/controllers/direct_controller.rb and
you will see this:

class DirectController < ApplicationController
  def entry
  end

end


The name/value pairs in the url after the ? will be inserted into a
"params" hash, which you can access.  With the information in params,
you can create a new Link object like this:

Link.create("url" => params[:url])

(that assumes the links table has only one field: url)

Apparently when you assign a Link object to the variable @link, rails
will create a record in the database corresponding to the values in the
Link object.  If you look at the create method in the file
LinksController.rb, that is what the create method does.  This is what I
came up with:

@link = Link.create("url" => params[:url])

Add that line to the entry method:

class DirectController < ApplicationController
  def entry
    @link = Link.create("url" => params[:url])
  end
end

Then when you enter the url:

http://localhost:3000/direct/entry?url=www.someurl.com

that will access the DirectController and call its entry method.  The
entry method then creates a new Link object.  Then rails enters a record
in the links table corresponding to the information in the Link object.

I have no idea whether that is the proper way to do things, and I can
see at least one issue: a GET request should not make any changes on the
host.
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-04-26 16:24
7stud -- wrote:
>
> Link.create("url" => params[:url])
>
> (that assumes the links table has only one field: url)
>
> Apparently when you assign a Link object to the variable @link, rails
> will create a record in the database corresponding to the values in the
> Link object.  If you look at the create method in the file
> LinksController.rb, that is what the create method does.  This is what I
> came up with:
>
> @link = Link.create("url" => params[:url])
>

After some more testing, I discovered that you don't have to assign the
Link object to @link.  I think that when you create a Model object(e.g.
a Link object) and the Model is hooked up to a database, then as soon as
you create the object, rails inserts a record corresponding to that
object in the table.
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-04-27 01:10
7stud -- wrote:
> 7stud -- wrote:
>>
>> Link.create("url" => params[:url])
>>
>> (that assumes the links table has only one field: url)
>>
>> Apparently when you assign a Link object to the variable @link, rails
>> will create a record in the database corresponding to the values in the
>> Link object.  If you look at the create method in the file
>> LinksController.rb, that is what the create method does.  This is what I
>> came up with:
>>
>> @link = Link.create("url" => params[:url])
>>
>
> After some more testing, I discovered that you don't have to assign the
> Link object to @link.  I think that when you create a Model object(e.g.
> a Link object) and the Model is hooked up to a database, then as soon as
> you create the object, rails inserts a record corresponding to that
> object in the table.

That isn't quite right either.  You have to save an object for rails to
enter it into a table:

mylink = Link.new
mylink.url = "www.somepage.com"
mylink.save

However, rails provides a convenience method, create(), that both
instantiates a new object and inserts a record into the table.  create()
takes a hash of name/value pairs as an argument, where each name is a
field in the table.

(Or, you can pass create() an array of hashes, where each hash
represents one record, and create() will insert multiple records at the
same time.)
408016ab4c062f421c418946185aa232?d=identicon&s=25 Cisco Ri (ciscor)
on 2009-04-27 15:30
7stud -- wrote:
> 7stud -- wrote:
>> 7stud -- wrote:
>>>
>>> Link.create("url" => params[:url])
>>>
>>> (that assumes the links table has only one field: url)
>>>
>>> Apparently when you assign a Link object to the variable @link, rails
>>> will create a record in the database corresponding to the values in the
>>> Link object.  If you look at the create method in the file
>>> LinksController.rb, that is what the create method does.  This is what I
>>> came up with:
>>>
>>> @link = Link.create("url" => params[:url])
>>>
>>
>> After some more testing, I discovered that you don't have to assign the
>> Link object to @link.  I think that when you create a Model object(e.g.
>> a Link object) and the Model is hooked up to a database, then as soon as
>> you create the object, rails inserts a record corresponding to that
>> object in the table.
>
> That isn't quite right either.  You have to save an object for rails to
> enter it into a table:
>
> mylink = Link.new
> mylink.url = "www.somepage.com"
> mylink.save
>
> However, rails provides a convenience method, create(), that both
> instantiates a new object and inserts a record into the table.  create()
> takes a hash of name/value pairs as an argument, where each name is a
> field in the table.
>
> (Or, you can pass create() an array of hashes, where each hash
> represents one record, and create() will insert multiple records at the
> same time.)

I'm not sure that I follow you.  Completely bypassing the form would be
nice.

I changed the new method to:
  def new
    @link = Link.create("url" => params[:url])

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @link }
    end
  end

and it didn't get written to the database.  When I changed it to:

  def new
    @link = Link.new("url" => params[:url])

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @link }
    end
  end

it goes to the form page with the correct URL in the textfield.  This
was actually what I originally wanted, but it would be better to bypass
the form entirely.

Thanks for the help so far.
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-04-27 21:20
Cisco Ri wrote:
>>
>> Completely bypassing the form would be
>> nice.
>>

Did you try this:


> Here's something that worked for me:
>
> 1) Create a new controller and action that the user will enter as the
> url:
>
> $ ruby script/generate controller direct entry
>
> That creates a controller called DirectController with one action(=a
> method) called entry.  Open up app/controllers/direct_controller.rb and
> you will see this:
>
> class DirectController < ApplicationController
>   def entry
>   end
>
> end
>
>
> The name/value pairs in the url after the ? will be inserted into a
> "params" hash, which you can access.  With the information in params,
> you can create a new Link object like this:
>
> Link.create("url" => params[:url])
>
> (that assumes the links table has only one field: url)
>
> Apparently when you assign a Link object to the variable @link, rails
> will create a record in the database corresponding to the values in the
> Link object.  If you look at the create method in the file
> LinksController.rb, that is what the create method does.  This is what I
> came up with:
>
> @link = Link.create("url" => params[:url])
>
> Add that line to the entry method:
>
> class DirectController < ApplicationController
>   def entry
>     @link = Link.create("url" => params[:url])
>   end
> end
>
> Then when you enter the url:
>
> http://localhost:3000/direct/entry?url=www.someurl.com
>
> that will access the DirectController and call its entry method.  The
> entry method then creates a new Link object.  Then rails enters a record
> in the links table corresponding to the information in the Link object.

--------

>>I'm not sure that I follow you.

If you create a Link object, then call .save on it, the information in
the Link object will be automatically inserted in the links table.
There are two ways to create and save a Link object:

1)
    mylink = Link.new
    mylink.url = "some url"
    mylink.save

You create the Link object, then you set the field names--as found in
the links table--e.g. 'url', to the desired values.

2)  Link.create(info)

where info is a hash containing the information, e.g.:

{"field1" => val1, "field2" => val2}

In your case, I'm assuming your links table has one field named url, so
you could create a new record in the table by writing:

Link.create("info" => "some url")

An action is called with a url.  The part after the ? in the url gets
entered into the rail's params hash, which you can access inside the
action.  For instance, if you enter the following url in your browser's
address bar:

http://localhost:3000/direct/entry?url=www.someurl.com

that will call the entry method in the DirectController.  Inside the
entry method, params[:url] will be equal to "www.someurl.com".  How
would you enter that url in the table?  You can that url in the links
table by writing the following inside the entry method:

Link.create("info" => params[:url])

or equivalently:

mylink = Link.new
mylink.url = params[:url]
mylink.save
408016ab4c062f421c418946185aa232?d=identicon&s=25 Cisco Ri (ciscor)
on 2009-04-28 00:50
I'm going ahead with:

@link = @user.links.create!("url" => params[:url])

I also changed my routes.rb file to include these lines:
  # map.resources :links
  map.resources :users, :has_many => :links

It works, but I'm still having some trouble.  With these lines

    @link = @user.links.create!("url" => params[:url])
    @link.title = title=(Hpricot(open(@link.url))/"title").inner_text

the action just repeats the URL as the title.  Also, is there a way that
I can reuse the code from my create action:

  def create
    @user = current_user
    @link = @user.links.create!(params[:link])
    @link.title = title=(Hpricot(open(@link.url))/"title").inner_text
....
408016ab4c062f421c418946185aa232?d=identicon&s=25 Cisco Ri (ciscor)
on 2009-04-28 01:10
Cisco Ri wrote:
> I'm going ahead with:
>
> @link = @user.links.create!("url" => params[:url])
>
> I also changed my routes.rb file to include these lines:
>   # map.resources :links
>   map.resources :users, :has_many => :links
>
> It works, but I'm still having some trouble.  With these lines
>
>     @link = @user.links.create!("url" => params[:url])
>     @link.title = title=(Hpricot(open(@link.url))/"title").inner_text
>
> the action just repeats the URL as the title.  Also, is there a way that
> I can reuse the code from my create action:
>
>   def create
>     @user = current_user
>     @link = @user.links.create!(params[:link])
>     @link.title = title=(Hpricot(open(@link.url))/"title").inner_text
> ....

Whoops, it actually doesn't repeat the URL as the title -- it works
correctly.  But is there a way that I can reuse the code from the create
action?
This topic is locked and can not be replied to.