Rails Unidentified Method Issue: undefined method `outlet_id' - ruby-on-rails

In my database I am trying to get a one to many relationship between outlets and articles.
I am getting the following error when that relationship is used:
undefined method `outlet_id' for #<Article:0x007fc353887e58>
Here are the models:
class Article < ActiveRecord::Base
belongs_to :analyst
belongs_to :outlet
has_and_belongs_to_many :loe
attr_accessible :article_body, :author, :distribution, :loe, :most_important, :pubdate, :publication, :state, :submitted, :summary, :title, :url, :analyst_id, :loe_ids, :outlet_id
end
class Outlet < ActiveRecord::Base
has_many :articles, foreign_key: :title
attr_accessible :distribution, :name, :state, :article_ids
end
Here are the schema:
create_table "articles_loes", :id => false, :force => true do |t|
t.integer "article_id"
t.integer "loe_id"
end
create_table "loes", :force => true do |t|
t.string "name"
t.string "customer"
t.integer "article_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "loes", ["article_id"], :name => "index_loes_on_article_id"
create_table "outlets", :force => true do |t|
t.string "name"
t.integer "articles_id"
t.integer "distribution"
t.string "state"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "outlets", ["articles_id"], :name => "index_outlets_on_articles_id"
And here is the chunk of the view that calls on :outlet :
<div class="span4">
<%= f.association :loe %>
<%= f.association :outlet %>
</div>
If anyone has any ideas I'd really appreciate them. I think I might need an index of Outlets in Article? I'm not really sure how to implement that if that is the case. Thanks in advance.

Right now there is no way for your Outlet model to associate with the articles that it has. Once you say belongs_to, you need to have an outlet_id column. So you need to add an outlet_id (integer) column to your Article model and populate it with the id of the outlet they belong to. If an Article can belong to many outlets in that case you need to create a many-to-many relationship through a joint table.

Related

Rails 4 Nested Form

