So I have a flow model and a page model
Each flow has_many pages and each page belongs_to a flow
Flow model
class Flow < ActiveRecord::Base
has_many :pages, :dependent => :destroy
accepts_nested_attributes_for :pages, :reject_if => lambda { |p| p[:path].blank?}, :allow_destroy => true
end
Page model
class Page < ActiveRecord::Base
belongs_to :flow
end
Then in the new flow action I have this
def new
#flow = Flow.new
3.times do
page = #flow.pages.build
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #flow }
end
end
but I keep getting the error: "unknown attribute: flow_id"?
Use generate migration add_flow_id_to_page flow_id:integer to generate the foreign key column.
Related
I add unique index, but record dont save, validation error. I need update tags in my post,existing tags adding to tags with new id, but I need existing tags not to be added
class Tag < ApplicationRecord
has_many :tags_posts
has_many :tags, through: :tags_posts
accepts_nested_attributes_for :tags_posts, :allow_destroy => true, :update_only=>true
end
class TagsPost < ApplicationRecord
belongs_to :post
belongs_to :tag
accepts_nested_attributes_for :tag, :allow_destroy => true, :update_only=>true
end
controller code:
def update
#resource=resource_class.find(params[:id])
#resource.assign_attributes(resource_params)
if #resource.save
render json: #resource.as_json(as_json_resource)
else
render json: {errors:#resource.errors}, status: :unprocessable_entity
end
end
def resource_class
Post
end
def resource_params
params.require(:post).permit(:user_id,:title,:category_id, :content, :date_of_publication, tags_posts_attributes: [tag_attributes: [:name]] )
end
Add id to tag_attributes
params.require(:post).permit(:user_id,..., tags_posts_attributes: [tag_attributes: [:id, :name]] )
That will prevent it from adding again.
I have a very basic example
app/models/user.rb
#name string
class User < ActiveRecord::Base
has_one :project,dependent: :destroy
validates :name,presence: true
validates_associated :project
accepts_nested_attributes_for :project
end
app/models/project.rb
#name string
#user_id integer
class Project < ActiveRecord::Base
belongs_to :user
has_many :tasks,dependent: :destroy
validates :name,presence: true
validates_associated :tasks
accepts_nested_attributes_for :tasks
end
app/models/tasks.rb
#name string
#project_id integer
class Task < ActiveRecord::Base
belongs_to :project,dependent: :destroy
validates :name,presence: true
end
That's all I have in model
On the Controller end for testing purpose, I have the following code.
app/controllers/users_controller.rb
def update
#user.project_attributes = {:name => "P#rand(100)",:tasks_attributes => [{name: "Task#{rand(100)}"}]}
respond_to do |format|
if #user.save
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
Every time, I try to update a given User, I run into stack level too deep
problem
Any Clue?
Note :
Rails version 4.0.4
Ruby 2.1.2p95
Write dependent: :destroy only in one of models that share an association. If both models have dependent: :destroy in 'em, it goes for an infinite number of calls causing Stack level too deep error to occur.
I am getting the following Active Record Association error when trying to join two tables (with a polymorphic relationship) and include all data from both tables in a JSON API response:
Association named 'categories' was not found; perhaps you misspelled it?
Here is the controller action that I am trying to call:
def index
#items = Item.includes(:categories)
respond_to do |format|
format.json { render :json => #items.to_json }
end
end
And here are the two models that I am trying to join:
class Category < ActiveRecord::Base
attr_accessible :name
has_many :items, :as => :linkable
end
class Item < ActiveRecord::Base
attr_accessible :due_date, :linkable_id, :linkable_type, ...
belongs_to :linkable, :polymorphic => true, :counter_cache => true
end
Specifically, I want to return each Item in the database along with its Category. I have tried everything that I can think of. Any help will be greatly appreciated.
Have you tried :
def index
#items = Item.includes(:linkable).where(:linkable_type => 'Category')
respond_to do |format|
format.json { render :json => #items.to_json(include: :linkable) }
end
end
The name of your association is actually :linkable for the Item model, and not :categories (especially because it's a belongs_to so it would be :category).
I'm having a problem based on the excellent RailsCast #258 from Ryan Bates.
The situation is as follows:
class User < ActiveRecord::Base
has_many :capabilities,
:dependent => :destroy
has_many :skills, :through => :capabilities,
:uniq => true
has_many :raters,
:through => :capabilities,
:foreign_key => :rater_id,
:uniq => true
attr_accessible :name, :skill_tokens
attr_reader :skill_tokens
def skill_tokens=(tokens)
self.skill_ids = Skill.ids_from_tokens(tokens)
end
end
class Capability < ActiveRecord::Base
belongs_to :user
belongs_to :rater, class_name: "User"
belongs_to :skill
validates_uniqueness_of :rater_id, :scope => [:user_id, :skill_id]
end
class Skill < ActiveRecord::Base
has_many :capabilities
has_many :users, :through => :capabilities,
:uniq => true
has_many :raters, :through => :capabilities,
:foreign_key => :rater_id
end
The form contains a normal textfield for the skill tokens which are passed as ids:
.field
= f.label :skill_tokens, "Skills"
= f.text_field :skill_tokens, data: {load: #user.skills}
So a user can get many skills assigned through capabilities. While assigning the skill, the rater should also be tracked in the capability model.
Using Ryans example of jquery TokenInput I created an appropriate form to allow a user to assign (and create) skills using a tokenInput text field.
The Problem lies now in processing the data and setting the rater before the association is saved.
Through some ruby magic, self.skill_ids on the user model sets the ids used for the association model creation so the controller action is quite simple:
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
Obviously, if I want to set the additional rater attribute on the capability model it won't work so easily with update_attributes.
So how can I achieve this with "the rails way" to do it - writing beautiful, readable code?
ANY help would be greately appreciated!
How are you setting the rater_id?
If you plan accept a user input for the rater for each skill the user adds on the form,
I can't see how you'll be able to use input fields based on token inputs to achieve this. You're going to have to choose some other types of inputs.
If you plan to set the rater to the currently logged in user, or are setting the rater based on some other business logic, my approach would be overwriting the skill_ids= method in the User model to work how you want it, adding an attr_accessor to store the current_rater and passing the current_rate from the controller.
Something like:
#user.rb
attr_accessor :current_rater
def skill_ids=(ids)
return false if current_rater.nil? || User.find_by_id(current_rater).nil?
capabilities.where("skill_id not in (?)", ids).destroy_all
ids.each do |skill_id|
capabilities.create(:skill_id => skill_id, :rater_id => self.current_rater) if capabilities.find_by_id(skill_id).nil?
end
end
#users_controller.rb
def update
#user = User.find(params[:id])
#Replace 'current_user' with whatever method you are using to track the logged in user
params[:user].merge(:current_rater => current_user)
respond_to do |format|
...
end
end
Probably not as elegant as you were hoping, but it should do the job?
I'm trying to get a nested form view to update properly. This is however causing problems when the second form has existing data.
I'm using accepts_nested_attributes_for and nested_form_for. The second which only purpose is to dynamically add the form element using js. See github for more
The error I'm getting is:
Couldn't find Muscle with ID=3685340 for Exercise with ID=212831413
I've tried to manually do the updating but my code didnt really work and I'm under the impression that it shouldnt be needed since rails is suppose to take care of it under the hood.
The idea is that: Exercises has many Muscles through Targets
And from within the Exercise form I want to be able to add target muscles.
My models:
class Exercise < ActiveRecord::Base
has_many :targets, :dependent => :destroy
has_many :muscles, :through => :targets
accepts_nested_attributes_for :muscles, :reject_if => :all_blank
...
end
class Target < ActiveRecord::Base
belongs_to :exercise
accepts_nested_attributes_for :exercise, :update_only => true
belongs_to :muscle
end
class Muscle < ActiveRecord::Base
has_many :targets, :dependent => :destroy
has_many :exercises, :through => :targets
end
My (haml) view:
%p
%b Target(s):
= f.fields_for :muscles do |e|
= e.collection_select :id, Muscle.all, :id, :name
= e.link_to_remove "-remove"
= f.link_to_add "Add target muscle", :muscles
And finally my failing controller:
def update
#exercise = Exercise.find(params[:id])
#exercise.user = current_user
params[:exercise][:muscles_attributes].each { |id, muscle|
target = Target.where(:exercise_id => #exercise.id , :muscle_id => muscle[:id]).first
if target && !(muscle[:_destroy] == "false")
puts "!!>>>>>>>>>>>>>>>>>>destroy target #{target.exercise_id} #{target.muscle_id}"
target.destroy
else
if !target
t = #exercise.targets.build(:muscle_id => muscle[:id])
t.save
end
end
}
respond_to do |format|
if #exercise.update_attributes(params[:exercise])
format.html { redirect_to(#exercise, :notice => 'Exercise was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #exercise.errors, :status => :unprocessable_entity }
end
end
end
Please let me know if I should expose more of my code (the final result will be opensource anyway) ill happily push to github or whatever is requested, thanks in advance.
You could achieve this by manipulating the intermediate table, here targets.
Insert in your model:
accepts_nested_attributes_for :targets
And in your html, append this line with javascript:
<input name="exercise[targets_attributes][0][muscle_id]" value="the_muscle_id_goes_here" type="hidden">