This is a follow-up of my question: Rails 4 - Access Join Table Value in views
Now I know how to retrieve join table attributes and show them in view. But still I can't find the right approach to edit and update the attribute.
Models:
class Recipe < ActiveRecord::Base
has_many :recipe_ingredients
has_many :ingredients, through: :recipe_ingredients
end
class Ingredient < ActiveRecord::Base
has_many :recipe_ingredients
has_many :recipes, through: :recipe_ingredients
end
class RecipeIngredient < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
#there is an attribute t.text :amount
end
Recipe#Edit:
...
<%= simple_form_for #recipe do |f| %>
<div class="form-group">
<%= f.input :name, input_html: { class: "form-control"} %>
<%= f.input :description, input_html: { class: "form-control"} %>
<%= f.collection_select(:ingredient_ids, Ingredient.all, :id, :title, {}, {multiple: true}) %>
<!-- reserve for recipe_ingredients.amount -->
</div>
<%= f.submit "Submit", disable_with: 'Submitting...', class: "btn btn-primary"%>
<% end %>
...
As shown above, this is a many-to-many relationship, each recipe may have several ingredients. It works fine and I can choose the right models to associate with (using collection_select). But I have left the work to edit and update join table attributes undone. I have two ideas in my mind:
Make another edit page for editing join model attributes
Ajax? But not quite familiar with
I know the question seems to be trivial, but many solutions are out-dated(Rails 3). Desperate for a Rails 4 solution.
Edit
Intention: I would like to make the creation of Recipe and Ingredient models on their own, which is done. User will see which recipe using the ingredient in Ingredient#show action, which is done also. As to Recipe#show action, there is a slight difference, where user will see which ingredient it is using as well as the amount(join table attribute), which is done in my previous question. The last problem is, I would like to make this attribute editable.
You may want to look into doing nested models combined with the cocoon gem. This will allow you to have a form which updates multiple models at once and it takes care of all the ajax for you. https://github.com/nathanvda/cocoon. I used this gem on a system where the user needed to be able to add one or more answers to a trivia question via dynamic form fields. I think it could work for you as well with giving the user the ability to add one or many RecipeIngredient relations for a recipe. You would be able to add selects dynamically to your form via Cocoon containing a select with the Ingredient model records.
Related
Ok, I searched all over the web and found no answer.
I am looking for a way to display a name of a 'category' in the show view of a post (I have to mention I'm rookie in Rails).
I have....
a model "Post"
class Post < ActiveRecord::Base
has_many :categories
belongs_to :user
end
a model "Category"
class Category < ActiveRecord::Base
belongs_to :post
end
and the "show" view of the "post" has a line like this
<%= #post.category.name %>
The error message as screen shot:
NoMethodError in Posts#Show - undefined method `category' for #
The "show" action in "Posts" controller:
def show
#post = Post.find(params[:id])
end
I'm building this app along a little outdated training video on udemy. In this video there's in the category model a line with "attr_accessible"
class Category < ActiveRecord::Base
attr_accessible :name <---------------------- this
has_many :posts
end
...but this does no longer exists since Rails 4.0. Is there another way to retrieve the category name of the post?
Thank you in advance :-)
I got the answer. I found out, that every way, to get the data out of the table categories in the view for products won't work. I than thougt, showing the category in the category show view is simple working. With this idea in mind I took the same code, this one:
app/views/categories/show.html.erb
<p>
<strong>Name:</strong>
<%= #category.category_name %> <--------this line
</p>
...from the category show view and put it into the post show view. I than got again an error but different:
--> NoMethodError in Posts#show
Ok, this says the instance variable "#category" isn't available for the post show view. To change that was easy. I copied the object from the categories controller's show action into the posts controller's the show action. Like this:
class PostsController < ApllicationController
.
.
.
def show
#post = Post.find(params[:id])
#category = Category.find(params[:id])
end
And: it works!!!!
But now, is there something wrong to do it like this?
Cheers.
The method category not exists because the Post model has many "categories" not one "category". The Post should have the method "categories". Then if you want to show a first "category" of post in the view:
<%= #post.categories.first.name %>
If you want to show all "categories" of post, then you iterate the collection:
<% #post.categories.each do |category| %>
<%= category.name %>
<% end %>
I tried again and found the real error in my code. the foreign key was not set by Rails. I had to do manually. The table which has a "belongs_to" (in my case the posts table) needs a foreign key added (like category_id).
First creating the migration file:
rails g migration add_foreign_key_to_posts_table
Second adding the migration code to the migration file:
class AddForeignKeyToPostsTable < ActiveRecord::Migration
def change
add_foreign_key :posts, :categories
end
end
Third raking the db migration with:
rake db:migrate
Fourth adding the foreign key for other resources by following steps one to three. Now everything works fine.
I'm building a rails app that hosts games. Games belong to categories and thus each category can have many games.
I'm using the Friendly_id gem to generate URL slugs and have the following setup:
Category.rb
class Category < ActiveRecord::Base
extend FriendlyId
friendly_id :name_and_games, use: [:slugged]
has_many :games
def name_and_games
"#{name}-games"
end
end
Games_Controller.rb
...
def category
#category = Category.friendly.find(params[:id])
#categories = Category.all
#games = #category.games.page(params[:page])
render 'games/index'
end
...
Routes.rb
get ':friendly_id', to: "games#category", as: :category
Category_View.html.erb
<% categories.each do |category| %>
<%= link_to category_path(category) do %>
<span><%= pluralize(category.name.capitalize, "Game") %> (<%= category.games.count %>)</span>
<% end %>
<% end %>
The problem is that when I use Friendly_id's slugged module, Rails is generating my urls WITHOUT the "-games" suffix so I end up with URLS like this:
http://localhost:3000/action
http://localhost:3000/adventure
Is there some way to have rails keep the "-games" in my URLs and have it all play nicely such that the "-games" are dropped when it comes time for processing in the model?
Thank you.
So it's:
User.find_each{ |i| i.slug = nil; i.save!; }
Turns out the issue wasn't that Friendly_id wouldn't make the update but that the slug was not getting refreshed.
I had to drop into the Rails console and manually set the "slug" column to nil for each category. Once I did this, Friendly_id reset the "slug" column to reflect my additional text.
I am using custom fields in redmine. I need a set of custom fields to populate based upon how a user answers a question. for instance, if a user chooses "a" they get a series of 3 custom fields that pertain to "a" ..if a user chooses "b" they get a series of custom fields that pertain to "b" is this possible? any help would be great!
Are You search ready plugin or want to develop your own with neccesary functionality?
In case of develop You may pass selected field from view to controller as parameter. Then check which field was selected and set value to it from other parameter.
I think that somethng like this:
view
<%= form_tag ... do %>
<%= label_tag :selected_field %>
<% select_tag :selected_field, options_for_select(['field1', 'field2',...])
<%= label_tag :value %>
<% text_box_tag :value, value %>
<%= submit_tag 'save' %>
<% end %>
and controller method
def update
obj = SomeClass.find_by... # get your instance
case params[:selected_field]
when 'field1'
obj.field1 = params[:value]
when 'field2'
obj.field2 = params[:value]
end
obj.save
end
I have a project with partials associated with it. I am trying to create a selection box so that the user can select a parcel from the associated parcels to add to another model associated with the project. What I have below is my attempt that displays the parcels but simply returns the id ie I get
undefined method `each' for "64":String
With 64 being the parcel's ID.
I would also like to allow the user to select multiple parcels or no parcels.
<% #pro_par = #project.parcels %>
<%= f.input :parcels, :collection => #pro_par, :label_method =>:tax_parcel %>
How can I fixe this?
If you already have a associated model like
class Article < ActiveRecord::Base
has_many :parcels
# rest of the code
end
then you can directly call the associating models in the view using simple form
<%= simple_form_for #project do |f| %>
<!-- remaining codes -->
<%= f.association :parcels %>
<%= f.button :submit %>
<% end %>
it automatically lets you select multiple parcels.
Reference: https://github.com/plataformatec/simple_form#associations
I am using Cocoon gem to associate resume fields to one resume, and each user has ONE resume and have everything working the correct way via cocoon documentation. However, I would like the ability for users to be able to edit resume fields/nested models directly on the profile page without being redirected to the cocoon nested form page. Further more I would like users to have the ability to add and or delete a SINGLE field/entry. Is there any way at all to accomplish this?
In my console I have been able to successfully delete an entire resume nested model using
User.last.resume.resume_edus.destroy_all
Where 'resume.edus' is the nested model inside of resume complete with 3 other 'text_fields'. But as stated I would only like to be able to edit/delete a single instance of resume_edus. Any ideas?
User.rb
has_one :profile
has_one :resume
Resume.rb
belongs_to :user
has_many :resume_edus
accepts_nested_attributes_for :resume_edus,
reject_if: :all_blank,
allow_destroy: true
Resume_edu
belongs_to :resume
Resume Controller
params.require(:resume).permit(:user_id, :cover,
resume_edus_attributes:
[:id, :title, :date, :description, :_destroy])
Figured out the answer! I passed the resume_edus 'ID' in the delete action
<%= link_to "Delete", resume_path(r.id), method: :delete %>
Then was able to search for said ID in the current users resume_edu modal to specifically isolate and delete it without deleting the other instances of the model!
def destroy
#instance = current_user.resume.resume_edus.find(params[:id])
debugger
#instance.destroy
flash[:notice] = "Resume Field Was Deleted"
redirect_to profile_path(current_user)
end
accepts_nested_attributes_for :order_line_items, allow_destroy: true
<tr class="nested-fields">
<%= f.hidden_field :_destroy %>
<%= link_to_remove_association "Delete", f %>
</tr>
Add _destroy in controller params:
order_line_items_attributes: %i[id product_id quantity price discount total _destroy]