Created objects do not save in database - ruby

What did I do:
create a new ruby app rails new campaigns_manager
move to campaigns_manager directory, generate first scaffold campaigns
rails generate scaffold campaign name:string and migrate
add root route root to: 'campaigns#index', as: 'campaigns'
Such a few strings of code. Then I start server to test it. Everything looks and works ok, but when I try to add a new campaign, nothing saves. After pressing "Create campaign" button I receive in console something like that:
Started POST "/" for 127.0.0.1 at 2012-04-25 22:30:40 +0300
Processing by CampaignsController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"sKom3YBDEbOcqbSt3gLGWPqBNeqkEw6M59hlwrmH4tM=", "campaign"=>{"name"=>"test"}, "commit"=>"Create Campaign"}
Campaign Load (0.3ms) SELECT "campaigns".* FROM "campaigns"
Rendered campaigns/index.html.erb within layouts/application (0.9ms)
Completed 200 OK in 37ms (Views: 35.4ms | ActiveRecord: 0.3ms)
then I redirect to campaigns list and there is no new campaign. Table campaigns in db\development.sqlite3 is empty.
Furthermore, I add print methods to campaigns controller to check if I call correct methods. And I see, that create method is not called when I press "Create campaign" button.
My campaigns/new view:
<h1>New campaign</h1>
<%= form_for(#campaign) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Back', campaigns_path %>
Why cannot I save my campaigns to database?

The problem is in the routes.rb file.
root to: 'campaigns#index', as: 'campaigns'
The alias as: 'campaigns' tries to consume all requests. There is no need to add an alias to your root directive, it already has one by default: as: 'root'
Your routes.rb file has to look something like this:
resources :campaigns
root to: 'campaigns#index'
More on Routes in Rails Guides

It would help to see the view code in campaigns/new, but clearly the form there is posting to /, which you can see from the log, is being handled by the index action (which is as it should be according to your routes). You have to make sure your form in campaigns/new is posting to /campaigns (which in Rails RESTful routing resolves to the create action). If you're using form_for (which I think is what the scaffold generates), it should look something like this:
<%= form_for #campaign do |f| %>

Related

redirect to another URL using submit button in ruby

I have submit button and i want to redirect in another URL (hard coded) this URL
https://www.ccavenue.com/shopzone/cc_details.jsp
my code :
<%= form_tag #ccavanue do |f| , url => "https://www.ccavenue.com/shopzone/cc_details.jsp", :html => :method => "put" %>
<%= hidden_field_tag :my_field, #MerchantId, :id => 'merchant_id' %>
<%= submit_tag "Click Me" %>
<% end %>
i want to redirect another website URL with this submit button . please guided me.
Change your code to following:
<%= form_for #ccavanue, url: "https://www.ccavenue.com/shopzone/cc_details.jsp" do |f| %>
<%= f.hidden_field :my_field, #MerchantId, :id => 'merchant_id' %>
<%= f.submit "Click Me" %>
<% end %>
In Rails a form is designed to create or update a resource and reflects the identity of the resource in several ways:
The url that the form is sent to (the form element's action attribute) should result in a request being routed to the appropriate controller action (with the appropriate :id parameter in the case of an existing resource),
Input fields should be named in such a way that in the controller their values appear in the appropriate places within the params hash, and
For an existing record, when the form is initially displayed, input fields corresponding to attributes of the resource should show the current values of those attributes.
In Rails this is achieved by creating form using form_for where:
If we want to create any object we use POST method within url and PUT method if we are trying to update an existing record.
Rails framework is smart enough to use POST or PUT method by itself looking at the url of the form. So in this case we need not use method parameter within form_for url.
Probably you can start with Michael Hartl's tutorial

Rails 4 - Controller Edit Action Returning Wrong Record

I have a Comment model which belongs to both User and Story. Creating a comment correctly associated to the appropriate User and Story is working fine but when trying to edit the comment my edit action appears to retrieving the wrong record.
The offending action in comments_controller.rb:
def edit
#story = Story.find_by(params[:story_id])
#comment = #story.comments.find_by(params[:id])
end
The link used to render the comments/edit view:
<%= link_to 'edit', edit_story_comment_path(comment.story_id, comment.id) %>
The corresponding view:
<%= form_for(#comment, url: { controller: 'comments', action: 'update' }) do |f| %>
<%= f.text_area :content %>
<%= f.submit "update" %>
<% end %>
The edit view appears to be rendering the most recently added comment regardless of which #comment I am trying to edit.
You're using find_by, which is basically a magic find_by_X method, with no fields specified. find_by(1) generates invalid SQL for me using Postgres, but it might be that whatever database back-end your using accepts it.
Regardless, find_by certainly won't do what you want it to do.
You should be using find, if you want to find records by id:
#story = Story.find(params[:story_id])

2 instance variables of the same name in different controllers

I finished Michael Hartl's Ruby on Rails Tutorial. Now I'm working on the suggested exercises. The application he builds is basically a Twitter clone where one can post Microposts and they appear in your feed http://ruby.railstutorial.org/chapters/user-microposts#fig-micropost_created
The main page is in home.html.erb from the StaticPagesController and features a Micropost textbox where one can post Microposts. The code for the textbox looks like so:
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
The #micropost variable is initialized in the StaticPagesController like so:
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
end
end
Now inside the MicropostsController there's a create action like so:
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
My question is what is the purpose of the first #micropost variable as opposed to the second?
thanks,
mike
The first #micropost becomes available to the view rendered by the first controller method; the second #micropost becomes available to the view rendered by the second controller method. And it just so happens that the two methods are rendering the same view.
The only wrinkle is that since the second controller is conditional. If the create succeeds (passes validation and saves) then there's a redirect, so there's no proper view (although there will be in a moment, after the client-side redirect). But if it fails, then the view gets an object that contains the user-entered values as well as the validation errors which the view can then show to the user.

instance vs local variables in a partial

I'm currently going through Michael Hartl's tutorial Ruby on Rails Tutorial http://ruby.railstutorial.org/ruby-on-rails-tutorial-book. I'm confused about where certain partial variables come from. In his tutorial he creates Users and Microposts. A User can create a Micropost on his main page (called a Feed) and have them posted there. The layout looks like this http://ruby.railstutorial.org/chapters/user-microposts#fig:proto_feed_mockup. Now the User model looks like this (I'm not posting the entire thing):
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
def feed
Micropost.where("user_id = ?", id)
end
end
The Micropost model looks like this:
class Micropost < ActiveRecord::Base
belongs_to :user
end
In the text the author says that the feed method inside the User model can be written equivalently like this:
def feed
microposts
end
Why are they the same?
My next questions have to do with partials. On the user's show page (show.html.erb) the _microposts.html.erb is called with this if I'm not mistaken:
<%= render #microposts %>
_microposts.html.erb looks like this:
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<% if current_user?(micropost.user) %>
<%= link_to "delete", micropost, method: :delete,
data: { confirm: "You sure?" },
title: micropost.content %>
<% end %>
</li>
My question here is where is the micropost variable come from? Is it the same as the #micropost variable which calls this partial?
Now on the users home page (home.html.erb) there is a call to the _feed.html.erb partial like this:
<%= render 'shared/feed' %>
_feed.html.erb looks like this:
<% if #feed_items.any? %>
<ol class="microposts">
<%= render partial: 'shared/feed_item', collection: #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>
I know where #feed_items comes from. It's set in a controller. Now _feed_item.html.erb looks like this:
<li id="<%= feed_item.id %>">
<%= link_to gravatar_for(feed_item.user), feed_item.user %>
<span class="user">
<%= link_to feed_item.user.name, feed_item.user %>
</span>
<span class="content"><%= feed_item.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
</span>
<% if current_user?(feed_item.user) %>
<%= link_to "delete", feed_item, method: :delete,
data: { confirm: "You sure?" },
title: feed_item.content %>
<% end %>
</li>
So a similar question is where does the variable feed_item come from and what does it contain?
thanks,
mike
Ok, let's see. This is a lot of questions in one go, but...
Why is 'feed' equivalent to 'microposts'?
This is Rails' associations at work. When you use has_many to describe an association, Rails creates a whole bunch of methods based on the association name. In this case, you say that User has_many :microposts, which, among others, creates a User#microposts method.
The instance variable used in the render call (#microposts) is presumably set in a controller action. When you call render in this fashion (with an array of ActiveRecord objects), Rails looks for a partial with a name matching the class name of those objects. In this case, they're MicroPost objects, so it looks for a partial named _micropost and renders it once for each object in the array. When rendering a partial, the object that the partial is associated with can be referred to using a local variable with the same name as the partial. Since this is the _micropost partial, the local micropost variable refers to the object it's rendering.
Once again, the local variable with the same name as the partial refers to the object the partial is rendering. #feed_items is a collection, and for each object in it, you get one rendering of the _feed_item partial, in which the feed_item local variable refers to that object.
Because a user's microposts are associated using has_many, and internally, the relationship is based on the user's id. Getting them "by hand" does essentially the same thing, but with more work.
micropost comes from convention–Rails creates it for you. I don't know what you mean by "the #micropost variable which calls this partial".
Same answer, although it's based explicitly on the template name (IIRC) rather than a singularized name. It contains a single one of whatever #feed_items contains.

No route matches [POST] "/story/new" after submitting form

I've just started "Build Your Own Ruby on Rails" and I have had to use Google a lot, as the book seems to have a bunch of places where the code just doesn't work. This time, I couldn't find an answer. Okay, so here's the deal. I have a form that looks like this:
new.html.erb:
<%= form_for :story do |f| %>
<p>
name:<br />
<%= f.text_field :name %>
</p>
<p>
link: <br />
<%= f.text_field :link %>
</p>
<p>
<%= submit_tag %>
</p>
<% end %>
It shows up fine when I go to localhost:3000/story/new. The thing is, when I try to type stuff into the form and press "submit," I get this error:
Routing Error
No route matches [POST] "/story/new"
My routes.rb looks like this:
FirstApp::Application.routes.draw do
resources :story
story_controller looks like this:
def new
#story = Story.new(params[:story])
if request.post?
#story.save
end
end
The story_controller stuff for new is straight out of the book. I thought I might have had a solution here, but no dice. Any help would be greatly appreciated.
I'm guessing you meant (note the at sign):
<%= form_for #story do |f| %>
That'll probably take care of your routing issue, but as John mentions, your controller action is a bit off, too. The new action should only load a dummy model and display the new.html.erb page - the saving should take place in a separate action, called create.
Hope this helps!
Edit: Minimal controller code:
class StoriesController < ApplicationController
def new
#Make a dummy story so any default fields are filled correctly...
#story = Story.new
end
def create
#story = Story.new(params[:story])
if(#story.save)
#Saved successfully; go to the index (or wherever)...
redirect_to :action => :index
else
#Validation failed; show the "new" form again...
render :action => :new
end
end
end
First off, Rails is relies on convention over configuration when using singular vs plural names. If you want to follow convention, you have to change the line in your routes.rb to resources :stories, which would generate following routes:
stories GET /stories(.:format) stories#index
POST /stories(.:format) stories#create
new_story GET /stories/new(.:format) stories#new
edit_story GET /stories/:id/edit(.:format) stories#edit
story GET /stories/:id(.:format) stories#show
PUT /stories/:id(.:format) stories#update
DELETE /stories/:id(.:format) stories#destroy
Note, that in this case you would have to rename your controller to StoriesController. However, your routes.rb has resources :story, which generates following routes:
story_index GET /story(.:format) story#index
POST /story(.:format) story#create
new_story GET /story/new(.:format) story#new
edit_story GET /story/:id/edit(.:format) story#edit
story GET /story/:id(.:format) story#show
PUT /story/:id(.:format) story#update
DELETE /story/:id(.:format) story#destroy
As you can see, indeed, there is no route for POST /story/new. I guess, the error that you are getting is triggered by following code in your controller:
if request.post?
#story.save
end
It is quite wrong, because you trying to check for POST request inside the action that is routed to by GET. Just remove this code from your new action and add create action to your StoryController like this:
def create
#story = params[:story]
if #story.save
redirect_to #story, notice: "Story created"
else
render action: "new"
end
end
This should resolve your issue for now. But I strongly recommend using plural stories for your resources, since it will be back to haunt you again.
This is the part that you (and me) have missed from the guide:
There's one problem with this form though. If you inspect the HTML
that is generated, by viewing the source of the page, you will see
that the action attribute for the form is pointing at /articles/new.
This is a problem because this route goes to the very page that you're
on right at the moment, and that route should only be used to display
the form for a new article.
The form needs to use a different URL in order to go somewhere else.
This can be done quite simply with the :url option of form_for.
Typically in Rails, the action that is used for new form submissions
like this is called "create", and so the form should be pointed to
that action.
Edit the form_for line inside app/views/articles/new.html.erb to look like this:
<%= form_for :story, url: stories_path do |f| %>

Resources