I have three models:
class Item < ActiveRecord::Base
has_many :item_points
has_many :groups, through: :item_points
accepts_nested_attributes_for :item_points
end
class ItemPoint < ActiveRecord::Base
belongs_to :group
belongs_to :item
accepts_nested_attributes_for :group
end
class Group < ActiveRecord::Base
has_many :item_points
has_many :items, through: :item_points
end
The schema for items
create_table "items", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The schema for item_points
create_table "item_points", force: :cascade do |t|
t.decimal "points", null: false
t.integer "item_id", null: false
t.integer "group_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
The schema for groups
create_table "groups", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
In my groups table, I've created a number of rows, e.g. group 1 and group 2.
In the form for creating items I'd really like to see a field each for group 1 and group 2, so that I might be able to enter the points for that item. e.g. In item X, group 1 is worth 10 points, and group 2 is worth 5 points.
EDIT Added the form
The form:
<%= form_for(#item) do |item_form| %>
<div class="form-group">
<%= item_form.label :name %>
<%= item_form.text_field :name, :class => 'form-control' %>
</div>
<%= item_form.fields_for(:groups) do |groups_form| %>
<% group = groups_form.object_id.to_s%>
<%= groups_form.hidden_field :id %>
<%= groups_form.fields_for(:item_point) do |entity_form| %>
<%= entity_form.text_field :points %>
<% end %>
<% end %>
This provides me with a form, which contains one extra entry box, called item[groups][item_point][points], and has no label.
What I'd like to know is how do I get all of the rows I've added into groups as fields into a Rails Form? And when I do, how do I save the associated item_points data using strong parameters?
I've spent quite some time looking for an answer, and I can't seem to find anything other than a series of StackOverflow questions, which don't quite seem to have the same problem as me.
All help is wonderfully appreciated.
There's a helpful post with some examples at: https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through. It specifically talks about adding inverse_of on your associations.
In your view you'll need to use fields_for. You could (for example) put that in a table or a list and have each entry be a row.
If you share what you've tried in your view so far you may be able to get a more detailed response if you need it.
As for permitted_params in your controller, you can nest them something like:
def permitted_params
params.permit(item: [
:name,
item_points_attributes: [
:id,
:points,
:group_id,
]
)
end
Update:
Rather than fields_for(:groups) I think you want your controller to build the models for all the item_points (#item_points = Group.all.collect {|group| ItemPoint.new({group_id: group.id, item_id: #item.id}).
Then you can use a fields_for(:item_points, #item_points).
You can add a label for the field so it's not just an unlabeled field using the HTML label tag.

One to Many Relationship: List of many not showing up

I have a simple one to many relationship mapping users to posts. Here is the relevant part of the schema:
create_table "users", :force => true do |t|
t.string "username"
t.string "first_name"
t.string "last_name"
t.string "email"
t.string "password"
t.string "status", :default => "User"
t.string "img_url"
t.text "bio"
t.integer "num_posts", :default => 0
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "posts", :force => true do |t|
t.string "subject"
t.text "body"
t.integer "user_id"
t.integer "section_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
And here are the models:
class User < ActiveRecord::Base
attr_accessible :bio, :email, :first_name, :img_url, :last_name, :num_posts, :password, :status, :username
has_many :posts
has_many :comments
end
class Post < ActiveRecord::Base
attr_accessible :body, :section_id, :subject, :tag_ids, :user_id
belongs_to :user
belongs_to :section
has_and_belongs_to_many :tags
has_many :comments
end
I go into the rails console and create a new user doing User.create(attributes) and a new post doing Post.create(some attributes), assinging them to p1 and u1, respectively, then I do p1.user = u1.
Now when I do p1.user, I get a u1 object. Moreover, I can see that the user_id key is set to the key of u1 in the DB. However, when I do u1.posts, I get an empty list. How can I get a list of all of the posts that belong to a given user?
Ideally, when creating posts, you can create like this:
user.posts.create!({attributes})
Here in your case it could be the problem with association caching. Try
u1.reload.posts

rails self join

I want a user to be able to create a challenge (challenges_created) and other users to be able to offer support to achieve them (challenges_supported). I tried to do this with a self joined challenge model with its resources nested beneath the users resource. I currently have models:
class User < ActiveRecord::Base
attr_accessible :name, :supporter_id, :challenger_id
has_many :challenges_created, :class_name => 'Challenge', :foreign_key => :challenger_id
has_many :challenges_supported, :class_name => 'Challenge', :foreign_key => :supporter_id
end
and
class Challenge < ActiveRecord::Base
attr_accessible :challenger, :completion_date, :description, :duration, :status, :supporter, :title
belongs_to :challenger, :class_name => 'User'
has_many :supporters, :class_name => 'User'
end
I think that I would need full CRUD and corresponding views both for when users are creating challenges and when they are supporting them. Because of this, I created 2 controllers named challenges_created_controller and challenges_supported_controller.
My routes.rb file is:
resources :users do
resources :challenges_created
resources :challenges_supported
end
The problem that I am encountering with this setup is that when I try to create a new challenge at
http://localhost:3000/users/3/challenges_created/new
I receive the message
Showing /home/james/Code/Rails/test_models/app/views/challenges_created/_form.html.erb where line #1 raised:
undefined method `user_challenges_path' for #<# <Class:0x007fb154de09d8>:0x007fb1500c0f90>
Extracted source (around line #1):
1: <%= form_for [#user, #challenge] do |f| %>
2: <% if #challenge.errors.any? %>
The result is the same for the edit action too. I have tried many things but if I were to reference #challenge_created in the form_for then it is not matching the Challenge model.
Can anybody please advise on how what I am doing wrong. Thank you in advance. My schema is:
create_table "users", :force => true do |t|
t.string "name"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "challenger_id"
t.integer "supporter_id"
end
create_table "challenges", :force => true do |t|
t.string "title"
t.text "description"
t.integer "duration"
t.date "completion_date"
t.string "status"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "challenger_id"
t.integer "supporter_id"
end
I think the problem is that you have a challenge_created controller, but you do not have model for it. In you form you specify a user and a challenge so rails tries to find a controller for challenge, not challenge_created. Rails thinks that for a model you have a controller named based on the convention.
I recommend you not to create two different controllers for challenges. Use only one and differenciate on actions. E.g. ou can create a list_created and list_supported action in challenges.

unknown attribute: user_id

I'm getting the error unknown attribute: user_id durring execution of current_user.stories.build
class User < ActiveRecord::Base
has_many :stories, class_name: 'Story', foreign_key: 'user_id', dependent: :destroy
...
class Story < ActiveRecord::Base
belongs_to :user, class_name: 'User', foreign_key: 'user_id'
...
schema.rb
create_table "stories", :force => true do |t|
t.string "responsible"
t.string "descr"
t.string "state"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "email"
t.string "password_digest"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "name"
end
It doesn't contain 'user_id' field. Any ideas?
Kulbir is correct that you need to define a user_id column in your stories table, but doesn't explain the way to do that.
The correct way to make that change is to create a new migration. By convention, it should be called add_user_id_to_stories and would be created as follows (assuming you're using Rails 3+):
rails generate migration add_user_id_to_stories
If you run that, it should actually generate a migration that already contains the change you need to make, which should be something like:
add_column :stories, :user_id, :integer
As an aside when you're following the Rails conventions concerning association naming, which you are, you can actually skip a lot of the extra specification. In the User model, you can specify just has_many :stories and in the Story model specify belongs_to :user. Rails will assume the same class names and foreign keys you've specified.
You should have a user_id field in your stories table like below to define the association in your models.
create_table "stories", :force => true do |t|
t.integer "user_id"
t.string "responsible"
t.string "descr"
t.string "state"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
...
end
Edit
Check Emily's answer for detailed explanation.
you should use the new syntax and pass the fieldtype as symbol
add_column :stories, :user_id, :integer

Why is rails not finding my table relation?

class Product < ActiveRecord::Base
has_many :models, :dependent => :destroy, :order => 'display, title'
class Model < ActiveRecord::Base
belongs_to :product
class GsCollector < ActiveRecord::Base
belongs_to :model
Why can't I do the following in my form for GsCollector?:
<p>
Model:<br />
<%= collection_select :gs_collector, :model_id, Product.where("title = 'Some Title'").models.all, :id, :title %>
</p>
I get the error:
undefined method `models' for #<ActiveRecord::Relation:0x007fef0ac09350>
Shouldn't the models method be provided by the relation? In the console, this works:
p = Product.find(4).models
But this doesn't:
p = Product.where("title = 'some title'").models
Not sure what the difference is....
Here's my schema:
create_table "gs_collectors", :force => true do |t|
t.integer "project_id"
t.integer "model_id"
t.integer "quantity", :default => 1
t.string "housing", :default => "Base Unit"
t.string "hopper"
t.string "controller"
t.boolean "overbags", :default => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "models", :force => true do |t|
t.string "title"
t.integer "product_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "display"
end
create_table "products", :force => true do |t|
t.string "title"
t.datetime "created_at"
t.datetime "updated_at"
end
You are returning an array of objects, collectively called a ActiveRecord::Relation. This is due to your where search term. Maybe you want something like the following:
p = Product.find_by_title('some title').models
where returns a list of Products
find returns a single Product
You need to define the relationship between Model and GsCollector both ways. You forgot the part in the Model:
class Model < ActiveRecord::Base
belongs_to :product
has_many :gs_collectors
end
class GsCollector < ActiveRecord::Base
belongs_to :model
end
And the real problem is that you can .models only on a single record. Product.where returns several ones - so use Product.find_by_title("title").models

Resources