please help solve the problem.
models:
class Tag < ActiveRecord::Base
has_and_belongs_to_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :tags
end
tables:
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "body"
t.integer "user_id"
end
create_table "posts_tags", id: false, force: :cascade do |t|
t.integer "post_id"
t.integer "tag_id"
end
create_table "tags", force: :cascade do |t|
t.string "tagname"
end
form:
<%= form_for [#user, #post] do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :body %>
<%= f.text_area :body %>
<label class="lbl_tagname"><%=t :tags %></label>
<%= text_field_tag 'tagnames', nil, class: 'tagnames' %>
<%= f.submit %>
<% end %>
post controller:
def new
#user = User.find(params[:user_id])
#post = Post.new
end
def create
#post = current_user.posts.build(post_params)
if #post.save
add_new_tags(#post)
flash[:success] = t :post_saved
redirect_to user_post_path(#current_user, #post)
else
flash.now[:error] = t :post_not_saved
render 'new'
end
end
private
def add_new_tags(post)
tagnames = params[:tagnames].split(/[, \.?!]+/)
tagnames.each do |tagname|
tagname_exist = Tag.find_by tagname: tagname.downcase
tag = Tag.create(tagname: tagname.downcase) if !tagname_exist
tag.posts.push post
p '=============='
p post.id
p '=============='
end
end
def post_params
params.require(:post).permit(:title, :body, :tagnames)
end
a user visits a page, see the form. fill in the form below. sends. resulting record is not added to the table posts_tags.
displays the following error message:
NoMethodError in PostsController#create
undefined method `posts' for nil:NilClass
the console displays the following:
"=============="
391
"=============="
Tag Load (0.1ms) SELECT "tags".* FROM "tags" WHERE "tags"."tagname" = ? LIMIT 1 [["tagname", "asd"]]
Completed 500 Internal Server Error in 904ms (ActiveRecord: 811.8ms)
NoMethodError (undefined method `posts' for nil:NilClass):
app/controllers/posts_controller.rb:93:in `block in add_new_tags'
app/controllers/posts_controller.rb:89:in `each'
app/controllers/posts_controller.rb:89:in `add_new_tags'
app/controllers/posts_controller.rb:45:in `create'
wherein. in table post entry is created
def add_new_tags(post)
tagnames = params[:tagnames].split(/[, \.?!]+/)
tagnames.each do |tagname|
tag = Tag.find_or_create_by(tagname: tagname.downcase)
tag.posts << post
end
end
You need to push post to tag only after initilizing tag variable
tag = tagname_exist || Tag.create(tagname: tagname.downcase)
tag.posts.push post
Related
I am using gem nested form https://github.com/ryanb/nested_form in order to create a Flat with multiple pictures.
The Flat model has many pictures.
the form looks like that :
<%= simple_nested_form_for #flat do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.fields_for :pictures do |pictures_form| %>
<%= pictures_form.file_field :image %>
<%= pictures_form.link_to_remove ('<i class="fa fa-trash"></i>').html_safe %>
<% end %>
<%= f.link_to_add ('<i class="fa fa-plus"></i>').html_safe, :pictures %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
My controller create action :
def create
#flat = Flat.new(flat_params)
authorize #flat
#flat.user = current_user
#flat.pictures.build
if #flat.save
redirect_to flat_path(#flat), notice: 'Flat was successfully created.'
else
render :new
end
end
and my flat_params :
def flat_params
params.require(:flat).permit(:name, pictures_attributes: [:id, :image, :_destroy])
end
I always get the following error :
unknown attribute 'image' for Picture.
I used the gem paperclip for image upload Here's how my table picture looks in my schema :
create_table "pictures", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.integer "flat_id"
end
What is the problem ?
Why are you building in the create method? This is where you save only:
def new
#flat = Flat.new
#flat.pictures.build #-> pictures.build should be in the new method only
end
def create
#flat = Flat.new flat_params
#flat.user = current_user
authorize #flat
if #flat.save
redirect_to #flat, notice: 'Flat was successfully created.'
else
render :new
end
end
Other than the above (pictures.build), your code looks good.
The other issue you may have is that you've not included the Paperclip reference in your Picture model. You'll need to have the following:
#app/models/picture.rb
class Picture < ActiveRecord::Base
has_attached_file :image #-> + any styling options etc
end
From the code you've provided, that's what I can give.
i am new to rails so any help would be much appreciated. I have the models userrs (recruiters) and adverts. Userr has_many adverts and Advert belongs to a user.
Question: when a userr creates an advert i want the created advert to
be automatically linked to the userr that created the advert. I am
unsure how to go about this in the controller
i know how to assign an advert to a user in the console. but unsure how to do this in the controller
console
advert = Advert.first
advert.userr_id = 3
advert.save
route
Rails.application.routes.draw do
resources :adverts
resources :feedbacks
devise_for :userrs
devise_for :userjs
root 'static_pages#homepg'
get 'affiliate', to: 'static_pages#affiliatepg'
get 'terms', to: 'static_pages#termpg'
get 'privacy', to: 'static_pages#privacypg'
get 'contact', to: 'static_pages#contactpg'
get 'about', to: 'static_pages#aboutpg'
get 'recruiters', to: 'static_pages#recruiterpg'
get 'jobseekers', to: 'static_pages#jobseekerpg'
get 'approach', to: 'static_pages#approachpg'
get 'sector', to: 'static_pages#sectorpg'
get 'news', to: 'static_pages#newspg'
get 'offer', to: 'static_pages#offerpg'
get 'refferal', to: 'static_pages#refferalpg'
end
i placed the below code:
in my advert controller under the create function:
def create
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.build(params[:advert])
if #advert.save
flash[:notice] = 'Successfully created advert'
redirect_to recruiters_path
else
render action: 'new'
end
end
but i got the error:
Couldn't find Userr without an ID
log - error message
Started GET "/adverts/new" for 127.0.0.1 at 2015-04-02 14:59:38 +0100
Processing by AdvertsController#new as HTML
Completed 404 Not Found in 1ms (ActiveRecord: 0.0ms)
ActiveRecord::RecordNotFound (Couldn't find Userr without an ID):
app/controllers/adverts_controller.rb:20:in `new'
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_source.erb (8.2ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_trace.html.erb (3.4ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_request_and_response.html.erb (0.8ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_web_console.html.erb (0.8ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/diagnostics.html.erb within rescues/layout (27.3ms)
Started GET "/adverts/new" for 127.0.0.1 at 2015-04-02 14:59:38 +0100
Processing by AdvertsController#new as HTML
Completed 404 Not Found in 1ms (ActiveRecord: 0.0ms)
ActiveRecord::RecordNotFound (Couldn't find Userr without an ID):
app/controllers/adverts_controller.rb:20:in `new'
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_source.erb (8.1ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_trace.html.erb (3.0ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_request_and_response.html.erb (0.9ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/_web_console.html.erb (0.8ms)
Rendered /Users/ARTLoe/.rvm/gems/ruby-2.1.2/gems/web-console-2.0.0.beta3/lib/action_dispatch/templates/rescues/diagnostics.html.erb within rescues/layout (26.2ms)
Schema
ActiveRecord::Schema.define(version: 20150330233948) do
create_table "adverts", force: true do |t|
t.string "title"
t.text "content"
t.integer "category_jobtype_id"
t.integer "category_positiontype_id"
t.integer "salarystart"
t.integer "salaryend"
t.integer "category_country_id"
t.string "city"
t.string "town"
t.string "postcode"
t.integer "category_editorialapproval_id"
t.integer "category_applicationrequest_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "userr_id"
end
create_table "userrs", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.string "firstname"
t.string "lastname"
t.string "companyname"
t.integer "category_businesstype_id"
end
add_index "userrs", ["email"], name: "index_userrs_on_email", unique: true
add_index "userrs", ["reset_password_token"], name: "index_userrs_on_reset_password_token", unique: true
model
class Advert < ActiveRecord::Base
belongs_to :user
end
class Userr < ActiveRecord::Base
has_many :adverts
end
controller: Advert
class AdvertsController < ApplicationController
respond_to :html, :xml, :json
before_action :set_advert, only: [:show, :edit, :update, :destroy]
def index
#adverts = Advert.all
respond_with(#adverts)
end
def show
respond_with(#advert)
end
# def new
# #advert = Advert.new
# respond_with(#advert)
# end
def new
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.build
respond_with(#advert)
end
def edit
end
# def create
# #advert = Advert.new(advert_params)
# #advert.save
# respond_with(#advert)
# end
def create
#userr = Userr.find(params[:userr_id])
#advert = #userr.adverts.build(params[:advert])
if #advert.save
flash[:notice] = 'Successfully created advert'
redirect_to recruiters_path
else
render action: 'new'
end
end
def update
#advert.update(advert_params)
respond_with(#advert)
end
def destroy
#advert.destroy
respond_with(#advert)
end
private
def set_advert
#advert = Advert.find(params[:id])
end
def advert_params
params.require(:advert).permit(:title, :content, :category_jobtype_id, :category_positiontype_id, :salarystart, :salaryend, :category_country_id, :city, :town, :postcode, :category_editorialapproval_id, :category_applicationrequest_id)
end
end
form for advert
<%= simple_form_for(#advert) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title %>
<%= f.input :content %>
<%= f.association :category_jobtype, collection: CategoryJobtype.all, prompt: "select a category" %>
<%= f.association :category_positiontype, collection: CategoryPositiontype.all, prompt: "select a category" %>
<%= f.input :salarystart %>
<%= f.input :salaryend %>
<%= f.association :category_country, collection: CategoryCountry.all, prompt: "select a category" %>
<%= f.input :city %>
<%= f.input :town %>
<%= f.input :postcode %>
<%= f.association :category_editorialapproval, as: :radio_buttons %>
<%= f.association :category_applicationrequest, as: :radio_buttons %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
any help will be appreciated
First, you need to add userr_id to params:
def advert_params
params.require(:advert).permit(:userr_id, :title, :content, :category_jobtype_id, :category_positiontype_id, :salarystart, :salaryend, :category_country_id, :city, :town, :postcode, :category_editorialapproval_id, :category_applicationrequest_id)
end
Second, add userr_id to the form:
<%= simple_form_for(#advert) do |f| %>
<%= f.hidden_field(:userr_id) %>
Third, change the param name in create:
def create
#userr = Userr.find(params[:advert][:userr_id])
You can do the same via routes, without altering the form. It's much cleaner but needs more source changes. I can't give you the full syntax here, but it will look like the following:
#routes.rb
resources :userrs do
resources :addverts
end
And the advert's form will become /userrs/[user-id]/adverts, so you'll be able to get the user id from the url instead of the form field. But you'll need to change all the path shortcuts.
I have a model "votes" which belongs_to two models by polymorphous association, and has the attributes user_id and comment_id. Previously, I had a voting system in place for users that would create a new vote for a specific user every time a button was pressed:
<%= form_for [#user, #vote] do |f| %>
<input type="hidden" id="user_id" name="user_id" value="#{#user.id}" />
<%= f.submit ": )", :onclick => 'alert("Voted up!")' %>
<% end %>
and #user.votes.count would return the number of times the button was pressed. However, I switched to a different method:
View:
<%= link_to "voteuser", vote_user_path(#user.id), method: :post, :class => "btn btn-small" %>
Controller:
def vote
#user = User.find(params[:id])
Vote.create!(user_id: #user.id)
redirect_to #user
end
Routes:
Website::Application.routes.draw do
root 'home_page#home'
get "votes/new"
get 'users/random'
post 'users/vote/:id' => 'users#vote', as: 'vote_user'
get 'users/users/random' => 'users#random'
resources :users
get "all/allusers"
get "all/users/new" => 'users#new'
get 'all/all/allusers' => 'all#allusers'
end
and a Vote is still created, with a user_id equal to the current User.id, but now #user.votes.count returns 0, so the application isn't registering that the vote belongs to the user. How can I remedy this?
Vote Model:
class Vote < ActiveRecord::Base
belongs_to :voteable, polymorphic: true
end
Votes Schema:
create_table "votes", force: true do |t|
t.integer "thing_id"
t.integer "comment_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "voteable_id"
t.string "voteable_type"
end
User Model:
class User < ActiveRecord::Base
has_many :votes, as: :voteable
end
User Schema:
create_table "users", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.string "avatar_file_name"
t.string "avatar_content_type"
t.integer "avatar_file_size"
t.datetime "avatar_updated_at"
end
It should be Vote.create!(voteable_id: params[:id], voteable_type: 'User') for users or in short
Vote.create!(vote: User.find(params[:id])) # Vote.create!(vote: Comment.find(params[:id]))
check if you retrieve the user id in your controller and you can in your view
<%= form_for [#user, #vote] do |f| %>
<%= f.hidden_field :user_id, value: f.model.user.id %>
<%= f.submit ": )", :onclick => 'alert("Voted up!")' %>
<% end %>
on your controller you can simply do:
def vote
Vote.create!(user_id: params[:id])
redirect_to #user
end
but you use the polymorphous association so you have to specify the user_id and the user_type.
So i'm trying to record the number of times a link is clicked but can't get over the last hurdle.
I have the following so far:
config/routes.rb
resources :papers do
resources :articles do
resources :clicks
end
end
click.rb
class Click < ActiveRecord::Base
belongs_to :article, counter_cache: true
validates :ip_address, uniqueness: {scope: :article_id}
end
clicks_controller.rb
class ClicksController < ApplicationController
def create
#article = Article.find(params[:article_id])
#click = #article.clicks.new(ip_address: request.ip)
#click.save
end
end
article.rb
class Article < ActiveRecord::Base
has_many :clicks
end
schema.rb
create_table "clicks", force: true do |t|
t.integer "article_id"
t.string "ip_address"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "articles", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.text "title"
t.string "url"
t.integer "paper_id"
t.integer "clicks_count"
end
index.html.erb -- articles
<% #articles.each do |article| %>
<div class="articles col-md-4">
<%= link_to article.url, target: '_blank' do %>
<h4><%= article.title %></h4>
<h5><%= article.paper.name.upcase %></h5>
<h6><%= article.created_at.strftime("%d %B %y") %></h6>
<% end %>
Firstly, does this setup look correct, does anyone see where i may have gone wrong?
Secondly, what i don't know how to set up my view so that when the existing link is clicked the click is registered and the count goes up?
Thanks
Solved with the following.
clicks_controller.rb
Original:
def create
#article = Article.find(params[:article_id])
#click = #article.clicks.new(ip_address: request.ip)
#click.save
end
end
Amended:
def create
#article = Article.find(params[:article_id])
#click = #article.clicks.new(ip_address: request.ip)
#click.save
redirect_to #article.url
end
end
index.html.erb -- articles
Original:
<%= link_to article.url, target: '_blank' do %>
Amended:
<%= link_to paper_article_views_path(article.id, article), method: :post, target: '_blank' do %>
Also, i edited the original question to include the routes.rb file.
In my opinion, you should do 2 things :
1) Set all the methods for "clicks" into a Model
For example, you can remove your ClicksController and add this :
class Article
def create_click(ip_address)
self.clicks.create({ :ip_address => ip_address })
end
end
A little note with this code : you have a uniqueness validation in your code. Indeed, when a click already exists for an article and an ip address, the create method will return false. Do not use create! instead, or it will raise an exception.
2) Add a filter :
You can simply add a filter in your ArticlesController. At each show, it will create a click instance for the viewed article
class ArticlesController
before_filter :create_click, :only => [ :show ]
def create_click
#article.create_click(ip_address)
end
end
Environment: Rails 3.0.1, MySQLI have a Users table, and I want to search for users by city.
I have the following code in users_controller:
def output
#results = User.select(:fname, :lname).where(['city = ?', params[:text1]]).all
output.html.erb in View:
<% #results.each do |r| %>
<%= #r.fname %>
<%= #r.lname %>
<% end %>
It will show up as undefined method `fname' for nil:NilClass.
However, if I type following in View, it works:
your search are <%= #results %>
The output is:
your search are [#<User fname: "adam", lname: "huang">, #<User fname: "eric", lname: "huang">]
The Users table is:
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.integer :uid
t.string :email
t.string :password
t.string :fname
t.string :lname
t.string :city
t.integer :pid
t.timestamps
end
end
Try this
<% #results.each do |r| %>
<%= r.fname %>
<%= r.lname %>
<% end %>
It looks like you did a simple typo.