PUT routes broken by scope - ruby-on-rails-3

In my application, I have several resources scoped into 'admin' as follows (in routes.rb):
scope 'admin', :as => 'admin' do
resources :events
end
So when I go in to use the #new or #update methods through the form, I end up getting the ActionController exception saying No route matches [PUT] "/admin/events".
rake routes produces the following:
admin_events GET /admin/events(.:format) events#index
POST /admin/events(.:format) events#create
new_admin_event GET /admin/events/new(.:format) events#new
edit_admin_event GET /admin/events/:id/edit(.:format) events#edit
admin_event GET /admin/events/:id(.:format) events#show
PUT /admin/events/:id(.:format) events#update
DELETE /admin/events/:id(.:format) events#destroy
_form code:
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<%= form_for #event, :html => { :class => 'form-horizontal' }, :url => url_for(:controller => 'events', :action => 'index') do |f| %>
<fieldset>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :name %>
</div>
</div>
<div class="control-group">
<%= f.label :event_date, :class => 'control-label' %>
<div class="controls date-selects">
<%= f.datetime_select :event_date, :start_year => 2012 %>
</div>
</div>
<div class="control-group">
<%= f.label :publish_date, :class => 'control-label' %>
<div class="controls date-selects">
<%= f.datetime_select :publish_date, :start_year => 2012 %>
</div>
</div>
<div class="control-group">
<%= f.label :blurb, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :blurb, :class => 'span6 wysi' %>
</div>
</div>
<div class="control-group">
<%= f.label :graphic, :class => 'control-label' %>
<div class="controls">
<%= f.file_field :graphic %>
</div>
</div>
<div class="control-group">
<%= f.label :tix_link, :class => 'control-label' %>
<div class="controls">
<%= f.url_field :tix_link %>
</div>
</div>
<div class="form-actions">
<%= f.submit 'Submit', :class => 'btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")), admin_events_path, :class => 'btn' %>
</div>
</fieldset>
<% end %>
What am I doing wrong?

