Duplicate two linked models Ruby - ruby-on-rails

I want to duplicate my models 'Formulaire' and 'Question'. They have a has_may/belongs_to relation.
I'm able to duplicate the first model but I have a " NoMethodError in FormulairesController#duplicate
undefined method `save' for # " when I duplicate the second
My models :
Formulaire.rb
class Question < ActiveRecord::Base
belongs_to :formulaire
validates :nom, presence: true
end
Question.rb
class Formulaire < ActiveRecord::Base
has_many :questions, dependent: :destroy
end
formulaire_controller.rb
def duplicate
template = Formulaire.find(params[:id])
#formulaire= template.dup
#formulaire.save
#for question in #formulaire.questions
# question.dup
# question.save
#end
template2 = Question.where(formulaire_id: 47)
#question = template2.dup
#question.save
redirect_to #formulaire, notice: "Formulaire dupliqué"
end
def formulaire_params
params.require(:formulaire).permit(:name, :description,
questions_attributes: [:id, :nom, :typequestion, :image, '_destroy', photos_attributes:[:id],
answers_attributes:[:id, :content,'_destroy']]) if params[:formulaire]
#puts YAML::dump params
end
My view
formulaire/show.html.erb
<li class="Dupliquer"><%= link_to 'Dupliquer', duplicate_formulaire_path(#formulaire) %> </li>
routes.rb
resources :formulaires do
member do
get 'duplicate'
end
end
Thank you

Here in stackoverflow, I found it here:
If you want to copy an activeRecord object you can use its attributes to create new one like
you can have an action in your controller which can be called on link,
def create_from_existing
#existing_post = Post.find(params[:id])
#create new object with attributes of existing record
#post = Post.new(#existing_post.attributes)
render "your_post_form"
end
what's here: Rails clone copy or duplicate
I never used this gem, but it's for this, I'm going to leave it there and you'll see what you want.
https://github.com/amoeba-rb/amoeba
And also on reddit
def clone
#location = Location.find(params[:id]).dup
............
render :new
end
link: https://www.reddit.com/r/rails/comments/6phfy4/form_how_to_implement_a_clone_action/

Related

added gem and got this error undefined method `acts_as_votable' for #<Class:0x00007f65df881b38>

