Okay so I have a post index and would like to link it to my slide index, but for some reason i keep getting this error
No route matches {:controller=>"slides"}
when i link with this
<%= link_to 'Show Slides', post_slides_path(#post) %>
If i use the same link above in my Posts Edit Viewer, it seems to work fine....any suggestions?
I would basically like to link to this....../posts/:id/slides from the my table in posts
ROUTES.RB
resources :posts do
resources :slides
end
POST MODEL
class Post < ActiveRecord::Base
attr_accessible :text, :title
has_many :slides, :dependent => :destroy
def self.search(search)
if search
where('Title Like ?' , "%#{search}%")
else
scoped
end
end
SLIDE MODEL
class Slide < ActiveRecord::Base
belongs_to :post
POST INDEX VIEW
<table id="posts" class="table table-striped table-bordered">
<thead>
<tr>
<th>Title</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= link_to 'Show Slides', post_slides_path(#post) %>
<td><%= link_to 'Edit', :action => :edit, :id => post.id %></td>
<td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :confirm => 'Are you sure?' %></td>
</tr>
<% end %>
<tbody>
<% end %>
</table>
POST CONTROLLER
class PostsController < ApplicationController
def new
#post = Post.new
end
def show
#post = Post.find(params[:id])
end
def index
#posts = Post.search(params[:search]).paginate(:per_page => 10, :page => params[:page])
end
def edit
#post = Post.find(params[:id])
end
SLIDE CONTROLLER
class SlidesController < ApplicationController
def index
#post = Post.find(params[:post_id])
#slides = #post.slides.all
end
def show
#post = Post.find(params[:post_id])
#slide = #post.slides.find(params[:id])
end
def new
#post = Post.find(params[:post_id])
#slide = Slide.new
end
def edit
#post = Post.find(params[:post_id])
#slide = Slide.find(params[:id])
end
The post_slides_path is looking for an id as the parameter to match to the /posts/:id/slides route. The reason it works in your edit page is because your #post variable is finding the id of the Post object ( #post = Post.find(params[:id]) ). In your index action of the Post controllers, you have the #posts instance variable pointing to the search params and paginating and you do not have a #post instance variable defined.
In your block try
post_slides_path(post.id)
Related
Each day for every Store a Daily is created containing DailyDatum for each Service. I am able to create and render the fields but I can't seem to get them to update.
My problem is saving the data from the services hash.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"F3JnDp/6TMV7rte24kjBDOjMo17BR/jIdaH2+a5s3AXLtvybhSUM9xbPSn1uvUfL9d7AXUmSeZOM+iz18SnYJA==", "daily"=>{"store_id"=>"1"}, "services"=>{"5"=>{"service_id"=>"1", "value"=>"2"}, "6"=>{"service_id"=>"2", "value"=>"2.0"}, "7"=>{"service_id"=>"3", "value"=>"3.0"}, "8"=>{"service_id"=>"4", "value"=>"4.0"}}, "commit"=>"Update Daily", "store"=>"12", "id"=>"12"}
The services hash contains hashes of each DailyDatum object and their attribute/value.
Daily Datum Model
class DailyDatum < ApplicationRecord
belongs_to :daily
belongs_to :service
end
Daily Model
class Daily < ApplicationRecord
has_many :daily_data
belongs_to :store
accepts_nested_attributes_for :daily_data
end
Store Model
class Store < ApplicationRecord
has_many :store_users, inverse_of: :store
has_many :users, through: :store_user
has_many :dailies
accepts_nested_attributes_for :store_users, allow_destroy: true
end
User Model
class User < ApplicationRecord
has_many :store_users, inverse_of: :user
has_many :stores, through: :store_user
accepts_nested_attributes_for :store_users, allow_destroy: true
end
Daily Controller
class DailyController < ApplicationController
before_action :set_daily, only: [:show, :edit, :update]
before_action :set_services, only: [:edit, :update]
def index
#dailies = Daily.all
end
def show
#daily = Daily.find(params[:id])
end
def store
#dailies = Daily.where(store_id: params[:store])
end
def new
#daily = Daily.new
#services = []
Service.all.each do |s|
service = #daily.daily_data.build
service.service_id = s.id
#services << service
end
end
def edit
end
def create
#daily = Daily.new(daily_params)
if #daily.save
params["services"].each do |service|
data = DailyDatum.new(service_params(service))
data.daily_id = #daily.id
data.save
end
redirect_to dailies_url
else
render 'new'
end
end
def update
if #daily.update_attributes(daily_params)
redirect_to #daily
else
render 'edit'
end
end
private
def set_daily
#daily = Daily.find(params[:id])
end
def set_services
#services = DailyDatum.where(daily_id: #daily.id).where(created_at: #daily.created_at.time.beginning_of_day..#daily.created_at.time.end_of_day)
end
def daily_params
params.require(:daily).permit(:store_id, services: [:daily_id, :service_id, :value])
end
def service_params(my_params)
my_params.permit(:daily_id, :service_id, :value)
end
end
Daily View (form partial) for new and edit
<%= form_for(daily) do |f| %>
<% if daily.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(daily.errors.count, "error") %> prohibited this daily from being saved:</h2>
<ul>
<% daily.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :store_id, value: params[:store] %>
<table class="table table-hover">
<thead>
<tr>
<th>Service</th>
<th>Cash In</th>
<th>Cash Out</th>
</tr>
</thead>
<tbody>
<% #services.each do |service| %>
<tr>
<%= fields_for 'services[]', service do |s| %>
<%= s.hidden_field :service_id, value: service.service_id %>
<td><%= s.label :value, service_name(service.service_id) %></td>
<% if ( cash_in(service.service_id) ) %>
<td><%= s.text_field :value %></td>
<td></td>
<% else %>
<td></td>
<td><%= s.text_field :value %></td>
<% end %>
<% end %>
</tr>
<% end %>
</table>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Probably not "the rails way", but it works..
def update
if #daily.update_attributes(daily_params)
params["services"].each do |k,v|
data = DailyDatum.find(k)
data.update_attributes(service_params(v))
end
redirect_to daily_path(#daily)
else
render 'edit'
end
end
Sorry for maybe newbie question.
I want to use a paperclip and paperclip_database gems to attach and save files in my database.
But I stuck on sending file's data from views to controller.
I've done all from this, and this resources. As the result I have next models:
class User < ActiveRecord::Base
has_many :certificates, :dependent => :destroy
accepts_nested_attributes_for :certificates, :allow_destroy => true
end
class Certificate < ActiveRecord::Base
belongs_to :user
attr_accessor :image
has_attached_file :image,
:storage => :database,
:database_table => 'image_files',
:cascade_deletion => true
end
in a controller
Users_controller
def new
#user = User.new
#user.certificates.build
~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~
end
def create
#user = User.new(params[:user])
~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~
end
end
and my view form is:
<%= form_tag #user, method: :put, :html => { :multipart => true } do |f|%>
<%= fields_for each_event_entry.certificates.first do |c| %>
<tr>
<th>Certificate</th>
<td>
<%= c.file_field :image %>
</td>
</tr>
<% end %>
<% end %>
But when I attach a file and try to submit, I've only got a file name in params:
{
"user" => {"some"=>"params"}
"certificate"=>{"image"=>"IMG_1642.JPG"}
}
And certificate is saved whithout attached file.
Any help will be extremely appreciated.
Finally, I found out the problem.
It appears to be that the "form_tag" form doesn't need an :html attribute, so the html form should look like:
<%= form_tag #user, :multipart => true do |f| %>
In my case, there is no necessity of method: as well.
Hope this will help someone.
Updated
Per the answer below here is my new link_to
<%= link_to "Post a Question", new_classifieds_question_path(#classified) %>
and my controller
class QuestionsController < ApplicationController
def index
end
def new
#classified = Classified.find(params[:classified_id])
#question = Question.new
end
def create
#classified = Classified.find(params[:classified_id])
#question = Question.new(params[:question])
#classified.questions << #question
if #question.save
flash[:notice] = "Question has been posted"
else
flash[:notice] = "It did not go through"
end
end
end
new routes
resource :classifieds do
resources :questions
end
classified model
class Classified < ActiveRecord::Base
has_many :questions
end
and question model
class Question < ActiveRecord::Base
attr_accessible :question_body, :classifieds_id
belongs_to :classified
end
and my new error
Couldn't find Classified without an ID
I have a questions controller with two new/create methods
def new
#question = Question.new
end
def create
#question = Question.new(params[:question])
#question.classifieds_id = #classified.id
##question.classifieds_id = params[:id]
if #question.save
flash[:notice] = "Question has been posted"
else
flash[:notice] = "It did not go through"
end
end
A question belongs_to a classified ad. The questions table in the schema has a classifieds_id column.
Here is my question model
class Question < ActiveRecord::Base
attr_accessible :question_body, :classifieds_id
belongs_to :classified
end
in my routes.rb
resources :questions
Here is one variation of my link_to (in my show.html.erb)
This is my show method in another controller
def show
#classified=Classifieds.find(params[:id])
end
<td>
<%= link_to "Post a Question", new_question_path(#classified) %>
</td>
I am trying to pass the id of the classified instance to be processed by the questions controller.
I have tried many version of a link_to, like this
<td>
<%= link_to "Post a Question", new_question_path(:id => #classified.id) %>
</td>
and like this
<td><%= link_to "Post a Question", {:controller => "questions", :action => "new", :classified_id => #classified.id }, :class => "btn btn-default btn-lg" %></td>
<tr>
The hacks just isn't working and searching questions on stackoverflow isn't working either.
I have tried doing this in show.html.erb
<p>
<%= #classified.id %>
</p>
and the value gets outputted. I got better errors installed and a nil value gets passed in.
using gem 'rails', '3.2.13'
If you have nested resources in your routes...
resources :classifieds do
resources :questions
end
That will give you the method
<%= link_to "Post a question", new_classifieds_question_path(#classified) %>
Your new method will receive the classified_id
def new
#classified = Classified.find(params[:classified_id])
#question = Question.new
end
def create
#classified = Classified.find(params[:classified_id])
#question = Question.new(params[:question]
#classified.questions << #question
...
end
EDIT
Sorry, forgot the _path in the path call, now fixed.
My problem is that I don't have an idea to create a list of users with emails, and in the same list have a checkbox for every user, then at the end have a button 'Send' and send all the emails to the checked users, I solved temporaly with:
1)List (index view)
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Correo</th>
<th>Send Email</th>
<th></th>
<th></th>
<th></th>
</tr>
<% var1 = []; i = 0 %>
<% #users.each do |user| %>
<tr id=<%= if user.value == 'No dispatched'
'c'
elsif user.value == 'Dispatched'
'a'
else
'b'
end%> >
<td><%= user.name %></td>
<td><%= user.email %></td>
<td><%= user.value %></td>
<td><% var1[i] = user.name; i=i+1 %>
<%= button_to 'Activate/Desactivate', edit_send_path(user.id), :method => :get %> </td>
</td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New User', new_user_path %>
<%= button_to 'Send', {:controller => :Send, :action => :send}, :method => :get, :value => 2 %>
2)Send controller
class SendController < ApplicationController
def send
#users = User.all
#users.each do |user|
if user.value == 'In Process'
UserMailer.registration_confirmation(user).deliver
user.value = 'Dispatched'
user.save
end
end
redirect_to :controller => :users, :protocol => 'http'
end
def edit
user = User.find(params[:id])
if user.value == 'In process'
user.value = 'No dispatched'
user.save
elsif user.value == 'No dispatched'
user.value = 'In process'
user.save
end
redirect_to :controller => :users, :protocol => 'http'
end
end
I'm using the flag 'value' to check if the email was sended
I did this for part of my senior project, here's how I did it:
For each user add a checkbox that is linked to each user's id inside the do loop, looks like:
<td><%= check_box_tag ':multiple_users[]', user.id %></td>
Add a submit_tag below the do loop, looks like, note that the name was simply to differentiate between differing actions we used when selecting users:
<%= submit_tag "Email Selected Users", :name => "selected" %>
Add the corresponding form tag somewhere at the top of the view, mine goes to the handler, but yours would go to your "send" action, the empty hash is important:
<%= form_tag handle_checkbox_handler_path({}) do %>
Generate a mailer, I did not do this and I do not know how, I'm sure Google does :) You will also need to make a config file for the mailer (again google this, I can't help you).
Once you have that mailer, create an action in it to email a user:
def email_user(email, subject, text_body)
#text_body = text_body
mail( :to => email, :subject => subject, :from => "monkey#feet.com")
end
Once you have the action, make a corresponding view for the email (mine is very simple it just puts the #text_body value.
<%= #text_body %>
In your send action send the email to multiple users, here's my code, I'm no Ruby expert but it worked for me. Also it's not very clean so I'll add some comments for your readability:
if not params[':multiple_users'].nil? # There are multiple users to email
# Split the passed string and loop through each ID in the string sending an email to each user listed
params[':users'].split.each do |u|
# Emailer is my mailer's name, :subject and :message I passed into the action as well. email_user is the name of my mailer action, defined above.
Emailer.email_user(User.find(u.to_i).email, params[:subject], params[:message]).deliver
end
redirect_to users_path, :notice => "Message was sent successfully"
else # there is only one user to email
if Emailer.email_user(params[:email], params[:subject], params[:message]).deliver # Try to send, if fails tell them so
redirect_to users_path, :notice => "Message was sent successfully"
else
redirect_to users_path, :alert => "Message failed to send"
end
end
end
I hope this is readable and at least gives you a starting point. You should also know that the check_box_handler I mentioned earlier does some checking to ensure that nothing bad happened.
I have a project that contains projects that have todos that have tasks. When I try to create a new task, I get this error when I submit:
No route matches [POST] "/projects/1/todos/19/tasks/new"
Here is my form:
<%= form_for [#todo, #todo.tasks.new], :url => new_project_todo_task_path(#project, #todo) do |f| %>
<div class="field">
<%= f.label :description, "Description" %><br />
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %> or <%= link_to "Cancel", "#", :id => "cancel_new_task_link" %>
</div>
<% end %>
Here is my controller:
class TasksController < ApplicationController
before_filter :authenticated?
before_filter :get_project_and_todo
respond_to :html, :xml, :json, :js
def new
#task = #todo.tasks.new
end
def create
#task = #todo.tasks.new(params[:task])
if #task.save
respond_with #todo, :location => project_todo_path(#project, #todo)
else
render "new"
end
end
private
def get_project_and_todo
#project = Project.find(params[:project_id])
#todo = #project.todos.find(params[:todo_id])
end
end
Here are my routes:
resources :projects do
resources :todos do
resources :tasks
end
end
Thanks
Your URL should not be new_project_todo_task_path(#project, #todo). You don't need to specify the URL here as Rails will imply it from the parameters passed in to form_for.
If the final object is a new object and not persisted in the database then it will make a POST request to, in this case, /projects/:project_id/todos. You're declaring in your example that you want to make a POST request to /projects/:project_id/todos/new, for which there is no POST route and that is why it's failing.