Try changing your form tag from:
<%= form_for #event, :html => { :class => 'form-horizontal' }, :url => url_for(:controller => 'events', :action => 'index') do |f| %>
to:
<%= form_for [:admin, #event], :html => { :class => 'form-horizontal' } do |f| %>
This will use the proper admin scope and properly generate the url, depending if the #event is persisted on the database or not.

Related

Rails two related models in one form not saving

My form fields are:
<%= form_tag signup_path, :class=>"no-ajax form-signin" do %>
<fieldset>
<legend>Company</legend>
<div class="field">
<label>Company Name</label>
<%= text_field :company, :name, :class => "input-block-level" %>
</div>
<%= hidden_field :company, :accounttype_id, :value => 2 %>
</fieldset>
<fieldset>
<legend>User</legend>
<div class="field">
<label>First Name</label>
<%= text_field :user, :first_name, :class => "input-block-level" %>
</div>
<div class="field">
<label>Last Name</label>
<%= text_field :user, :last_name, :class => "input-block-level" %>
</div>
<div class="field">
<label>Email</label>
<%= text_field :user, :email, :class => "input-block-level" %>
</div>
<div class="field">
<label>Role</label>
<%= text_field :user, :role_id, :value => 2 %>
</div>
</fieldset>
<fieldset>
<div class="field">
<label>Password</label>
<%= text_field :user, :password, :class => "input-block-level" %>
</div>
<div class="field">
<label>Confirm Password</label>
<%= text_field :user, :password_confirmation, :class => "input-block-level" %>
</div>
</fieldset>
<div class="form-actions">
<%= submit_tag 'Sign Up', :class => "btn btn-large btn-success btn-block" %>
</div>
<% end %>
My controller for the form is:
def signup
#company = Company.new
#user = #company.users.build
if #company.save
redirect_to :action => 'success'
else
render :action => 'signup'
end
end
When I save, it says that it fails.
This is the data that was posted (pasted from the rails console):
{"utf8"=>"✓", "authenticity_token"=>"9y4JeSvm34P05FBKbP3D3aToHlwejFZBkSyPbmGMJrk=", "company"=>{"name"=>"Test Co", "accounttype_id"=>"2"}, "user"=>{"first_name"=>"Andy", "last_name"=>"Bernard", "email"=>"andy#testco.com", "role_id"=>"2", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign Up"}
What is the form unable to save
is there a better way to do this process? (create new Company, then create user linked to that company, all in one form)
The signup action in your controller does not save #company because no attributes were passed when Company.new was called.
#company = Company.new(params[:company])
will pass the parameters "company"=>{"name"=>"Test Co", "accounttype_id"=>"2"}.
Likewise for "user"=>{...}:
#user = #company.users.build(params[:user])
For an all-in-one form, Rails provides the following method accepts_nested_attributes_for which allows you to create both the company and the user in one go.

Why am I getting undefined method `model_name' for NilClass:Class?

I get this when I visit a user's profile page. so localhost:3000/users/1 for example...
I get it here in line 1
1: <%= form_for(#micropost) do |f| %>
2: <%= render 'shared/error_messages', object: f.object %>
3: <div class="field no-indent">
4: <%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
so then I have two micropost forms one is here
<%= form_for(#micropost, :html => { :id => "sale" }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= hidden_field_tag 'micropost[kind]', "sale" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
and another one is here
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field no-indent">
<%= f.text_area :content, placeholder: "What's something else you want to buy?" %>
<%= hidden_field_tag 'micropost[kind]', "purchase" %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
Here is my routes.
SampleApp::Application.routes.draw do
resources :users do
resources :comments
member do
get :following, :followers
end
end
resources :sessions, only: [:new, :create, :destroy]
resources :microposts, only: [:create, :destroy] do
resources :comments
resources :kind
end
resources :relationships, only: [:create, :destroy]
root to: 'static_pages#home'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
and here is the code for the page itself (users show)
<section>
<%= render 'shared/user_info' %>
</section>
<section>
<div id= "purchases">
<%= render 'shared/micropost_form_purchase' %>
</div>
<div id="sales">
<%= render 'shared/micropost_form_sale' %>
</div>
</section>
<% provide(:title, #user.name) %>
<div class="row">
<aside class="span4">
<section>
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</section>
</aside>
<div class="span8">
<% if #user.microposts.any? %>
<h3>Purchases I am interested in (<%= #user.microposts.count %>)</h3>
<ol class="microposts">
<%= render #microposts %>
</ol>
<%= will_paginate #microposts %>
<% end %>
</div>
</div>
also I dont understand how you can pass an empty object into form for? Isn't the whole point of the form to create the object?
According to the article which I stumbled upon today it may be that the object you are passing to form_for (#micropost in this case) is nil or empty.
Here's the mentioned article: http://schneems.com/post/31460949407/raise-hell-better-programming-through-error-messages

Rails 3 Nested Attributes

I've had this issue for a few days and looked over every tutorial and stack overflow. I cannot seem to resolve. I can't seem to use nested attributes that work. I get an error with this form view.
**Form View**
<%= form_for #trip, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :start, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :start, :class => 'text_field' %>
</div>
<div class="control-group">
<%= f.label :end, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :end, :class => 'text_field' %>
</div>
<div class="control-group">
<% f.fields_for :driver do |d| -%>
<%= d.label :driver, :class => 'control-label' %>
<div class="controls">
<%= d.text_field :driver, :class => 'text_field' %>
</div>
Model:
class Trip < ActiveRecord::Base
attr_accessible :end, :start
belongs_to :driver
belongs_to :customer
accepts_nested_attributes_for :driver
end
class Driver < ActiveRecord::Base
attr_accessible :name
has_many :trips
end
As you said you need closing end tag.
If you have the "Can't mass-assing procteted attributes: drivers" error you must declare "attr_accessible" on :drivers_attributes at the trip model.

Having issues login in with devise with a custom view

I load my custom view with this config in devise.rb
config.scoped_views = true
and then this is my app/views/users/sessions/new.html.erb
<div class="container">
<div id="login">
<%= devise_error_messages! %>
<%= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<div class="login">
<li><%= f.label :email %> <%= f.text_field :email %></li>
<li><%= f.label :password %> <%= f.password_field :password %></li>
</div><!-- login -->
<div class="reset">
<%= f.input :email, :required => false, :autofocus => true %>
<%= f.input :password, :required => false %>
<%= f.input :remember_me, :as => :boolean if devise_mapping.rememberable? %>
</div>
<div class="login">
<%= f.button :submit, "Sign in" %>
</div>
<% end %>
<%= render "links" %>
</div><!-- login -->
</div><!-- container -->
When I submit it just goes back to the page.
When I disable scoped.views it logs in fine.
I forgot you uncomment this line
config.default_scope = :user

Advices to clean this show.html.erb view (Rails)?

The following view shows a single post and its comments:
views/posts/show.html.erb:
<h2>posts show</h2>
<span>Title: <%= #post.title %></span><br />
<span>Content: <%= #post.content %></span><br />
<span>User: <%= #post.user.username %></span><br />
<div class="post-<%= #post.id %>">
<h3><span class="vote-count"><%= #post.total_votes %></span> votes</h3><br />
<div class='voted-user'>
<% #post.votes.each do |vote| %>
<%= link_to vote.user.username, vote.user %>
<% end %>
</div>
<%= link_to "Vote Up", vote_up_path(#votable, :votable_type => "Post"), :remote => true, :class => "vote-up" %><br />
<%= link_to "Vote Down", vote_down_path(#votable, :votable_type => "Post"), :remote => true, :class => "vote-down" %><br />
<h2>Comments</h2>
<p><%= link_to 'Order by Date', post_path(#post, :order_by => "created_at ASC") %></p>
<p><%= link_to 'Order by Votes', post_path(#post, :order_by => "total_votes DESC") %></p>
<% #comments.map do |comment| %>
<div class="comment-<%= comment.id %>">
<p>
<b>Comment:</b>
<%= comment.content %>
</p>
<p>
<b>Vote:</b>
<span class="vote-count"><%= comment.total_votes %></span>
<div class='voted-user'>
<% comment.votes.each do |vote| %>
<%= link_to vote.user.username, vote.user %>
<% end %>
</div>
</p>
<p>
<b>Commenter</b>
<%= link_to comment.user.username, comment.user %>
</p>
<p>
<b>Link</b>
<%= link_to "Show Post Comment", [#post, comment] %>
</p>
<p>
<b>Vote</b>
<%= link_to "Vote Up", vote_up_path(comment, :votable_type => "Comment"), :remote => true, :class => "vote-up" %><br />
</p>
</div>
<% end %>
<%= will_paginate #comments %>
<h2>Add a comment:</h2>
<%= form_for([#post, #post.comments.build]) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% if current_user.id == #post.user_id %>
<%= link_to 'Edit', edit_post_path(#post) %> |
<% end %>
<%= link_to 'Back', posts_path %>
I just focused on making things work so I totally forgot to make it clean.
I'm a Rails beginner and I would like some suggestions or advises to clean this view
(if you suggest to move code to another file please mention the name of the file and the directoy). Thanks in advance.
Good on you for wanting to clean it up. This is some of what I would do. I've included some examples of a few things here: Partials, Helpers, and also cleaned up the HTML a little to allow more control over the style in your stylesheets (which I left out, but you can figure out that part I'm sure). If this was my project, I would extract everything even more (for example, I would probably move the entre "edit/back" links at the bottom, as well as the "Order" links, to their own partials or helpers, since I would probably be using them in a lot of places throughout the application.) And if your comments are polymorphic (i.e., not just for posts), then definitely move that into its own view file. Also, I did this a rather quickly, so it might have some errors, sorry if you find any.
_post.html.erb
<article class="post-info">
<span class="title"><b>Title:</b> <%= post.title %></span>
<p><%= post.content %></p>
<span class="user"><b>User:</b> <%= post.user.username %></span>
</article>
<div class="post" id="post-<%=post.id%>">
<div class="vote-count"><%= post.total_votes %></span> votes
<ul class="voted-user">
<% post.votes.each do |vote| %>
<li><%= link_to vote.user.username, vote.user %></li>
<% end %>
</ul>
<ul class="voting">
<li><%= link_to "Vote Up", vote_up_path(post, :votable_type => "Post"), :remote => true, :class => "vote-up" %></li>
<li><%= link_to "Vote Down", vote_down_path(post, :votable_type => "Post"), :remote => true, :class => "vote-down" %></li>
</ul>
_comment.html.erb
<div class="comment" id="comment-<%=comment.id%>">
<article class="comment">
<b>Comment:</b> <%= comment.content %>
</article>
<div class="votes-total">
<b>Votes:</b> <span class="vote-count"><%= comment.total_votes %></span>
<ul class='voted-user'>
<% comment.votes.each do |vote| %>
<li><%= link_to vote.user.username, vote.user %></li>
<% end %>
</ul>
</div>
<div class="commenter">
<b>Commenter:</b> <%= link_to comment.user.username, comment.user %>
</div>
<div class="link">
<b>Link:</b> <%= link_to "Show Post Comment", [comment.post, comment] %>
</div>
<div class="vote">
<b>Vote:</b> <%= link_to "Vote Up", vote_up_path(comment, :votable_type => "Comment"), :remote => true, :class => "vote-up" %>
</div>
</div> <!-- .comment -->
show.html.erb
<h2>Posts</h2>
<%= render #post %>
<h2>Comments</h2>
<ul class="order">
<li><%= link_to 'Order by Date', post_path(#post, :order_by => "created_at ASC") %></li>
<li><%= link_to 'Order by Votes', post_path(#post, :order_by => "total_votes DESC") %></li>
</ul>
<%= render #comments %>
<%= will_paginate #comments %>
<h2>Add a Comment</h2>
<%= form_for([#post, #post.comments.build]) do |f| %>
<div class="field">
<%= f.label :content %>
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<ul class="manage">
<li><%= edit_link_if_allowed(current_user, #post) %></li>
<li><%= link_to 'Back', posts_path %></li>
</ul>
Posts Helper
def edit_link_if_allowed(current_user, post)
link_to "Edit", edit_post_path(post) if post.user_id == current_user.id
end
You could use Partials