My Rails model 'Product' has a string attribute called 'Brand'. I am trying to create a list of links consisting of the unique brands I have as attributes in my products. I am able to list the unique brands, but need help setting up the routes/controller structure. In the StoreController I have a method 'brand' that should trigger the filtered #products based on my :brand parameter. It looks like this:
My StoreController:
def index
#brands = Product.uniq.pluck(:brand)
end
def brand
#products = Product.find(params[:brand])
render 'store/index'
end
My view:
<% #brands.each do |brand| %>
<%= link_to brand, brand_store_path(brand) %>
<% end %>
My routes.rb:
resource :store do
collection do
get ':brand' => 'store#brand', :as => 'brand'
end
end
I assume the structure of this is not right, as I am currently trying to set up URL consisting of the name (Sting) for each of the different brands, e.g: localhost:3000/store/brand1, localhost:3000/store/brand2 etc...
thanks in advance for any structural advice/guiding on how to get this right!
Related
A user can have multiple lists and a list can have multiple products
A product has a name and a date of last purchase
I am trying to add a button for each shopping list which on click it should update the last_purchase date with the current date for all the specific products added to the list already
This is what i have now
index.html.erb(in the list view folder) {each list has this button}
<%= button_to "Just-Shopped", just_shopped_product_path(...), :method => :put %>
routes.rb
resources :products do
member do
put 'just_shopped'
end
end
I know i am meant to create a function in the controller of list, but I am not sure how to select all products from the list ignoring the not selected ones and then updating that last_purchased field with the current date
This is a picture of how the rails console behaves when displaying products of a list
You're on the right track - first of all it looks like you want the button to apply to a list's products rather than an individual product, so let's change the route to:
resources :lists do
member do
put 'just_shopped'
end
end
end
Then in our lists_controller:
class ListsController < ApplicationController
...
def just shopped
list = List.find(params[:id])
list.products.each do |product|
product.update_attributes(last_purchased: DateTime.now)
end
end
That's our route and controller action setup, now we just need to add the correct button. I'm assuming you've got a #lists variable (or current_user.lists or something like that), and you're iterating through them as such:
<% #lists.each do |list| %>
<%# whatever html you want for each list %>
<%= button_to "Just-Shopped", just_shopped_list_path(list), :method => :put %>
end
You'll also need to figure out where you want to redirect to after you've updated the products in your controller
I am using acts-as-taggable-on to tag a Car model. I have three different tag contexts: Make, Color & Features. The first two Make & Color are predefined in an ENV variable and the last context is user generated(automatic windows, heated seats etc.)
What I'd like to do is make it so that from my index page Cars can be filtered by multiple tags at a time. So for instance, I'd like a series of checkboxes at the top of the index page a separate set for each context where a user can check Hyundai & Red and the index of cars would populate with only red Hyundais. At the moment I have a route and some code in my Cars Controller that allows me to filter by one tag but I'd like to modify it to filter by whatever a user selects.
routes.rb
get 'tags/:tags', to: 'cars#index', as: :tag
controller
def index
if params[:keyword].present?
#cars = Car.tagged_with(params[:keyword])
else
#cars = Car.all.order(:cached_weighted_score => :desc)
end
end
The #selected_tag is tags that have been selected as parameter in index page.
Controller
def index
if params[:keyword].present?
#selected_tag = params[:keyword]
#cars = Car.tagged_with(params[:keyword])
else
#cars = Car.all.order(:cached_weighted_score => :desc)
end
end
View
It's only prototype view so you have to combine with your own code.
<% #tags.each do |tag| %>
<div>
<%= check_box_tag "keywords[]", tag.name, #selected_tag.present? ? #selected_tag.include?(tag.name) : '' %>
<%= tag.name %>
</div>
<% end %>
I hope I can give a general overview with my description.
For more information to prepopulate data in checkbox
I'm adding a new model to my equasion and I'm wondering if there is a way to associate two models into one model then display any/all results within a view. For example, here is what I've currently have;
#tweet_category.order("position").each do |tweet|
<%= tweet.title %>
end
just a short example... now what if I added facebook into this. I was first thinking of creating a model thats named stuff then associate it to tweet_category and facebook_category like so;
class Stuff < ActiveRecord::Base
attr_accessible :title
belongs_to :user
has_many :tweet_category
has_many :facebook_category
end
Now in my controller I'm guessing I would do the following;
class StuffController < ApplicationController
def index
#stuff_list = Stuff.find(:all)
end
end
and in my view I would just simply do the following from above view;
#stuff_list.order("position").each do |stuff|
<%= stuff.title %>
end
am I understanding the logic here??? would that work having two models / two tables db.. etc..
First of all, I don't understand why you would need that "stuff" model. It belongs to users and has_many tweet_category and facebook_category, and just does nothing but offering a "title", when your User model could do the job ( I mean, each user could have many tweets and fb category, instead of having one or several "stuff" which has/have many of them ).
Anyway, if you want to make links between your models and then display everything in a view, first in your User model you just have to do :
class User < ActiveRecord::Base
...
has_many :facebook_categories #( I don't know how rails would pluralize it, btw, I'm just making an assumption )
has_many :tweeter_categories
end
and
class Facebook_category
...
belongs_to :user
end
and do the same fot the tweeter category
Then in your controller :
def show_everything #Here it's a custom action, but you can call it wherever you want
#users = User.all
end
And finally in your view :
<% #users.each do |user| %>
<% user.facebook_categories.all.each do |fb_c| %>
<%= fb_c.title %>
<% end %>
<% user.tweeter_categories.all.each do |t_c| %>
<%= t_c.title %>
<% end %>
<% end %>
Maybe just try to grab a better name for your models, so the pluralization doesn't get messy ( and I saw that the ".all" method is deprecated, so maybe replace it with something
Hope it helps !
Edit :
Basically, when you're doing
#users = User.all
What rails' doing is putting every hash defining every "User" in an array. So, if you want to mix two tables' arrays inside a single array, you can do something like this :
#categories = [] << Facebook_category.all, Tweeter_category.all
You will then have an array ( #category ), filled with 2 arrays ( one ActiveRecord relation for Facebook_category and one for Tweeter_category ). Themselves filled with hashes of their model. So, what you need to do is :
#categories.flatten!
Here's the API for what flatten does ( basically removing all your nested arrays inside your first tarray )
Now, you got a single array of hashes, being the informations from both your model's instances. And, if these informations can be ordered, in your view, you just have to :
<% #categories.order("updated_at").each do |i| %>
<%= i.title %>
<% end %>
I'm building a martial arts related database, currently I have the following associations set up:
Student has_and_belongs_to_many :styles
Style has_many :ranks
Student has_many :ranks, through: :gradings (and vice versa)
I'm generating a form as follows, depending on the student's styles:
So the headings are generated by the Style model (Tai Chi, Karate...), then their rankings listed below (taken from the Rank model), and the "Dojo" and "Date" fields should belong to the Grading model once created.
The question: I know how to build a form that creates one association (or one association + its children), but how do I build a form that creates multiple associations at once?
Also, what would be a clean way to implement the following:
Only lines which are ticked become associations
Dojo and date must be filled in for ticked lines to save successfully
If a line is unticked it will destroy any previously created associations
This is what I've currently implemented to retrieve the correct records:
class GradingsController < ApplicationController
before_filter :authenticate_sensei!
def index
#student = Student.includes(:styles).find(params[:student_id])
#ranks = Rank.for_student_styles(#student)
split_ranks_by_style
end
private
def split_ranks_by_style
#karate = #ranks.select_style("Karate")
#tai_chi = #ranks.select_style("Tai Chi")
#weaponry = #ranks.select_style("Weaponry")
end
end
# Rank model
def self.for_student_styles(student)
includes(:style).where("styles.id in (?)", student.styles.map(&:id))
end
def self.select_style(style)
all.map { |r| r if r.style.name == style }.compact
end
Complicated forms like this are best handled in a service object initiated in the primary resource's create or update action. This allows you to easily find where the logic is happening afterwards. In this case it looks like you can kick off your service object in your GradingsController. I also prefer formatting a lot of the data in the markup, to make the handling easier in the service object. This can be done a'la rails, by passing a name like "grade[style]" and "grade[rank]". This will format your params coming in as a convenient hash: {grade: {style: "karate", rank: "3"}}. That hash can be passed to your service object to be parsed through.
Without really grasping the full extent of your specific requirements, let's put together an example form:
<%= form_for :grading, url: gradings_path do |f| %>
<h1><%= #rank.name %></h1>
<%- #grades.each do |grade| %>
<div>
<%= hidden_field_tag "grade[#{grade.id}][id]", grade.id %>
<%= check_box_tag "grade[#{grade.id}][active]" %>
...
<%= text_field_tag "grade[#{grade.id}][date]" %>
</div>
<%- end %>
<%= submit_tag %>
<%- end %>
With a form like this, you get your params coming into the controller looking something like this:
"grade"=>{
"1"=>{"id"=>"1", "active"=>"1", "date"=>"2013-06-21"},
"3"=>{"id"=>"3", "date"=>"2013-07-01"}
}
Nicely formatted for us to hand off to our service object. Keeping our controller nice and clean:
class GradingsController < ApplicationController
def index
# ...
end
def create
builder = GradeBuilder.new(current_user, params['grade'])
if builder.run
redirect_to gradings_path
else
flash[:error] = 'Something went wrong!' # maybe even builder.error_message
render :action => :index
end
end
end
So now we just need to put any custom logic into our builder, I'd probably recommend just making a simple ruby class in your /lib directory. It could look something like this:
class GradeBuilder
attr_reader :data, :user
def self.initialize(user, params={})
#user = user
#data = params.values.select{|param| param['active'].present? }
end
def run
grades = data.each{|entry| build_grade(entry)}
return false if grades.empty?
end
private
def build_grade(entry)
grade = Grade.find(entry['id'])
rank = grade.rankings.create(student_id: user, date: entry['date'])
end
end
There will obviously need a lot more work to pass all the specific data you need from the form, and extra logic in the GradeBuilder to handle edge cases, but this will give you a framework to handle this problem in a maintainable and extensible way.
I have a table of venues and a table of areas, where a venue belongs to an area and an area has many venues.
How can I show all the venues which belong to an area when I view the areas show page?
I thought this would work:
area show.html.erb:
<%= area.venue.name %>, or
<%= area.venue.name, :collection => #area.venues %>
routes:
resources :areas, :has_many => :venues
but it gives an "undefined local variable or method `area'" error or a syntax error.
I'm super new to any programming and rails what am I doing wrong?
Also, I have a venue partial set up but it's being displayed in another part of my app, I would just like the venue names listed without using partials.
Thanks very much for any help its much appreciated!
First, can you show us your areas_controller.rb file please?
Inside your view you can do this by doing:
<% #area.venues.each do |venue| %>
<%= venue.name %>
# etc.
<% end %>
This implies that inside your areas controller, you have a show action that instantiates the #area instance variable.
Something like:
def show
#area = Area.find(params[:id])
end
And by the way, don't put your model relations inside the routes.rb file! You need to put them inside your models.
Area.rb
class Area < ActiveRecord::Base
has_many :venues
end
Venue.rb
class Venue < ActiveRecord::Base
belongs_to :area
end