I am creating a website using a rails and I would like to share the model. I followed The tutorial for creating an article. In the ArticlesController is index, show, new, edit, create, update and destroy. I figured I would use this as the data entry part of my app. Then I was going to create a PageController that has home, news, videos, music and events. Here is my set up:
here is my Article model
class Article < ActiveRecord::Base
has_attached_file :image, styles: { large:"700x700>", medium:"300x300>", thumb:"150x150#"}
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
validates :title, presence: true,
length: { minimum: 5 }
belongs_to :page
end
here is my page model
class Page < ActiveRecord::Base
has_many :article
end
here is my page controller
class PageController < ApplicationController
def home
#page = Page.includes(:articles)
end
def news
end
def videos
end
def music
end
def events
end
end
here is my home view
<h1>Page#home</h1>
<p>Find me in app/views/page/home.html.erb</p>
<%= #page.articles.each do |article| %>
<%= article.title %>
<%= article.content %>
<%= article.image %>
<% end %>
here is the error I get
undefined method `articles' for #<ActiveRecord::Relation []>
not clear onwhats going on. Any help would be appreciated
From the limited information you posted, I am assuming the best thing for you to do is create an association. Pages should has_many articles and articles should belong_to a page. http://guides.rubyonrails.org/association_basics.html
After that is setup, your controller can be set up as follows:
#page = Page.includes(:articles)
This will load your pages and its related articles in a single SQL query, then you can call
#page.articles.each |article|
puts article.title
puts article.content
puts article.image
end
You can now access all the information and use it as you please.
Related
I'm using the sign-up and login that we built with the rails tutorial as a base for a Reddit clone that I’m making. As it stands the application is functioning properly apart from the user_id in comments table is blank when I make a comment, the link_id is present and correct so I can make comments on a link. The user_id in links table is also present and correct.
I'm fairly certain that the error i've made is in the create action of comments_controller.rb but it could also be my original migration. What's confusing me (as a novice) is I had this working in it's current form once before with rails 4.1.8 and device. However, using this approach with rails 4.2.1 using the rails tutorial as a base, it doesn't work. I'm a bit new here so I hope i've formulated the post correctly and given enough information so somebody could give me some pointers as to the problem
Comment Controller
before_action :logged_in_user, only: [:create, :destroy]
def create
#link = Link.find(params[:link_id])
#comment = #link.comments.create(params[:comment].permit(:link_id, :body))
#comment.user = User.find(current_user.id)
redirect_to link_path(#link)
end
def destroy
#link = Link.find(params[:link_id])
#comment = #link.comments.find(params[:id])
#comment.destroy
redirect_to link_path(#link)
end
private
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
Form
app/views/links/show.html.erb
<h2 class="comment-count"><%= pluralize(#link.comments.count, "comment") %></h2>
<%= render #link.comments %>
<%= form_for([#link, #link.comments.build]) do |f| %>
<%= render 'comments/fields', f: f %>
<%= f.submit "Save Comment", class: 'btn btn-primary margin-bottom-10' %>
<% end %>
Partials
app/views/comments/_comment.html.erb
<p class="comment_body"><%= comment.body %></p>
<p class="comment_time"><%= time_ago_in_words(comment.created_at) %> Ago </p>
app/views/comments/_fields.html.erb
<%= render 'shared/comment_error_messages' %>
<%= f.label :body %>
<%= f.text_area :body, class: 'form-control' %>
Routes
config/routes.rb
resources :links do
member do
put "like", to: "links#upvote"
put "dislike", to: "links#downvote"
end
resources :comments
end
Models
app/models/link.rb
belongs_to :user
has_many :comments, dependent: :destroy
app/models/comment.rb
belongs_to :user
belongs_to :link
validates :body, presence: true
app/models/user.rb
has_many :links, dependent: :destroy
Migration
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.integer :link_id
t.text :body
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
add_index :comments, :link_id
end
end
Hopefully that’s a good enough post and I’ve included everything you need so somebody can help me out, It's a rookie error but i can't see it. thanks in advance.
Regards
As it stands, you are currently creating a comment without saving user_id for it. Try the below code
#comments_controller.rb
def create
#link = Link.find(params[:link_id])
#comment = #link.comments.new(params[:comment].permit(:link_id, :body))
#comment.user = User.find(current_user.id)
#comment.save
redirect_to link_path(#link)
end
I want to put a search form on my homepage at pages#home. I'd like to be able to search my model by category. I haven't been able to find a solution where you're actually putting the logic on a different controller than the models you're searching on. I was wondering if someone could help with the syntax and where it needs to go. Here are my relations:
vendor.rb
class Vendor < ActiveRecord::Base
validates :category_id, presence: true
belongs_to :category
end
category.rb
class Category < ActiveRecord::Base
has_one :vendor
end
pages_controller.rb
def home
#vendors = Vendor.all
end
routes.rb
root 'pages#home'
I'm trying to put the search form on home.html.erb, which is under the pages layouts. Was hoping someone could help with how I can accomplish this. This being (seemingly) a simple type of search, I'd hopefully not have to use a gem.
EDIT: ANSWER
For those searching, here's what worked. Thank you #Vla
vendors_controller.rb
def search
#vendors = Vendor.search(params)
end
pages/home.html.erb (this is my root 'pages#home')
<%= form_tag vendors_search_path, method: :get do |f| %>
<%= text_field_tag :search, params[:search], placeholder: "Search Vendors" %>
<%= select_tag 'category', options_for_select(Category.all.map{|el| [el.name, el.id]}) %>
<%= submit_tag 'Search' %>
<% end %>
routes.rb (make sure to put this near the top)
get 'vendors/search'
vendors/search.html.erb
<% #vendors.each do |vendor| %>
<%= vendor.name %>
<%= vendor.phone %>
<%= vendor.email %>
<% end %>
Ok, You can do it this way:
Go to Your vendor.rb file and add search method like this:
def self.search params
vendors = Vendor.where(category_id: params[:category].to_i) unless params[:category].blank?
vendors
end
Then in Your vendors_controller create search method:
def search
#vendors = Vendor.search(params)
end
Then create form at homepage similar to:
= form_tag search_vendors_path, method: :get, role: 'form' do
.form-group
%label Category
= select_tag 'category', options_for_select(Category.all.map{|el| [el.name, el.id]}), class: 'form-control'
= submit_tag 'Search'
And do not forget to put
get 'vendors/search'
into Your routes and add "search" view.
You can still do the same without search action, with result on Your homepage. Anyway I hope You got the idea.
I'm building a training website where I'm trying to generate dynamic routes for content based on the content title, which is a column in the database. I got pretty far, but I'm having issues with the last part.
Let's say that the content title is "Business Travel," i.e. a training course on business travel. With the code shown below, the link_to helper method in the template generates the link like this:
http://localhost:3000/courses/Business Travel
What I need is for the words to be separated by dashes, like how Stack Overflow question URLs are formatted.
Is there a built-in method for this? Or do I have to write a helper function that manipulates the content object's title property into something URL-friendly? Or... am I doing this completely the wrong way?
contentcontroller.rb
class ContentController < ApplicationController
before_action :signed_in_user
def tracks
end
def courses
#courses = Content.all
end
def show
#course = Content.find_by_title(params[:title])
end
end
content.rb
class Content < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
end
courses.html.erb
<% provide(:title, 'Tracks') %>
<div class="container">
<% #courses.each do |course| %>
<div class="row">
<%= link_to course_path(course.title) do %>
<div class="col-md-12 course-box content-link centertext">
<strong><%= course.title %></strong>
<p><%= course.description %></p>
</div>
<% end %>
</div>
<% end %>
</div>
routes.rb
match '/courses/:title', to: 'content#show', via: 'get', as: 'course'
Essentially what you are looking for is slugged url. Have a look at friendly_id gem
https://github.com/norman/friendly_id
It's super easy to get started. Look under Rails Quickstart section and that should get you up to speed.
For your convenience.
In your Gemfile
gem 'friendly_id'
Run the following commands in your terminal
rails generate friendly_id
rails generate migration add_slug_to_content slug:string
Edit your generated migration file to include
add_index :contents, :slug, unique: true
Run the rake migration
rake db:migrate
Add the following to your content class
class Content < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
validates :title, presence: true
validates :description, presence: true
end
That should automatically take care of converting the URL to model id for you :)
I am a newbie to Ruby on Rails and have scoured Stackoverflow and the internet to the best of my abilities and am still stumped.
In my set-up, a Rating belongs_to a Product and has_many Comments. I'm using simple-form and trying to use nested fields_for to add RatingComment through the Rating form. Interestingly, when using the singular form of :rating_comment, the field is displayed. But as expected, I get the unpermitted parameter error when trying to save. When I use plural :rating_comments, the field disappears. This is similar to this SO posting, but adding #rating.rating_comments.build to new action still does not work for me. I've tried restarting the server many times, and even reset the database to no avail. Would appreciate any assistance as I've been struggling with this issue for the past few days.
Note: I've also taken out what I think is irrelevant code from the snippets below. If I need to show more information, please do let me know. Thanks in advance!
routes.rb
resources :ratings, only: [:new, :create, :edit, :update, :destroy] do
resources :rating_comments, shallow: true
end
rating.rb
class Rating < ActiveRecord::Base
belongs_to :product
belongs_to :user
has_many :rating_comments, foreign_key: "rating_id", dependent: :destroy
accepts_nested_attributes_for :rating_comments, reject_if: :all_blank
end
rating_comment.rb
class RatingComment < ActiveRecord::Base
belongs_to :rating
validates :rating_id, presence: true
end
ratings_controller.rb
class RatingsController < ApplicationController
before_action :signed_in_user, only: [:create, :new, :show]
def new
#product = Product.find(params[:id])
#rating = #product.ratings.new
#rating.rating_comments.build
end
def create
#product = Product.find(params[:product_id])
#rating = #product.ratings.build(rating_params)
#rating.user_id = current_user.id
...
private
def rating_params
params.require(:rating).permit(:user_id, :product_id, :rating, rating_comments_attributes: [:rating_id, :content])
end
end
ratings/_new_rating_form.html.erb
<%= simple_form_for([#product, #rating], html: { class: 'form-horizontal' }) do |f| %>
<%= f.error_notification %>
<%= f.input :rating, collection: 1..10, as: :radio_buttons,
item_wrapper_class: 'inline', checked: 5 %>
<%= f.simple_fields_for :rating_comments do |rc| %>
<fieldset>
<%= rc.input :content, label: "Comments" %>
</fieldset>
<% end %>
<%= f.error :base %>
<%= f.button :submit, "Submit" %>
<% end %>
Very embarrassed to admit that it turns out that I had the view written in the wrong action. Once I put it in the new.html, it finally worked.
I have two associated models in my Rails 4 app: product.rb and image.rb. The Image model allows attached files using the Paperclip gem.
Images belong_to a Product, and a product has_many Images.
I would like to use the Product's new view to create and attach an image when I create a product. Each time I try, the parameters associated with the Paperclip image do not get saved, and end up nil.
Here are the models:
Product.rb
class Product < ActiveRecord::Base
validates :name, :part_number, presence: true
has_many :images, dependent: :destroy
belongs_to :category
accepts_nested_attributes_for :images, allow_destroy: true
end
Image.rb
class Image < ActiveRecord::Base
belongs_to :product
has_attached_file :image
end
Looking through past Stack Overflow questions I've found some relevant questions and answers, but none that seem to help my particular situation. So far I'm able to submit the file with the correct attributes, but it doesn't save them to the database.
ProductsController#create
def create
#product = Product.new(product_params)
end
def product_params
params.require(:product).permit(:name,
:category_id,
:part_number,
images_attributes: [:image])
end
ProductsController#new
def new
#product = Product.new
#categories = # irrelevant to question
end
products/new.html.haml
= form_for #product, :html =>
= f.label :name
= f.text_field :name
= f.label :part_number
= f.text_field :part_number
= f.label :category_id
= f.select :category_id, #ca
= f.fields_for :image do |ff|
= ff.label :image
= ff.file_field :image
= f.submit('Create Product')
Looking at the parameters I can tell that the correct attributes are being passed on:
Example parameters:
{"utf8"=>"✓",
"authenticity_token"=>"jGNy/TasHzP0EcWDFzZ3XH5/fpxb6vD+ncQ2PZSQ3/I=",
"product"=>{"name"=>"bar",
"part_number"=>"foo",
"category_id"=>"30",
"image"=>{
"image"=>#<ActionDispatch::Http::UploadedFile:0x007fc82f58e0e0
#tempfile=#<Tempfile:/var/folders/04/23d9grkj5fv3wkj2t8858kx40000gn/T/RackMultipart20131029-64949-1ldkz4g>,
#original_filename="FPE230_b.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"product[image][image]\"; filename=\"FPE230_b.jpg\"\r\nContent-Type: image/jpeg\r\n">}},
"commit"=>"Create Product"}
However, the image is not actually being saved to the database. How can I rectify this?
EDIT
Looking more closely at the logs, I see that I'm getting an "unpermitted parameters: image" error. This is even after adding images_attributes: [:image] to my product_params method.
I was able to get a setup similar to yours working with the following changes:
In ProductsController#create, instead of building the image separately, let the nested attributes handle it and just do:
#product = Product.new(product_params)
And allow the nested parameters (I figured out the image_attributes: [:image] from this question):
def product_params
params.require(:product).permit(:name, :part_number, images_attributes: [:image])
end
This is what my parameters look like in the logs for a create request:
{
"utf8"=>"✓",
"authenticity_token"=>"7EsPTNXu127itgp4fbohu672/L4XnSwLEkrqUGec3pY=",
"product"=>{
"name"=>"whatever",
"part_number"=>"12345",
"images_attributes"=>{
"0"=>{
"image"=>#<ActionDispatch::Http::UploadedFile:0x007feb0c183b08
#tempfile=#<Tempfile:/var/folders/6k/16k80dds0ddd6mhvs5zryh3r0000gn/T/RackMultipart20131031-51205-emaijs>,
#original_filename="some-image.png",
#content_type="image/png",
#headers="Content-Disposition: form-data; name=\"product[images_attributes][0][image]\"; filename=\"ponysay.png\"\r\nContent-Type: image/png\r\n">
}
}
},
"commit"=>"Create"}
And I see an insert into products and an insert into images.
If that doesn't work, could you post your ProductsController#new and your new product form?
EDIT AFTER YOUR EDIT:
I have 3 different things in my app/views/products/new.html.erb and ProductsController#new that might be affecting your results:
In the form_for, I have multipart: true as in the paperclip documentation:
<%= form_for #product, :url => products_path, :html => { :multipart => true } do |f| %>
Because Product has_many :images, in my form I have fields_for :images instead of fields_for :image:
<%= f.fields_for :images do |i| %>
<%= i.file_field :image %>
<% end %>
This fields_for doesn't show anything on the page unless in the ProductsController#new I build an image; does your Product.new do this by any chance?
def new
#product = Product.new
#product.images.build
end
Are there any particular reasons for these differences you have? Does your code work if you change it to match mine?