For my application, I have Users, who can Create Project Postings. On each Project Posting, they can make comments that I have made a Blogupdate model. I want users to be able to like Blogupdates made on each Project page.
So, I created a Bloglike model. But when I try to render a LIKE/UNLIKE button, I get the following error:
NoMethodError in Projects#blogs
undefined method `bloglikes_path'
Extracted source (around line #11):
11: <%= form_for(current_user.bloglikes.build(blogupdate_id: blogupdate.id)) do |f| %>
Question: As a note, I have not built up the controller for the actual create/destroy function in my bloglikes controller; but looking at my attached code below, does somebody know how I can resolve this error so the like/unfollow button renders?
schema.rb
create_table "bloglikes", :force => true do |t|
t.integer "user_id"
t.integer "blogupdate_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "bloglikes", ["blogupdate_id"], :name => "index_bloglikes_on_blogupdate_id"
add_index "bloglikes", ["user_id", "blogupdate_id"], :name => "index_bloglikes_on_user_id_and_blogupdate_id", :unique => true
add_index "bloglikes", ["user_id"], :name => "index_bloglikes_on_user_id"
user.rb
has_many :bloglikes, foreign_key: "user_id"
has_many :liked_blogupdates, through: :bloglikes, source: :blogupdate
blogupdate.rb
has_many :bloglikes, foreign_key: "blogupdate_id"
has_many :liked_by, through: :bloglikes, source: :user
def liking_blogupdate?(blogupdate)
bloglikes.find_by_blogupdate_id(blogupdate.id)
end
def like_blogupdate!(blogupdate)
bloglikes.create!(blogupdate_id: blogupdate.id)
end
def blogupdate_unlike!(blogupdate)
bloglikes.find_by_blogupdate_id(blogupdate.id).destroy
end
bloglike.rb
class Bloglike < ActiveRecord::Base
attr_accessible :blogupdate_id
belongs_to :user, foreign_key: "user_id"
belongs_to :blogupdate, foreign_key: "blogupdate_id"
end
projects_controller.rb
def blogs
#project = Project.find(params[:id])
#blogupdates = #project.blogupdates.newest.page(params[:blogupdates_page]).per_page(5)
end
views/projects/blogs.html.erb
<%= render 'blogs' %>
views/projects/_blogs.html.erb
<%= render #blogupdates %>
views/blogupdates/_blogupdates.html.erb
<%= blogupdate.liked_by.count %>
<% if current_user.liking_blogupdate?(blogupdate) %>
<%= form_for(current_user.bloglikes.find_by_blogupdate_id(blogupdate),
html: { method: :delete }) do |f| %>
<%= f.submit "UNLIKE", class: "btn btn-medium" %>
<% end %>
<% else %>
<%= form_for(current_user.bloglikes.build(blogupdate_id: blogupdate.id)) do |f| %>
<div><%= f.hidden_field :blogupdate_id %></div>
<%= f.submit "LIKE", class: "btn btn-medium btn-primary" %>
<% end %>
<% end %>
<p><%= raw blogupdate.content %></p>
UPDATE: As noted below by #Dan, I forgot to update the routes.rb file. I added "resources :bloglikes" and it worked now.
You didn't post your routes.rb file but I'd wager that is where the problem is at. An undefined method related to routes (e.g. bloglikes_path) typically indicates you've not defined the routes.
Add resources :bloglikes to your project's routes.rb file and see if that resolves the issue.
Related
I want to get data like this in the show.html.erb , but it doesn't work.
How can I get data from spot table?
here is the code.
show.html.erb
<% #planaction.each do |action| %>
<hr>
<%= action.spot.name %>
<%= action.spot.description %>
<hr>
<%= action.title %>
<%= action.experience %>
<% end %>
plan.rb
class Plan < ActiveRecord::Base
has_many :plan_actions
end
plan_action.rb
class PlanAction < ActiveRecord::Base
belongs_to :plan
has_one :spot
end
spot.rb
class Spot < ActiveRecord::Base
belongs_to :plan_action
end
plan_actions_controller.erb
class PlanPagesController < ApplicationController
def show
#plan = Plan.find(params[:id])
#planaction = #plan.plan_actions
end
end
and error message here
undefined method `name' for nil:NilClass
and here is migration file for spot table.
class CreateSpots < ActiveRecord::Migration
def change
create_table :spots do |t|
t.integer :spot_id
t.integer :plan_action_id
t.string :name
t.text :description
t.time :time_open
t.time :time_close
t.date :dayoff
t.string :address
t.integer :tel
t.string :image
t.string :image2
t.string :image3
t.timestamps null: false
end
end
end
Looks good to me.
The issue is probably (can't be certain without seeing your logs) that the plan_action doesn't have an associated spot record.
To fix this, you should use some conditional logic:
<% #planaction.each do |action| %>
<hr>
<% if action.spot %>
<%= action.spot.name %>
<%= action.spot.description %>
<hr>
<% end %>
<%= action.title %>
<%= action.experience %>
<% end %>
Again, this is speculation. I wrote the answer because I felt it best to provide some sort of idea as to how to resolve it. The above should work.
I also think as Rich Peck that you don't have a record in spots table with plan_action_id corresponding to a plan action.
Following rails convention, I suggest the following:
class PlanAction < ActiveRecord::Base
belongs_to :plan
has_one :spot
delegate :name, :description, to: :spot, prefix: true, allow_nil: true
end
and in your view:
<%= action.spot_name %>
<%= action.spot_description %>
Finally, get your validations corrected. For example, if a plan_action should have a spot, then you need to use nested forms for both spot and plan action.
I'm using Closure tree idea in my new website.
In one of the show views I want to select data by the id (1-level descendant) or if the id is null the first level.
How do I connect sql with set result?
The Query:
select id,name
from tags t
join tag_hierarchies th (t.id = th.ancestor_id)
where t.id=nvl(?,0) and th.generations=1
Code so far(problem on app/views/show.erb):
db/schema.rb:
create_table "tags" do |t|
t.string "name", :null=>false
t.boolean "isCat", :default => true
end
create_table "tag_hierarchies", :id => false do |t|
t.integer "ancestor_id", :null => true
t.integer "descendant_id", :null => false
t.integer "generations", :null => false
end
add_foreign_key(:tag_hierarchies, :tags, :column => 'ancestor_id')
add_foreign_key(:tag_hierarchies, :tags, :column => 'descendant_id')
app/models/tag.rb
class Tag < ActiveRecord::Base
#attr_accessible :name, :isCat
validates :name, uniqueness: false, allow_blank: false
end
app/models/Tag_Hierarchie.rb
class TagHierarchie < ActiveRecord::Base
#attr_accessible :ancestor_id, :descendant_id, :generations
end
app/views/show.erb
<% provide(:title, category_name_or_constant(#tags)) %>
<h1><%= category_name_or_constant(#tags)%></h1>
<div class="row">
<div class="span6 offset3">
<%= for(<<here goes the sql by the Closure tree >>) do |f| %>
<%= link_to tag.name, tag %>
<% end %>
</div>
</div>
Add static method (or scope, if you prefer) to your Tag model:
app/models/tag_hierarchy.rb
class TagHierarchy
belongs_to :tag, foreign_key: :ancestor_id
end
app/models/tag.rb
class Tag
has_many :tag_hierarchies, foreign_key: :ancestor_id
def self.descendants(id = nil)
id ||= 0
self.where(id: id).joins(:tag_hierarchies).where(tag_hierarchies: {generations: 1})
end
end
Create a controller:
rake g controller TagsController
Add code to your controller:
app/controllers/tags_controller.rb
class TagsController < ApplicationController
def index
#descendants = Tag.descendants
end
def show
#descendants = Tag.descendants(params[:id])
end
end
Then use all the stuff in your views:
app/views/tags/show.html.erb:
<div class="row">
<div class="span6 offset3">
<%= #descendants.each do |tag| %>
<%= link_to tag.name, tag %>
<%# you can also use tag.tag_hierarchies here %>
<% end %>
</div>
</div>
I suggest you read some tutorials and/or docs on Rails:
Active Record Associations
Rails Routing from the Outside In
Getting Started with Rails
I am trying to create a profile page where I can input "born_on". It will be using the
class CreateWineMakers < ActiveRecord::Migration
def change
create_table :wine_makers do |t|
t.string :name
t.date :born_on
t.text :nationality
t.text :profile
t.text :wine
t.integer :wine_list_id
t.timestamps
end
add_index :wine_makers, :wine_list_id
end
end
Here is my view file.
<%= simple_form_for WineMaker.new do |f| %>
<%= f.input :name %>
<%= f.input :profile %>
<%= f.input :wine %>
<%= f.input :born_on %>
<br/>
<%= f.submit "Create", :class => 'btn btn-primary' %>
<% end %>
The "born_on" is giving me error saying the method is not defined. I am confused since all other inputs are working except "born_on" and "nationality". Before, my "born_on" was named "birth_date", and I thought the naming convention was wrong and changed it to "born_on". Here is the controller.
class WineMakersController < ApplicationController
def new
#wine_maker = WineMaker.new
end
def create
#wine_maker = WineMaker.create(wine_maker_params)
redirect_to wine_list_path(#wine_list)
end
def show
end
private
def wine_maker_params
params.require(:wine_maker).permit(:name, :born_on, :nationality, :profile, :wine )
end
end
This seems like such an easy question that I couldn't find similar problems..
Thank you.
Attempting to add data to a join table of scrapbook_entries which has_one :scrapbook and has_one :recipe.
:recipe and :scrapbook already exist. I am trying to add them to link them with the scrapbook_entries table.
form_for adding to scrapbook_entries table:
<%= form_for(#scrapbook_entry, :url => scrapbook_entries_path(params[:id])) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%=f.select(:scrapbook_id, current_user.scrapbooks.collect {|p| [ p.name, p.id ] }, {prompt: 'Select Scrapbook...'})%>
<%= f.hidden_field :recipe_id, :value => #recipe.id %>
</div>
<%= f.submit "Save", class: "btn btn-large btn-primary" %>
<% end %>
scrapbook_entries_controller:
def create
#recipe = Recipe.find(params[:scrapbook_entry][:recipe_id])
#scrapbook = current_user.scrapbooks.find(params[:scrapbook_entry][:scrapbook_id])
#entry = #scrapbook.scrapbook_entries.build(scrapbook: #scrapbook)
if #entry.save
flash[:success] = "Added '#{#recipe.name}' to scrapbook '#{#scrapbook.name}'"
else
flash[:error] = "Could not add to scrapbook"
end
redirect_to #recipe
end
scrapbook.rb
has_many :recipes, through: :scrapbook_entries
has_many :scrapbook_entries
recipe.rb
has_many :scrapbooks, through: :scrapbook_entries
scrapbook_entry.rb
has_one :recipe
has_one :scrapbook
On submitting the form to the controller I am getting a error:
can't write unknown attribute `scrapbook_entry_id'
Can anyone tell me what I am doing wrong?
Update:
schema.rb
create_table "scrapbook_entries", force: true do |t|
t.integer "scrapbook_id"
t.integer "recipe_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
end
Your scrapbook_entr.rb should contain
belongs_to :recipe
belongs_to :scrapbook
and not has_one!
You always use belongs_to when your table contains a foreign key to another table, which in this case definitely is the case!
I am working on building an application (following Michael Hartl's chapter 11) where users can follow projects that are created by other users.
I created a ProjectRelationship model to hold two components: follower_id for the users and projectuser_id for the projects. The foreign keys have been set up as such.
Right now, my _follow_form.html.erb page renders "follow" or "unfollow" depending on whether the current_user is following the project. Please see my code below and see what I am missing.
Right now, the follow button is generated on each project show page. But when I click the button follow button that is generated by _follow.html.erb, it does not seem to follow the project or update the count when I call #project.followers.count as the POST is not happening.
And thus, when I click follow button, the URL becomes all jumbled. See example:
#Goes from
domain.com/projects/21
#to
domain.com/projects/21?utf8=%E2%9C%93&authenticity_token=5EQmU0EkHB5yKDYakqL78piMWzZl0CfdpHFEqBeQiN4%3D&project_relationship%5Bprojectuser_id%5D=21&commit=Follow%22
**Update:
It seems to work now, but I'm not sure if I really changed anything but got rid of the follower_id index :unique => true through a migration change.
schema.rb
create_table "project_relationships", :force => true do |t|
t.integer "follower_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "projectuser_id"
end
add_index "project_relationships", ["follower_id"], :name => "index_project_relationships_on_follower_id", :unique => true
add_index "project_relationships", ["projectuser_id"], :name => "index_project_relationships_on_projectuser_id"
routes.rb
resources :projects do
resources :comments
member do
get :following
end
end
resources :project_relationships, only: [:create, :destroy]
project_relationship.rb
class ProjectRelationship < ActiveRecord::Base
attr_accessible :projectuser_id
belongs_to :user, foreign_key: "follower_id"
belongs_to :project, foreign_key: "projectuser_id"
end
project.rb
has_many :project_relationships, foreign_key: "projectuser_id"
has_many :favorited_by, through: :project_relationships, source: :user
user.rb
has_many :project_relationships, foreign_key: "follower_id"
has_many :followed_projects, through: :project_relationships, source: :project
def following_project?(project)
project_relationships.find_by_follower_id(project.id)
end
def follow_project!(project)
project_relationships.create!(projectuser_id: project.id)
end
def project_unfollow!(project)
project_relationships.find_by_projectuser_id(project.id).destroy
end
project_relationships_controller.rb
class ProjectRelationshipsController < ApplicationController
def create
#project = Project.find(params[:project_relationship][:projectuser_id])
current_user.follow_project!(#project)
redirect_to #project
end
def destroy
#project = ProjectRelationship.find(params[:id]).followed_project
current_user.project_unfollow!(#project)
redirect_to #project
end
end
projects/show.html.erb
<%= render 'follow_form' if signed_in? %>
projects/_follow_form.html.erb
<% if current_user.following_project?(#project) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
projects/_follow.html.erb
<%= form_for(current_user.project_relationships.build(projectuser_id: #project.id)) do |f| %>
<div><%= f.hidden_field :projectuser_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
projects/_unfollow.html.erb
<%= form_for(current_user.project_relationships.find_by_projectuser_id(#project),
html: { method: :delete }) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
First of all - if you run projectfollow!(project) and projectunfollow!(project) in your console (with a user, project etc) do they work properly?
For your forms try the following instead and see if it works:
<%= form_for(current_user.project_relationships.build, url: project_relationships_path(project_id: #project.id)) do |f| %>
Then in your project relationships controller:
class ProjectRelationshipsController < ApplicationController
def create
#project = Project.find(params[:project_id])
current_user.projectfollow!(#project)
redirect_to #project
end
end
So if your create URL is /project_relationships (via POST), the above should post to /project_relationships?project_id=5 and then the controller can find that project.
Also, try to rename your methods so they make sense:
def following_project?(project)
end
def follow_project!(project)
end
def unfollow_project!(project)
end
Now current_user.following_project?(project) makes a lot of sense!
Update
Ok, I think the following is the problem, in your create action you're getting the id from the params:
#project = Project.find(params[:project_relationship][:projectuser_id])
However in your form you're not setting the value of the hidden field:
<%= f.hidden_field :projectuser_id %>
Change it to the following and see if it works:
<%= f.hidden_field :projectuser_id, value: #project.id %> # or wherever the id is from
The problem was that my follow/unfollow form was embedded in another form which caused the error. Once taken out, worked!