baby Ruby coder here.
I followed the steps here:https://masteruby.github.io/weekly-rails/2014/08/05/how-to-add-voting-to-rails-app.html#.XMFebOhKg2w to upload this act_as_votable gem however when I refresh my site to see if it works I get the following error: undefined method `acts_as_votable' for #<Class:0x00007f65df881b38>
The code does not seem to like the fact that I have put act_as_votable in my model I would like to use it on.
The error in my console also indicates that something is wrong in my controller. Do I need to define something there too?
Thanks in advance,
Angela
Model I want to use the act_as_votable gem on, you can see i have added it as the instructions instructed:
class Hairstyle < ApplicationRecord
belongs_to :user, optional: true
has_many :comments, dependent: :destroy
validates :name, presence: true
validates :description, presence: true
validates :category, presence: true
acts_as_votable
mount_uploader :photo, PhotoUploader
end
My hairstyles controller with the 'upvote' method at the end:
class HairstylesController < ApplicationController
def index
if params[:category].present?
#hairstyles = Hairstyle.where(category: params[:category])
elsif params[:search].present?
#hairstyles = Hairstyle.where('name ILIKE ?', '%#{params[:search]}%')
else
#hairstyles = Hairstyle.all
end
end
def show
#hairstyle = Hairstyle.find(params[:id])
#comment = Comment.new
end
def new
#hairstyle = Hairstyle.new
end
def create
#hairstyle = Hairstyle.create(hairstyle_params)
#hairstyle.user = current_user
if #hairstyle.save!
redirect_to hairstyle_path(#hairstyle)
else
render 'new'
end
end
def edit
#hairstyle = Hairstyle.find(params[:id])
end
def update
#hairstyle = Hairstyle.find(params[:id])
#hairstyle.update(hairstyle_params)
redirect_to hairstyles_path
end
def destroy
#hairstyle = Hairstyle.find(params[:id])
#hairstyle.destroy
redirect_to hairstyles_path
end
def upvote
#hairstyle = Hairstyle.find(params[:id])
#hairstyle.upvote_by current_user
redirect_to hairstyles_path
end
private
def hairstyle_params
params.require(:hairstyle).permit(:name, :description, :category, :location, :stylist, :photo, :video_url, :photo_cache)
end
end
My index file i'd like to display the gem on:
<% #hairstyles.each do |hairstyle| %>
<%= link_to "upvote", like_hairstyle_path(hairstyle), method: :put%>
<%end %>
</div>
Here is my repo if needed :https://github.com/Angela-Inniss/hair-do
It looks like you didn't run all 4 setup steps:
add 'acts_as_votable' to gemfile
Then run from terminal:
bundle install
rails generate acts_as_votable:migration
rake db:migrate
I cloned & setup your repo & I saw a few things going on that might be the cause:
The original error I got in this clone was due to act_as_taggable on your models. Your models should be annotated as acts_as_taggable (plural)
When I was initially testing, I wasn't logged in. This silently fails, which makes it seem like upvote isn't work. You might want to disable those hearts unless a user is logged in
Your html/erb template has some commented out code and such. This might be causing the link/URL to get swallowed and be non-clickable. I resolved it by deleting all styling & formatting except the link I was testing. I like using Haml to help reduce these kinds of nesting errors
I didn't run into your class error, but I would suggest running spring stop and trying to start your server again (I disable spring on all of my rails projects)

Trouble setting param values in controller for form

I have a form that lets users add a new blocked tv show to their list of blocked shows. The form is not taking the param values (:user_id, :title, :image) that I tried to set in the controller. I'm a beginner, so I'm guessing the syntax is the problem.
Also I am getting a Couldn't find Tvshow without Id error when trying to use the #tvshow instance variable to set the param values of :title and :image. Each Blocked show should have the same title and image as the tvshow that the user selects in the collection_select. Is there an easier way to do this?
View
<%= form_for #blockedshow do |b| %>
<%= b.label :tvshow_id, "Add a Blocked TV Show " %><br/>
<%= collection_select(:blockedshow, :tvshow_id, Tvshow.all, :id, :title, prompt: true) %>
<%= submit_tag 'Add' %>
<% end %>
Controller
class BlockedshowsController < ApplicationController
def new
#blockedshow = Blockedshow.new
end
def create
#tvshow = Tvshow.find params[:blockedshow][:id]
#blockedshow = Blockedshow.new(safe_blockedshow)
params[:user_id] = current_user.id
params[:title] = #tvshow.title
params[:image] = #tvshow.image
if #blockedshow.save
flash[:notice] = "New Blocked TV Show added successfully"
redirect_to tv_show_index_path
else
render 'new'
end
end
private
def safe_blockedshow
params.require(:blockedshow).permit(:title, :user_id, :tvshow_id, :image)
end
end
Blockedshow model
class Blockedshow < ActiveRecord::Base
has_many :phrases
has_many :tvshows
belongs_to :user
end
Tvshow model
class Tvshow < ActiveRecord::Base
has_many :phrases
belongs_to :blockedshow
def self.search_for (query)
where('title LIKE :query', query: "%#{query}%")
end
end
Routes
resources :blockedshows
post 'blockedshows', to:'blockedshows#create#[:id]'
you are getting the issue because params[:blockedshow][:id] is not passed, if your trying to access the Tvshow id selected by from the drop-list you can do the following
#tvshow = Tvshow.find params[:blockedshow][:tvshow_id]
Just fixed by changing the controller to this:
def create
#tvshow = Tvshow.find params[:blockedshow][:tvshow_id]
#blockedshow = Blockedshow.new(
:user_id =>current_user.id,
:title=> #tvshow.title,
:image=> #tvshow.image,
:tvshow_id=>#tvshow.id
)

ActiveRecord::RecordNotFound - in a descendant class' associated_controller#index

