I have two models:
class Tool < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :tools, dependent: :destroy
end
And I created a migration to provide the foreign key of the model:
class AddUserIdToTool < ActiveRecord::Migration
def change
add_column :tools, :user_id, :integer
end
end
I have the following form:
<%= form_for #tool, :html => { :multipart => true } do |f| %>
<% if #tool.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#tool.errors.count, "error") %> prohibited this tool from being saved:</h2>
<ul>
<% #tool.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.file_field :tool_image %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Whenever I submit the form the foreign key is not updated(user_id). I see the following while in my console:
irb(main):002:0> Tool.last
Tool Load (0.0ms) SELECT "tools".* FROM "tools" ORDER BY "tools"."id" DESC LIMIT 1
=> #<Tool id: 6, name: "wrench2", description: "another wrench", created_at: "2015-04-09 21:38:47", updated_at: "2015-04
-09 21:38:47", tool_image_file_name: "wrench.jpg", tool_image_content_type: "image/jpeg", tool_image_file_size: 3424, to
ol_image_updated_at: "2015-04-09 21:38:43", user_id: nil>
irb(main):003:0>
As you can see the user_id is nil
Here is my controller:
class ToolsController < ApplicationController
before_action :authenticate_user!, only: [:new, :destroy, :edit, :update], notice: 'you must sign in first!'
before_action :set_tool, only: [:show, :edit, :update, :destroy]
# GET /tools
# GET /tools.json
def index
#tools = Tool.all
end
# GET /tools/1
# GET /tools/1.json
def show
end
# GET /tools/new
def new
#tool = Tool.new
end
# GET /tools/1/edit
def edit
end
# POST /tools
# POST /tools.json
def create
#tool = Tool.new(tool_params)
respond_to do |format|
if #tool.save
format.html { redirect_to #tool, notice: 'Tool was successfully created.' }
format.json { render :show, status: :created, location: #tool }
else
format.html { render :new }
format.json { render json: #tool.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tools/1
# PATCH/PUT /tools/1.json
def update
respond_to do |format|
if #tool.update(tool_params)
format.html { redirect_to #tool, notice: 'Tool was successfully updated.' }
format.json { render :show, status: :ok, location: #tool }
else
format.html { render :edit }
format.json { render json: #tool.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tools/1
# DELETE /tools/1.json
def destroy
#tool.destroy
respond_to do |format|
format.html { redirect_to tools_url, notice: 'Tool was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tool
#tool = Tool.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def tool_params
params.require(:tool).permit(:name, :description, :tool_image, :user_id)
end
end
How would I get the user_id updated with the id of the logged in user? Do I have to include a hidden field in my form or something like that?
Also do I have to permit the user_id variable within my strong parameters in my controller? I have tried this but it has not solved the problem...
How does this work?
Currently you are building a tool on its own. To associate it with the user model you need to create a tool model in the following way:
#user.tools.build
It will create a new ActiveRecord tool model with proper user_id of a belonged model. But to get parent you need to fetch its id from your params. It could be done in a such way, in your action:
#user = User.find(params[:user_id])
Note: to make it possible your routes should be nested correspondingly (read more here: http://guides.rubyonrails.org/routing.html)
So, all in all, your new action should look like:
def new
#user = User.find(params[:user_id])
#tool = #user.tools.build
end
And in your routes.rb
resources :users do
resources :tools
end
Related
I am trying to send one email through action mailer using ROR. But it can not sent even if it is not showing any error.I am explaining my codes below .Please check these and let me to know where i did mistake and what might be the possibility solutions.
views/users/_form.html.erb:
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
views/user_mailer/registration_confirmation.html.erb:
Thank you for registering!
controller/users_controller.rb
class UsersController < ApplicationController
# GET /users
# GET /users.json
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #users }
end
end
# GET /users/1
# GET /users/1.json
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
# GET /users/new
# GET /users/new.json
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
end
# POST /users
# POST /users.json
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
UserMailer.registration_confirmation(#user).deliver
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PUT /users/1
# PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
end
mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "subhrajyotipradhan#gmail.com"
def registration_confirmation(user)
mail(:to => user.email, :subject => "Registered")
end
end
config/initializers/setup_mail.rb
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "gmail.com",
:user_name => "subhrajyotipradhan#gmail.com",
:password => "XXXXXXX",
:authentication => "plain",
:enable_starttls_auto => true
}
In your config/environments/<RAILS_ENV>.rb, alter or add the following configuration, and rerun your test:
config.action_mailer.delivery_method = :file
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
With this configuration, mails will not be actually delivered thru SMTP, but will be stored in tmp/mails/. If no error is raised, then check your SMTP settings.
I have a TodoList model and a TodoItem model. I can create the nested form and it renders in the todolist#new. It will only create a todolist title. It will accept the todo list items, but on the index page the items are not showing up.
I have done a ton of research including the docs and these sources; see bottom of the post.
The form will render with no errors. But when I hit save the todo list title will save, but the items I enter will not save.
Todo List Title
--This will save
Items
---This will not save
Controller
class TodoListsController < ApplicationController
before_filter :authenticate_user!
before_filter except: [:index]
before_action :set_todo_list, only: [:show, :edit, :update, :destroy]
# GET /todo_lists
# GET /todo_lists.json
def index
##todo_lists = TodoList.all
#todo_lists = current_user.todo_lists
#todo_items = current_user.todo_items
end
# GET /todo_lists/1
# GET /todo_lists/1.json
def show
end
# GET /todo_lists/new
def new
#todo_list = current_user.todo_lists.new
#todo_list.todo_items.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #todo_list }
end
end
# GET /todo_lists/1/edit
def edit
#todo_list = TodoList.find(params[:id])
end
# POST /todo_lists
# POST /todo_lists.json
def create
##todo_list = TodoList.new(todo_list_params)
#todo_list = current_user.todo_lists.new(todo_list_params)
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo list was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /todo_lists/1
# PATCH/PUT /todo_lists/1.json
def update
#todo_list = TodoList.find(params[:id])
respond_to do |format|
if #todo_list.update(todo_list_params)
format.html { redirect_to #todo_list, notice: 'Todo list was successfully updated.' }
format.json { render :show, status: :ok, location: #todo_list }
else
format.html { render :edit }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /todo_lists/1
# DELETE /todo_lists/1.json
def destroy
##todo_list.TodoList.find(params[:id])
#todo_list.destroy
respond_to do |format|
format.html { redirect_to todo_lists_url, notice: 'Todo list was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def owns_todolist
if current_user != TodoList.find(params[:id]).user
redirect_to todo_lists_path, error: "You can't do that!"
end
end
# Use callbacks to share common setup or constraints between actions.
def set_todo_list
#todo_list = TodoList.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def todo_list_params
params.require(:todo_list).permit(:title,:todo_list => [:description])
end
end
Models
class TodoList < ActiveRecord::Base
has_many :todo_items, dependent: :destroy
accepts_nested_attributes_for :todo_items
end
class TodoItem < ActiveRecord::Base
belongs_to :todo_list
end
Form
<%= form_for(#todo_list) do |f| %>
<% if #todo_list.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#todo_list.errors.count, "error") %> prohibited this todo_list from being saved:</h2>
<ul>
<% #todo_list.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<%= f.fields_for :todo_items do |b| %>
<--- I also tried passing this in fields for #todo_list.todo_items.build -- >
<%= b.label :description, "Items" %><br />
<%= b.text_field :description %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Previous research
Nested Form with Nested Resource Rails 4
Rails 4 Nested Form.
How to Create Nested Forms in Rails 4
http://www.createdbypete.com/articles/working-with-nested-forms-and-a-many-to-many-association-in-rails-4/
http://railscasts.com/episodes/196-nested-model-form-revised?view=comments
Rails 4 Nested form fields not saving in database
And the list goes on.
The problem is with your todo_list_params method.It should be like this
def todo_list_params
params.require(:todo_list).permit(:title,todo_items_attributes: [:description])
end
Hello I'm new to rails 4
I am working on project where we can post and rate it. I have used activerecord reputation gem. I have been following the http://railscasts.com/episodes/364-active-record-reputation-system video.
I am stuck at the routing point. When I click on upvote or downvote it shows me error.
my routes.rb file has
resources :posts do
resources :comments, :only => [:create]
member { post :vote }
end
get "posts/create"
get "posts/destroy"
get "posts/new"
get "posts/index"
get "posts/show"
get "posts/edit"
get "posts/update"
_post.html.erb
<h4 class="timeline-title"><%= link_to_unless_current post.title, post %></h4>
<p> Created : <%= post.created_at.strftime("%d/%m/%Y") %> by <%= post.postedby %>
</p>
<% if current_cubestudent.email == post.postedby %>
<p><%= link_to 'Edit', edit_post_path(#post) %>
<%= link_to 'Destroy', posts_path, method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
<%= simple_format post.body , :class => "timeline-body"%>
<%= pluralize post.reputation_for( :votes).to_i, "vote" %>
<% if current_cubestudent && !current_cubestudent.voted_for?(post) %>
<%= link_to "up", vote_post_path(post, type: "up"), method: "post" %>
<%= link_to "down", vote_post_path(post, type: "down"), method: "post" %>
<% end %>
my post#show is
<%= stylesheet_link_tag "application",:media =>"screen" %>
<p id="notice"><%= notice %></p>
<p id="alert"><%= alert %></p>
<%= render :partial => #post %>
<%= link_to 'Back', posts_path %>
<h2 id="timeline">Comments</h2>
<div>
<%= render :partial => #post.comments %>
</div>
<div class="container">
<%= form_for [#post, Comment.new] do |f| %>
<div style="padding-bottom:0">
<%= f.text_area :body , :placeholder => "Write your comment"%>
<%= f.submit "Add comment", :class => "btn btn-info" %>
</div>
<% end %>
</div>
posts controller is
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def create
#post = Post.new(post_params)
#post.postedby = current_cubestudent.email
#post.postedbyid = current_cubestudent.id
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
def new
#post = Post.new
end
def index
#posts = Post.find_with_reputation(:votes, :all, order: "votes desc")
end
def show
#post = Post.find(params[:id])
end
def edit
end
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def vote
value = params[:type] == "up" ? 1 : -1
#post = Post.find(params[:id])
#post.add_or_update_evaluation(:votes, value, current_cubestudent)
redirect_to :back, notice: "Thank you for voting"
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :body, :subject)
end
end
after rake routes | grep post
C:\Sites\project>rake routes | grep post
post_comments POST /posts/:post_id/comments(.:form comments#create
vote_post POST /posts/:id/vote(.:format) posts#vote
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
posts_create GET /posts/create(.:format) posts#create
posts_destroy GET /posts/destroy(.:format) posts#destroy
posts_new GET /posts/new(.:format) posts#new
posts_index GET /posts/index(.:format) posts#index
posts_show GET /posts/show(.:format) posts#show
posts_edit GET /posts/edit(.:format) posts#edit
posts_update GET /posts/update(.:format) posts#update
Can someone help me on it....??
Your main problem is in this code
<%= link_to "up", vote_post_path(post, type: "up"), method: "post" %>
you would like to send "post" request but in fact you send default ("get") request.
I can suppose that link_to accepts only symbols for method (you pass string). So try this
<%= link_to "up", vote_post_path(post, type: "up"), method: :post %>
Another source of the problem can be wrong routes. If code above does not help you run in console rake routes | grep post and add output to the question.
I have a Section model, where a Section can be a parent of another Section (subsection).
Here is my model:
class Section < ActiveRecord::Base
has_many :exercises
has_one :parent_link,
:foreign_key => 'subsection_id',
:class_name => 'SectionLink',
:dependent => :destroy
has_one :parent, :through => :parent_link
has_many :subsection_links,
:foreign_key => 'parent_id',
:class_name => 'SectionLink',
:dependent => :destroy
has_many :subsections, :through => :subsection_links
attr_accessor :parent_id
def to_param
"#{id}-#{description.parameterize}"
end
def self.search(search)
if search
find(:all, :conditions => ['description LIKE ?', "%#{search}%"])
else
find(:all)
end
end
end
And the association model:
class SectionLink < ActiveRecord::Base
belongs_to :parent, :class_name => 'Section'
belongs_to :subsection, :class_name => 'Section'
end
My controller:
class SectionsController < ApplicationController
# GET /sections
# GET /sections.json
def index
#sections = Section.order("subsections_count DESC").search(params[:search])
respond_to do |format|
format.html # index.html.erb
end
end
# GET /sections/1
# GET /sections/1.json
def show
#section = Section.find(params[:id])
#subsections = #section.subsections
#exercises = #section.exercises
respond_to do |format|
format.html # show.html.erb
format.json { render json: #section }
end
end
# GET /sections/new
# GET /sections/new.json
def new
#section = Section.new
#section.parent_id = params[:parent]
respond_to do |format|
format.html # new.html.erb
format.json { render json: #section }
end
end
# GET /sections/1/edit
def edit
#section = Section.find(params[:id])
end
# POST /sections
# POST /sections.json
def create
#section = Section.new(params[:section])
#parent = #section.build_parent(:parent_id => #section.parent_id) unless #section.parent_id.empty?
respond_to do |format|
if #section.save
format.html { redirect_to #section, notice: 'Section was successfully created.' }
format.json { render json: #section, status: :created, location: #section }
else
format.html { render action: "new" }
format.json { render json: #section.errors, status: :unprocessable_entity }
end
end
end
# PUT /sections/1
# PUT /sections/1.json
def update
#section = Section.find(params[:id])
respond_to do |format|
if #section.update_attributes(params[:section])
format.html { redirect_to #section, notice: 'Section was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #section.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sections/1
# DELETE /sections/1.json
def destroy
#section = Section.find(params[:id])
#section.destroy
respond_to do |format|
format.html { redirect_to sections_url }
format.json { head :no_content }
end
end
end
The parent ID is fed in via a hidden field in the form:
<%= form_for(#section) do |f| %>
<% if #section.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#section.errors.count, "error") %> prohibited this section from being saved:</h2>
<ul>
<% #section.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :description %><br />
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<%= f.hidden_field :parent_id, :value => #section.parent_id %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm getting
undefined method 'build_parent' for #<Section:0xb4f1764c>
Is there a better way of modelling this association? Why is build_parent undefined?
UPDATE:
Now works with following controller code:
#section = Section.new(params[:section])
unless #section.parent_id.empty?
#parent = Section.find(#section.parent_id)
#section.parent = #parent
end
Looking for any suggestions on how it can be improved, and why it did not work before...
You're looking to do a self join.
class Section < ActiveRecord::Base
has_many :subsections, :class_name => "Section"
belongs_to :parent_section, :class_name => "Section",
:foreign_key => "parent_id"
end
I want to add buttons on my article so that I can know the number of times its clicked and update counter on the database, I am using mongoid ,my model is:
class Article
include Mongoid::Document
include Mongoid::Timestamps
field :title, :type => String
field :content, :type => String
field :likes, :type => Integer ,:default => 0
field :dislikes, :type =>Integer, :default => 0
field :spam, :type => Integer, :default => 0
end
My articles show controller is:
def show
#article = Article.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #article }
end
end
My View for show is:
<p id="notice"><%= notice %></p>
<p>
<b>Title:</b>
<%= #article.title %>
</p>
<p>
<b>Content:</b>
<%= raw #article.content %>
</p>
Likes : <%= #article.likes %> <br/>
Dislikes : <%= #article.dislikes %><br/>
Spams : <%= #article.spam %><br/>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Back', articles_path %>
I find anything about it in internet.
How can I achieve it?
The easiest thing to do would be add a click_count integer attribute to your Article model and then increment this in your controller code:
def show
#article = Article.find(params[:id])
#article.increment! :click_count
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #article }
end
end
i got it done, phew!
I added the following form in my show.html.erb:
<%=form_for(#article,:action=>"update") do |f| %>
<%= submit_tag "Like", :name=>"like"%>
<%= submit_tag "Dislike",:name=>"dislike"%>
<%= submit_tag "Spam",:name=>"spam" %>
<%end%>
and wrote the following update controller:
def update
#article=Article.find(params[:id])
if params[:like]
#article.likes=#article.likes+1
elsif params[:dislike]
#article.dislikes=#article.dislikes+1
elsif params[:spam]
#article.spams=#article.spams+1
end
respond_to do |format|
if #article.update_attributes(params[:article])
format.html {redirect_to #article, :notice => "Article Updated"}
else
format.html {render :action=>"edit", :notice=> "Unable to update Article , sorry! :("}
end
end
end
It worked like a charm.