I am attempting to locate a parent object in a nested controller, so that I can associate the descendant resource with the parent like so:
# teams_controller.rb <snippet only>
def index
#university = Univeresity.find(params[:university_id])
#teams = #university.teams
end
When I call find(params[:university_id]) per the snippet above & in line 6 of teams_controller.rb, I receive ActiveRecord::RecordNotFound - Couldn't find University without an ID.
I'm not only interested in fixing this issue, but would also enjoy a better understanding of finding objects without having to enter a University.find(1) value, since I grant Admin the privilege of adding universities.
The Rails Guides say the following about the two kinds of parameters in a website:
3 Parameters
You will probably want to access data sent in by the user or other
parameters in your controller actions. There are two kinds of
parameters possible in a web application. The first are parameters
that are sent as part of the URL, called query string parameters. The
query string is everything after “?” in the URL. The second type of
parameter is usually referred to as POST data. This information
usually comes from an HTML form which has been filled in by the user.
It’s called POST data because it can only be sent as part of an HTTP
POST request. Rails does not make any distinction between query string
parameters and POST parameters, and both are available in the params
hash in your controller:
It continues a little further down, explaining that the params hash is an instance of HashWithIndifferentAccess, which allows usage of both symbols and strings interchangeably for the keys.
From what I read above, my understanding is that Rails recognizes both parameters (URL & POST) and stores them in the same hash (params).
Can I pass the params hash into a find method in any controller action, or just the create/update actions? I'd also be interested in finding a readable/viewable resource to understand the update_attributes method thats called in a controller's 'update' action.
Please overlook the commented out code, as I am actively searching for answers as well.
Thanks in advance.
Here are the associated files and server log.
Webrick
teams_controller.rb
class TeamsController < ApplicationController
# before_filter :get_university
# before_filter :get_team
def index
#university = University.find(params[:univeristy_id])
#teams = #university.teams
end
def new
#university = University.find(params[:university_id])
#team = #university.teams.build
end
def create
#university = University.find(params[:university_id])
#team = #university.teams.build(params[:team])
if #team.save
redirect_to [#university, #team], success: 'Team created!'
else
render :new, error: 'There was an error processing your team'
end
end
def show
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
end
def edit
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
end
def update
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
if #team.update_attributes(params[:team])
redirect_to([#university, #team], success: 'Team successfully updated')
else
render(:edit, error: 'There was an error updating your team')
end
end
def destroy
#university = University.find(params[:university_id])
#team = #university.teams.find(params[:id])
#team.destroy
redirect_to university_teams_path(#university)
end
private
def get_university
#university = University.find(params[:university_id]) # can't find object without id
end
def get_team
#team = #university.teams.find(params[:id])
end
end
team.rb
class Team < ActiveRecord::Base
attr_accessible :name, :sport_type, :university_id
has_many :home_events, foreign_key: :home_team_id, class_name: 'Event'
has_many :away_events, foreign_key: :away_team_id, class_name: 'Event'
has_many :medias, as: :mediable
belongs_to :university
validates_presence_of :name, :sport_type
# scope :by_university, ->(university_id) { where(team_id: team_id).order(name: name) }
# scope :find_team, -> { Team.find_by id: id }
# scope :by_sport_type, ->(sport_type) { Team.where(sport_type: sport_type) }
# scope :with_university, joins: :teams
# def self.by_university(university_id)
# University.where(id: 1)
# University.joins(:teams).where(teams: { name: name })
# end
def self.by_university
University.where(university_id: university_id).first
end
def self.university_join
University.joins(:teams)
end
def self.by_sport_type(sport_type)
where(sport_type: sport_type)
end
def self.baseball
by_sport_type('Baseball/Softball')
end
end
university.rb
class University < ActiveRecord::Base
attr_accessible :address, :city, :name, :state, :url, :zip
has_many :teams, dependent: :destroy
validates :zip, presence: true, format: { with: /\A\d{5}(-\d+)?\z/ },
length: { minimum: 5 }
validates_presence_of :name, :address, :city, :state, :url
scope :universities, -> { University.order(name: 'ASC') }
# scope :by_teams, ->(university_id) { Team.find_by_university_id(university_id) }
# scope :team_by_university, ->(team_id) { where(team_id: team_id).order(name: name)}
def sport_type
team.sport_type
end
end
views/teams/index.html.erb
Placed in gists for formatting reasons
rake routes output: (in a public gist)
enter link description here
rails console
You're not going to want to have both:
resources :universities #lose this one
resources :universities do
resources :teams
end
As for params... you have to give a param. So, when you go to http://localhost:3000/teams there are no params, by default. If you go to http://localhost:3000/teams/3 then params[:id] = 3 and this will pull up your third team.
Keep in mind the nomenclature of an index. The index action of Teams, is going to list all of the teams. All of them. There is no one University there, so what are you actually trying to find? If anything, you'd have, for your University controller:
def show
#university = University.find(params[:id])
#teams = #university.teams
end
so, the address bar will be showing http://localhost:3000/universities/23, right? params[:id] = 23, then you can find the teams associated with that university.

Nested Form: "Cannot call create unless the parent is saved" error

I have a nested form where each post has and belongs to many locations. Adding locations to a post with the nested form works just fine. However when I click 'edit' and change anything except a location I get passed the cannot call create unless the parent is saved error.
I'm guessing this is something to do with the bit of code in my model which runs through the location_attributes being submitted and checks them for uniqueness however I have no idea how to fix this. I have tried just #post.save! before I do find_or_initialize_by_name in the controller but get the same error.
Code is below. I know this is pretty unique to me but any suggestions would be great!
posts_controller.rb
...
def update
location_set = params[:post].delete(:locations_attributes) unless params[:post][:locations_attributes].blank?
#post = Post.find(params[:id])
#post.locations = Location.find_or_initialize_location_set(location_set) unless location_set.nil?
if #post.update_attributes(params[:post])
redirect_to #post, notice: 'Blog post was successfully updated.'
else
render action: "edit"
end
end
...
location.rb (model)
include PublicActivity::Model
tracked
tracked owner: Proc.new{ |controller, model| controller.current_user }
include FriendlyId
friendly_id :name
after_save { |location| location.destroy if location.name.blank? }
after_save { |venue| venue.destroy if venue.name.blank? }
has_many :location_post, :order => "position"
has_many :posts, :through => :location_post, :order => 'location_posts.position'
attr_accessible :latitude, :longitude, :name, :post_id, :notes, :asset, :assets_attributes, :venues_attributes
attr_accessor :_destroy, :position, :location_post_id
def self.find_or_initialize_location_set(location_set)
#create a locations array
locations = []
locations = locations.delete_if { |elem| elem.flatten.empty? }
location_set.each do |key, location|
if location.delete(:_destroy) == "1"
locations.delete_if {|elem| elem[:name] == location[:name]}
else
locations << find_or_initialize_by_name(location)
#REMINDER In rails 4 this must be written as where(...).first_or_create
end
end
locations
end
*EDIT - The Error *
app/models/location.rb:10:in `block in <class:Location>'
app/controllers/blogit/posts_controller.rb:97:in `update'
This was caused by a stupid mistake.
The line after_save { |venue| venue.destroy if venue.name.blank? } is no longer relevant.
I'm an idiot and didn't read the error properly. Thanks for all those who helped.

has_many build method, Rails

Another newbie question.
The goal: each ingredient can have zero or more unit conversions tied to it. I want to put a link to creating a new unit conversion on the page that shows a specific ingredient. I can't quite get it to work.
Ingredient Model:
class Ingredient < ActiveRecord::Base
belongs_to :unit
has_many :unit_conversion
end
Unit Conversion Model:
class UnitConversion < ActiveRecord::Base
belongs_to :Ingredient
end
Unit Conversion Controller (for new)
def new
#ingredient = Ingredient.all
#unit_conversion = #ingredient.unit_conversions.build(params[:unit_conversion])
if #unit_conversion.save then
redirect_to ingredient_unit_conversion_url(#ingredient, #comment)
else
render :action => "new"
end
end
Relevant Routes:
map.resources :ingredients, :has_many => :unit_conversions
Show Ingredient Link:
<%= link_to 'Add Unit Conversion', new_ingredient_unit_conversion_path(#ingredient) %>
This is the error:
NoMethodError in Unit conversionsController#new
undefined method `unit_conversions' for #<Array:0x3fdf920>
RAILS_ROOT: C:/Users/joan/dh
Application Trace | Framework Trace | Full Trace
C:/Users/joan/dh/app/controllers/unit_conversions_controller.rb:14:in `new'
Help! I'm all mixed up about this.
Unit Conversion Controller for new and create should be:
def new
#ingredient = Ingredient.find(params[:ingredient_id])
#unit_conversion = #ingredient.unit_conversions.build
end
def create
#ingredient = Ingredient.find(params[:ingredient_id])
#unit_conversion = #ingredient.unit_conversions.build(params[:unit_conversion])
if #unit_conversion.save
flash[:notice] = "Successfully created unit conversion."
redirect_to ingredient_unit_conversions_url(#ingredient)
else
render :action => 'new'
end
end
Also, this screencast is a nice resource for nested resources.
has_many :unit_conversion
Should be pluralized since you're calling it with
#unit_conversion = #ingredient.unit_conversions.build
your controller
def new
#ingredient = Ingredient.all
should be calling #new to setup a new Ingredient or #find to grab an existing Ingredient.
#ingredient = Ingredient.new # returns a new Ingredient
or
#ingredient = Ingredient.find(...) # returns an existing Ingredient
Which one you choose is up to your requirements.
Also, this is a typo, right?
belongs_to :Ingredient
You might want to lowercase :ingredient

Resources